Saltar al contenido

Cómo guardar una tabla pandas DataFrame como png

Orlando, parte de este gran staff, nos hizo el favor de escribir este tutorial porque controla perfectamente este tema.

Solución:

Pandas le permite trazar tablas usando matplotlib (detalles aquí). Por lo general, esto traza la tabla directamente en un gráfico (con ejes y todo) que no es lo que desea. Sin embargo, estos se pueden eliminar primero:

import matplotlib.pyplot as plt
import pandas as pd
from pandas.table.plotting import table # EDIT: see deprecation warnings below

ax = plt.subplot(111, frame_on=False) # no visible frame
ax.xaxis.set_visible(False)  # hide the x axis
ax.yaxis.set_visible(False)  # hide the y axis

table(ax, df)  # where df is your data frame

plt.savefig('mytable.png')

Es posible que la salida no sea la más bonita, pero puede encontrar argumentos adicionales para la función table () aquí. También gracias a esta publicación para obtener información sobre cómo eliminar ejes en matplotlib.


EDITAR:

Aquí hay una forma (ciertamente bastante hacky) de simular índices múltiples al trazar usando el método anterior. Si tiene un marco de datos de múltiples índices llamado df que se parece a:

first  second
bar    one       1.991802
       two       0.403415
baz    one      -1.024986
       two      -0.522366
foo    one       0.350297
       two      -0.444106
qux    one      -0.472536
       two       0.999393
dtype: float64

Primero restablezca los índices para que se conviertan en columnas normales

df = df.reset_index() 
df
    first second       0
0   bar    one  1.991802
1   bar    two  0.403415
2   baz    one -1.024986
3   baz    two -0.522366
4   foo    one  0.350297
5   foo    two -0.444106
6   qux    one -0.472536
7   qux    two  0.999393

Elimine todos los duplicados de las columnas de índices múltiples de orden superior configurándolos en un vacío string (en mi ejemplo solo tengo índices duplicados en “primero”):

df.ix[df.duplicated('first') , 'first'] = '' # see deprecation warnings below
df
  first second         0
0   bar    one  1.991802
1          two  0.403415
2   baz    one -1.024986
3          two -0.522366
4   foo    one  0.350297
5          two -0.444106
6   qux    one -0.472536
7          two  0.999393

Cambie los nombres de las columnas sobre sus “índices” al vacío string

new_cols = df.columns.values
new_cols[:2] = '',''  # since my index columns are the two left-most on the table
df.columns = new_cols 

Ahora llame a la función de tabla, pero establezca todas las etiquetas de fila en la tabla al vacío string (esto asegura que no se muestren los índices reales de su gráfico):

table(ax, df, rowLabels=['']*df.shape[0], loc='center')

et voila:

ingrese la descripción de la imagen aquí

Tu tabla multi-indexada no tan bonita pero totalmente funcional.

EDITAR: ADVERTENCIAS DE DEPRECATION

Como se señaló en los comentarios, la declaración de importación de table:

from pandas.tools.plotting import table

ahora está en desuso en las versiones más nuevas de pandas a favor de:

from pandas.plotting import table 

EDITAR: ADVERTENCIAS DE DEPRECATION 2

los ix indexador ahora ha sido completamente obsoleto, por lo que deberíamos usar el loc indexador en su lugar. Reemplazar:

df.ix[df.duplicated('first') , 'first'] = ''

con

df.loc[df.duplicated('first') , 'first'] = ''

La mejor solución a su problema es probablemente exportar primero su marco de datos a HTML y luego convertirlo usando una herramienta de HTML a imagen. La apariencia final podría modificarse mediante CSS.

Las opciones populares para la representación de HTML a imagen incluyen:

  • WeasyPrint
  • wkhtmltopdf/wkhtmltoimage

Supongamos que tenemos un marco de datos llamado df. Podemos generar uno con el siguiente código:

import string
import numpy as np
import pandas as pd


np.random.seed(0)  # just to get reproducible results from `np.random`
rows, cols = 5, 10
labels = list(string.ascii_uppercase[:cols])
df = pd.DataFrame(np.random.randint(0, 100, size=(5, 10)), columns=labels)
print(df)
#     A   B   C   D   E   F   G   H   I   J
# 0  44  47  64  67  67   9  83  21  36  87
# 1  70  88  88  12  58  65  39  87  46  88
# 2  81  37  25  77  72   9  20  80  69  79
# 3  47  64  82  99  88  49  29  19  19  14
# 4  39  32  65   9  57  32  31  74  23  35

Usando WeasyPrint

Este enfoque utiliza un pip-paquete instalable, que te permitirá hacer todo usando el ecosistema Python. Una deficiencia de weasyprint es que no parece proporcionar una forma de adaptar el tamaño de la imagen a su contenido. De todos modos, eliminar algo de fondo de una imagen es relativamente fácil en Python / PIL, y está implementado en el trim() función a continuación (adaptado de aquí). También es necesario asegurarse de que la imagen sea lo suficientemente grande, y esto se puede hacer con CSS @page size propiedad.

El código sigue:

import weasyprint as wsp
import PIL as pil


def trim(source_filepath, target_filepath=None, background=None):
    if not target_filepath:
        target_filepath = source_filepath
    img = pil.Image.open(source_filepath)
    if background is None:
        background = img.getpixel((0, 0))
    border = pil.Image.new(img.mode, img.size, background)
    diff = pil.ImageChops.difference(img, border)
    bbox = diff.getbbox()
    img = img.crop(bbox) if bbox else img
    img.save(target_filepath)


img_filepath = 'table1.png'
css = wsp.CSS(string='''
@page  size: 2048px 2048px; padding: 0px; margin: 0px; 
table, td, tr, th  border: 1px solid black; 
td, th  padding: 4px 8px; 
''')
html = wsp.HTML(string=df.to_html())
html.write_png(img_filepath, stylesheets=[css])
trim(img_filepath)

table_weasyprint


Utilizando wkhtmltopdf/wkhtmltoimage

Este enfoque utiliza una herramienta externa de código abierto y debe instalarse antes de la generación de la imagen. También hay un paquete de Python, pdfkit, que sirve como interfaz (no le exime de instalar el software principal usted mismo), pero no lo usaré.

wkhtmltoimage se puede llamar simplemente usando subprocess (o cualquier otro medio similar para ejecutar un programa externo en Python). También se necesitaría enviar al disco el archivo HTML.

El código sigue:

import subprocess


df.to_html('table2.html')
subprocess.call(
    'wkhtmltoimage -f png --width 0 table2.html table2.png', shell=True)

table_wkhtmltoimage

y su aspecto podría ajustarse aún más con CSS de manera similar al otro enfoque.


Aunque no estoy seguro de si este es el resultado que espera, puede guardar su DataFrame en png trazando el DataFrame con Seaborn Heatmap con anotaciones, así:

http://stanford.edu/~mwaskom/software/seaborn/generated/seaborn.heatmap.html#seaborn.heatmap

Ejemplo de mapa de calor de Seaborn con anotaciones en

Funciona de inmediato con un marco de datos de Pandas. Puede ver este ejemplo: Trazar eficientemente una tabla en formato csv usando Python

Es posible que desee cambiar el mapa de colores para que muestre solo un fondo blanco.

Espero que esto ayude.

Recuerda algo, que te brindamos la opción de decir .

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *