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