web-dev-qa-db-fra.com

Comment puis-je générer des listes sous forme de tableau dans le cahier Jupyter?

Je sais que j'ai déjà vu un exemple quelque part, mais je ne le trouve pas pour la vie en cherchant dans Google.

J'ai quelques lignes de données:

data = [[1,2,3],
        [4,5,6],
        [7,8,9],
        ]

Et je veux sortir ces données dans un tableau, par exemple.

+---+---+---+
| 1 | 2 | 3 |
+---+---+---+
| 4 | 5 | 6 |
+---+---+---+
| 7 | 8 | 9 |
+---+---+---+

Évidemment, je pourrais utiliser une bibliothèque comme prettytable ou télécharger des pandas ou quelque chose du genre, mais je suis très désintéressé de le faire.

Je veux simplement sortir mes lignes en tant que tables dans la cellule de mon carnet Jupyter. Comment puis-je faire cela?

49
Wayne Werner

J'ai finalement retrouvé la documentation jupyter/IPython que je cherchais.

J'avais besoin de ça:

from IPython.display import HTML, display

data = [[1,2,3],
        [4,5,6],
        [7,8,9],
        ]

display(HTML(
   '<table><tr>{}</tr></table>'.format(
       '</tr><tr>'.join(
           '<td>{}</td>'.format('</td><td>'.join(str(_) for _ in row)) for row in data)
       )
))

