¿Cómo puedo generar listas como una tabla en el cuaderno Jupyter?

80

Sé que he visto algún ejemplo en alguna parte antes, pero por mi vida no puedo encontrarlo cuando busco en Google.

Tengo algunas filas de datos:

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

Y quiero generar estos datos en una tabla, por ejemplo

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

Obviamente, podría usar una biblioteca como prettytable o descargar pandas o algo así, pero no estoy muy interesado en hacer eso.

Solo quiero generar mis filas como tablas en la celda de mi cuaderno Jupyter. ¿Cómo hago esto?

Wayne Werner
fuente
¿Quieres usar solo printfunciones? Son los números fijos de ancho (1 dígito, tres dígitos?
tglaria
Aquí escribí abstracción pitónica. Codifique sin problemas. :) jupyter_table_class.py
not_python

Respuestas:

85

Acabo de descubrir que tabular tiene una opción HTML y es bastante simple de usar.
Muy similar a la respuesta 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')))

Sigo buscando algo simple de usar para crear diseños de tablas más complejos, como la sintaxis de látex y el formato para fusionar celdas y hacer sustitución de variables en un cuaderno:
Permita referencias a variables de Python en celdas de Markdown # 2958

ruffl
fuente
¡Alinear cuerdas no funcionó para mí! ¡No alinea la cuerda a la izquierda!
Mojtaba Khodadadi
@MojtabaKhodadadi no lo ha verificado de cerca, pero parece que puede establecer el argumento de columna predeterminado para srtings vs números aquí .
ruffsl
Hoy en día, incluso tabulate.tabulate(table, tablefmt='html')parece funcionar (probé Jupyter 6.0.3, JupyterLab 2.0.1). ¡Agradable!
zonksoft
82

Hay un buen truco: envuelve los datos con pandas DataFrame.

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

Muestra datos como:

  | Foo | Bar |
0 | 1   | 2   |
1 | 3   | 4   |
Anton Dergunov
fuente
14
Como alguien que ama absolutamente Python para todo, PERO la ciencia de datos, me entristece REALMENTE ver que las respuestas de llamadas de función triple, importación cuádruple y nueve líneas reciben votación positiva cuando la respuesta MEJOR es literalmente "un DataFrame de pandas". Mi heurística es: "Si es largo, probablemente esté mal".
one_observation
1
Incluso puede mostrar el DataFrame como HTML usando to_html(), consulte stackoverflow.com/a/29665452/2866660
wvengen
¡Gracias! Sí, la respuesta aceptada definitivamente debería cambiarse a esta.
Helen
59

Finalmente encontré la documentación de jupyter / IPython que estaba buscando.

Necesitaba esto:

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)
       )
))

(Puede que haya estropeado un poco las comprensiones, pero display(HTML('some html here'))es lo que necesitábamos)

Wayne Werner
fuente
13

tabletext encaja bien

import tabletext

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

print tabletext.to_text(data)

resultado:

┌───┬───────┬─────┐
│ 1230 │
├───┼───────┼─────┤
│ 4231256 │
├───┼───────┼─────┤
│ 78999 │
└───┴───────┴─────┘
número 5
fuente
4

Si no le importa usar un poco de html, algo como esto debería funcionar.

from IPython.display import HTML, display

def display_table(data):
    html = "<table>"
    for row in data:
        html += "<tr>"
        for field in row:
            html += "<td><h4>%s</h4><td>"%(field)
        html += "</tr>"
    html += "</table>"
    display(HTML(html))

Y luego úsalo así

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

ingrese la descripción de la imagen aquí

Satyajit
fuente
2

Puedes intentar usar la siguiente función

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)
Taoufik BELKEBIR
fuente
2

Ok, esto fue un poco más difícil de lo que pensé:

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

Esto debería funcionar para un número variable de filas, columnas y número de dígitos (para números)

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

Un conjunto de funciones de propósito general para representar cualquier estructura de datos de Python (dictados y listas anidadas juntas) como 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)))
Más difícil
fuente
1

Yo solia tener el mismo problema. No pude encontrar nada que me ayudara, así que terminé haciendo la clase: PrintTablecódigo a continuación. También hay una salida. El uso es simple:

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

o en una línea:

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

Salida:

-------------------------------------------------------------------------------------------------------------
  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  
-------------------------------------------------------------------------------------------------------------

El código de la clase 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)

Demostración

# 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()
Celdor
fuente
1

Recientemente utilicé prettytablepara renderizar una bonita tabla ASCII. Es similar a la salida CLI de 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)

Salida:

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

Quiero generar una tabla donde cada columna tiene el ancho más pequeño posible, donde las columnas se rellenan con espacios en blanco (pero esto se puede cambiar) y las filas están separadas por líneas nuevas (pero esto se puede cambiar) y donde cada elemento se formatea usando str( pero...).


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 firma de la función ftable(tbl, pad=' ', sep='\n', normalize=str), con sus argumentos predeterminados está destinada a proporcionar la máxima flexibilidad.

Puedes personalizar

  • la almohadilla de la columna ding,
  • la fila septiembre arator, (por ejemplo, pad='&', sep='\\\\\n'para tener la mayor parte de una mesa de látex)
  • la función que se utilizará para normalizar la entrada a un formato de cadena común --- por defecto, para la máxima generalidad es, strpero si sabe que todos sus datos son de punto flotante lambda item: "%.4f"%itempodría ser una opción razonable, etc.

Pruebas superficiales:

Necesito algunos datos de prueba, posiblemente involucrando columnas de diferente ancho para que el algoritmo deba ser un poco más sofisticado (pero solo un poco;)

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
gboffi
fuente