(J'ai peut-être un peu gâché la compréhension, mais display(HTML('some html here')) est ce dont nous avions besoin)

41
Wayne Werner

Je viens de découvrir que tabulate a une option HTML et est assez simple à utiliser.
Assez similaire à la réponse de Wayne Werner:

from IPython.display import HTML, display
import tabulate
table = [["Sun",696000,1989100000],
         ["Earth",6371,5973.6],
         ["Moon",1737,73.5],
         ["Mars",3390,641.85]]
display(HTML(tabulate.tabulate(table, tablefmt='html')))

Vous recherchez toujours quelque chose de simple à utiliser pour créer des dispositions de tableau plus complexes, comme la syntaxe et le formatage en latex, pour fusionner des cellules et effectuer une substitution de variable dans un cahier:
Autoriser les références aux variables Python dans les cellules de Markdown # 2958

47
ruffsl

Il y a un bon truc: encapsuler les données avec pandas DataFrame.

import pandas as pd
data = [[1, 2], [3, 4]]
pd.DataFrame(data, columns=["Foo", "Bar"])

Il affiche des données comme:

  | Foo | Bar |
0 | 1   | 2   |
1 | 3   | 4   |
24
Anton Dergunov

tabletext convient parfaitement

import tabletext

data = [[1,2,30],
        [4,23125,6],
        [7,8,999],
        ]

print tabletext.to_text(data)

résultat:

┌───┬───────┬─────┐
│ 1 │     2 │  30 │
├───┼───────┼─────┤
│ 4 │ 23125 │   6 │
├───┼───────┼─────┤
│ 7 │     8 │ 999 │
└───┴───────┴─────┘
6
number5

Ok, donc c'était un peu plus dur que je ne le pensais:

def print_matrix(list_of_list):
    number_width = len(str(max([max(i) for i in list_of_list])))
    cols = max(map(len, list_of_list))
    output = '+'+('-'*(number_width+2)+'+')*cols + '\n'
    for row in list_of_list:
        for column in row:
            output += '|' + ' {:^{width}d} '.format(column, width = number_width)
        output+='|\n+'+('-'*(number_width+2)+'+')*cols + '\n'
    return output

Cela devrait fonctionner pour un nombre variable de lignes, de colonnes et de chiffres (pour les nombres)

data = [[1,2,30],
        [4,23125,6],
        [7,8,999],
        ]
print print_matrix(data)
>>>>+-------+-------+-------+
    |   1   |   2   |  30   |
    +-------+-------+-------+
    |   4   | 23125 |   6   |
    +-------+-------+-------+
    |   7   |   8   |  999  |
    +-------+-------+-------+
2
tglaria

Un ensemble de fonctions à usage général permettant de restituer toute structure de données Python (dict et listes imbriquées) au format HTML.

from IPython.display import HTML, display

def _render_list_html(l):
    o = []
    for e in l:
        o.append('<li>%s</li>' % _render_as_html(e))
    return '<ol>%s</ol>' % ''.join(o)

def _render_dict_html(d):
    o = []
    for k, v in d.items():
        o.append('<tr><td>%s</td><td>%s</td></tr>' % (str(k), _render_as_html(v)))
    return '<table>%s</table>' % ''.join(o)

def _render_as_html(e):
    o = []
    if isinstance(e, list):
        o.append(_render_list_html(e))
    Elif isinstance(e, dict):
        o.append(_render_dict_html(e))
    else:
        o.append(str(e))
    return '<html><body>%s</body></html>' % ''.join(o)

def render_as_html(e):
    display(HTML(_render_as_html(e)))
2
Hardest

Vous pouvez essayer d'utiliser la fonction suivante

def tableIt(data):
    for lin in data:
        print("+---"*len(lin)+"+")
        for inlin in lin:
            print("|",str(inlin),"", end="")
        print("|")
    print("+---"*len(lin)+"+")

data = [[1,2,3,2,3],[1,2,3,2,3],[1,2,3,2,3],[1,2,3,2,3]]

tableIt(data)
2
Taoufik BELKEBIR

J'ai déjà eu le même problème. Je ne pouvais rien trouver qui puisse m'aider alors j'ai fini par créer la classe PrintTable-- ci-dessous. Il y a aussi une sortie. L'utilisation est simple:

ptobj = PrintTable(yourdata, column_captions, column_widths, text_aligns)
ptobj.print()

ou sur une ligne:

PrintTable(yourdata, column_captions, column_widths, text_aligns).print()

Sortie:

-------------------------------------------------------------------------------------------------------------
  Name                                     | Column 1   | Column 2   | Column 3   | Column 4   | Column 5    
-------------------------------------------------------------------------------------------------------------
  Very long name 0                         |          0 |          0 |          0 |          0 |          0  
  Very long name 1                         |          1 |          2 |          3 |          4 |          5  
  Very long name 2                         |          2 |          4 |          6 |          8 |         10  
  Very long name 3                         |          3 |          6 |          9 |         12 |         15  
  Very long name 4                         |          4 |          8 |         12 |         16 |         20  
  Very long name 5                         |          5 |         10 |         15 |         20 |         25  
  Very long name 6                         |          6 |         12 |         18 |         24 |         30  
  Very long name 7                         |          7 |         14 |         21 |         28 |         35  
  Very long name 8                         |          8 |         16 |         24 |         32 |         40  
  Very long name 9                         |          9 |         18 |         27 |         36 |         45  
  Very long name 10                        |         10 |         20 |         30 |         40 |         50  
  Very long name 11                        |         11 |         22 |         33 |         44 |         55  
  Very long name 12                        |         12 |         24 |         36 |         48 |         60  
  Very long name 13                        |         13 |         26 |         39 |         52 |         65  
  Very long name 14                        |         14 |         28 |         42 |         56 |         70  
  Very long name 15                        |         15 |         30 |         45 |         60 |         75  
  Very long name 16                        |         16 |         32 |         48 |         64 |         80  
  Very long name 17                        |         17 |         34 |         51 |         68 |         85  
  Very long name 18                        |         18 |         36 |         54 |         72 |         90  
  Very long name 19                        |         19 |         38 |         57 |         76 |         95  
-------------------------------------------------------------------------------------------------------------

Le code de la classe PrintTable

# -*- coding: utf-8 -*-

# Class
class PrintTable:
    def __init__(self, values, captions, widths, aligns):
    if not all([len(values[0]) == len(x) for x in [captions, widths, aligns]]):
        raise Exception()
    self._tablewidth = sum(widths) + 3*(len(captions)-1) + 4
    self._values = values
    self._captions = captions
    self._widths = widths
    self._aligns = aligns

    def print(self):
    self._printTable()

    def _printTable(self):
    formattext_head = ""
    formattext_cell = ""
    for i,v in enumerate(self._widths):
        formattext_head += "{" + str(i) + ":<" + str(v) + "} | "
        formattext_cell += "{" + str(i) + ":" + self._aligns[i] + str(v) + "} | "
    formattext_head = formattext_head[:-3]
    formattext_head = "  " + formattext_head.strip() + "  "
    formattext_cell = formattext_cell[:-3]
    formattext_cell = "  " + formattext_cell.strip() + "  "

    print("-"*self._tablewidth)
    print(formattext_head.format(*self._captions))
    print("-"*self._tablewidth)
    for w in self._values:
        print(formattext_cell.format(*w))
    print("-"*self._tablewidth)

Manifestation

# Demonstration

headername = ["Column {}".format(x) for x in range(6)]
headername[0] = "Name"
data = [["Very long name {}".format(x), x, x*2, x*3, x*4, x*5] for x in range(20)] 

PrintTable(data, \
       headername, \
       [70, 10, 10, 10, 10, 10], \
       ["<",">",">",">",">",">"]).print()
1
Celdor

Je veux sortir un tableau où chaque colonne a la plus petite largeur possible, Où les colonnes sont complétées par un espace (mais cela peut être modifié) et les lignes sont séparées par des nouvelles lignes (mais cela peut être changé) et où chaque élément mis en forme avec str (mais ...).


def ftable(tbl, pad='  ', sep='\n', normalize=str):

    # normalize the content to the most useful data type
    strtbl = [[normalize(it) for it in row] for row in tbl] 

    # next, for each column we compute the maximum width needed
    w = [0 for _ in tbl[0]]
    for row in strtbl:
        for ncol, it in enumerate(row):
            w[ncol] = max(w[ncol], len(it))

    # a string is built iterating on the rows and the items of `strtbl`:
    #   items are  prepended white space to an uniform column width
    #   formatted items are `join`ed using `pad` (by default "  ")
    #   eventually we join the rows using newlines and return
    return sep.join(pad.join(' '*(wid-len(it))+it for wid, it in Zip(w, row))
                                                      for row in strtbl)

La signature de fonction, ftable(tbl, pad=' ', sep='\n', normalize=str), avec ses arguments par défaut, a pour but de fournir une flexibilité maximale.

Vous pouvez personnaliser

  • la colonne pad Ding,
  • la ligne sep arator, (par exemple, pad='&', sep='\\\\\n' pour avoir le volume d'une table LaTeX)
  • la fonction à utiliser pour normaliser l'entrée dans une chaîne commune format --- par défaut, pour la généralité maximale, elle est str mais sivous savez que toutes vos données sont la virgule flottante lambda item: "%.4f"%item pourrait être un choix raisonnable, etc.

Essais superficiels:

J'ai besoin de quelques données de test, impliquant éventuellement des colonnes de différentes largeurs. Ainsi, l'algorithme doit être un peu plus sophistiqué (mais juste un peu;)

In [1]: from random import randrange

In [2]: table = [[randrange(10**randrange(10)) for i in range(5)] for j in range(3)]

In [3]: table
Out[3]: 
[[974413992, 510, 0, 3114, 1],
 [863242961, 0, 94924, 782, 34],
 [1060993, 62, 26076, 75832, 833174]]

In [4]: print(ftable(table))
974413992  510      0   3114       1
863242961    0  94924    782      34
  1060993   62  26076  75832  833174

In [5]: print(ftable(table, pad='|'))
974413992|510|    0| 3114|     1
863242961|  0|94924|  782|    34
  1060993| 62|26076|75832|833174
0
gboffi

Ici, j'ai écrit l'abstraction Pythonic. Code sans tracas. :) 

jupyter_table_class.py

0
crook

J'ai récemment utilisé prettytable pour le rendu d'une table Nice ASCII. Il est similaire à la sortie CLI postgres.

import pandas as pd
from prettytable import PrettyTable

data = [[1,2,3],[4,5,6],[7,8,9]]
df = pd.DataFrame(data, columns=['one', 'two', 'three'])

def generate_ascii_table(df):
    x = PrettyTable()
    x.field_names = df.columns.tolist()
    for row in df.values:
        x.add_row(row)
    print(x)
    return x

generate_ascii_table(df)

Sortie:

+-----+-----+-------+
| one | two | three |
+-----+-----+-------+
|  1  |  2  |   3   |
|  4  |  5  |   6   |
|  7  |  8  |   9   |
+-----+-----+-------+
0
AlexG