Guarde la tabla “Out ” de un dataframe de pandas como una figura

Esto puede parecer una característica inútil pero sería muy útil para mí. Me gustaría guardar la salida que obtengo dentro de Canopy IDE. No creo que esto sea específico de Canopy, pero en aras de la claridad, eso es lo que uso. Por ejemplo, mi consola Out [2] es lo que querría de esto:

introduzca la descripción de la imagen aquí

Creo que el formato es bastante bueno y reproducirlo cada vez, en lugar de simplemente guardar la salida, sería una pérdida de tiempo. Así que mi pregunta es, ¿cómo puedo manejar esta figura? Idealmente, la implementación sería similar a los métodos estándar, de manera que se podría hacer así:

from matplotlib.backends.backend_pdf import PdfPages pp = PdfPages('Output.pdf') fig = plt.figure() ax = fig.add_subplot(1, 1, 1) df.plot(how='table') pp.savefig() pp.close() 

NOTA: Me doy cuenta de que antes se formuló una pregunta muy similar ( ¿Cómo guardar los datos del dataframe / serie de Pandas como una figura? ) Pero nunca recibió una respuesta y creo que he formulado la pregunta con mayor claridad.

Aquí hay una solución un tanto intrincada, pero hace el trabajo. Querías un .pdf pero obtienes un bono .png. 🙂

 import numpy as np import pandas as pd from matplotlib.backends.backend_pdf import PdfPages import matplotlib.pyplot as plt from PySide.QtGui import QImage from PySide.QtGui import QPainter from PySide.QtCore import QSize from PySide.QtWebKit import QWebPage arrays = [np.hstack([ ['one']*3, ['two']*3]), ['Dog', 'Bird', 'Cat']*2] columns = pd.MultiIndex.from_arrays(arrays, names=['foo', 'bar']) df =pd.DataFrame(np.zeros((3,6)),columns=columns,index=pd.date_range('20000103',periods=3)) h = "   

" + df.to_html() + "

"; page = QWebPage() page.setViewportSize(QSize(5000,5000)) frame = page.mainFrame() frame.setHtml(h, "text/html") img = QImage(1000,700, QImage.Format(5)) painter = QPainter(img) frame.render(painter) painter.end() a = img.save("html.png") pp = PdfPages('html.pdf') fig = plt.figure(figsize=(8,6),dpi=1080) ax = fig.add_subplot(1, 1, 1) img2 = plt.imread("html.png") plt.axis('off') ax.imshow(img2) pp.savefig() pp.close()

Ediciones bienvenidas.

Es, creo, una tabla HTML que está procesando su IDE. Esto es lo que hace el portátil ipython.

Usted puede obtener una manija de la misma manera:

 from IPython.display import HTML import pandas as pd data = pd.DataFrame({'spam':['ham','green','five',0,'kitties'], 'eggs':[0,1,2,3,4]}) h = HTML(data.to_html()) h 

y guardar en un archivo HTML:

 my_file = open('some_file.html', 'w') my_file.write(h.data) my_file.close() 

Creo que lo que se necesita aquí es una forma consistente de generar una tabla en un archivo pdf entre los gráficos de salida en pdf.

Mi primer pensamiento es no utilizar el backend matplotlib, es decir

 from matplotlib.backends.backend_pdf import PdfPages 

porque parecía algo limitado en cuanto a las opciones de formato y se inclinó hacia el formato de la tabla como una imagen (por lo tanto, se representa el texto de la tabla en un formato no seleccionable)

Si desea combinar los gráficos de salida de datos y de fotogtwigs matplotlib en un pdf sin utilizar el backend matplotlib pdf, puedo pensar en dos formas.

  1. Genere su pdf de las figuras de matplotlib como antes e inserte páginas que luego contengan la tabla de marcos de datos. Veo esto como una opción difícil.
  2. Utiliza una biblioteca diferente para generar el pdf. Ilustro una opción para hacer esto a continuación.

En primer lugar, instale la biblioteca xhtml2pdf . Esto parece un poco compatible, pero está activo en Github y tiene alguna documentación de uso básico aquí . Puede instalarlo a través de pip ie pip install xhtml2pdf

Una vez que hayas hecho eso, aquí hay un ejemplo de barebones que incrusta una figura de matplotlib, luego la tabla (todo el texto seleccionable), luego otra figura. Puedes jugar con CSS, etc. para modificar el formato a tus especificaciones exactas, pero creo que esto cumple con el resumen:

 from xhtml2pdf import pisa # this is the module that will do the work import numpy as np import pandas as pd from matplotlib.backends.backend_pdf import PdfPages import matplotlib.pyplot as plt # Utility function def convertHtmlToPdf(sourceHtml, outputFilename): # open output file for writing (truncated binary) resultFile = open(outputFilename, "w+b") # convert HTML to PDF pisaStatus = pisa.CreatePDF( sourceHtml, # the HTML to convert dest=resultFile, # file handle to recieve result path='.') # this path is needed so relative paths for # temporary image sources work # close output file resultFile.close() # close output file # return True on success and False on errors return pisaStatus.err # Main program if __name__=='__main__': arrays = [np.hstack([ ['one']*3, ['two']*3]), ['Dog', 'Bird', 'Cat']*2] columns = pd.MultiIndex.from_arrays(arrays, names=['foo', 'bar']) df = pd.DataFrame(np.zeros((3,6)),columns=columns,index=pd.date_range('20000103',periods=3)) # Define your data sourceHtml = '' # add some table CSS in head sourceHtml += '''''' sourceHtml += '' #Add a matplotlib figure(s) plt.plot(range(20)) plt.savefig('https://stackoverflow.com/questions/24574976/save-the-out-table-of-a-pandas-dataframe-as-a-figure/tmp1.jpg') sourceHtml += '\n

' # Add the dataframe sourceHtml += '\n

' + df.to_html() + '

' #Add another matplotlib figure(s) plt.plot(range(70,100)) plt.savefig('https://stackoverflow.com/questions/24574976/save-the-out-table-of-a-pandas-dataframe-as-a-figure/tmp2.jpg') sourceHtml += '\n

' sourceHtml += '' outputFilename = 'test.pdf' convertHtmlToPdf(sourceHtml, outputFilename)

Nota Parece que hay un error en xhtml2pdf en el momento de escribir esto, lo que significa que no se respeta algo de CSS. Particularmente pertinente a esta pregunta es que parece imposible obtener bordes dobles alrededor de la tabla


EDITAR

En los comentarios de respuesta, se hizo obvio que algunos usuarios (bueno, al menos @Keith, ¡quienes respondieron y recibieron una recompensa!) Quieren que la tabla sea seleccionable, pero definitivamente en un eje matplotlib. Esto es algo más acorde con el método original. Por lo tanto, aquí hay un método que utiliza el backend pdf para objetos matplotlib y matplotlib solamente. No creo que la tabla se vea tan bien, en particular la visualización de encabezados de columnas jerárquicas, pero creo que es una cuestión de elección. Estoy en deuda con esta respuesta y con mis comentarios sobre la forma de dar formato a los ejes para la visualización de tablas.

 import numpy as np import pandas as pd from matplotlib.backends.backend_pdf import PdfPages import matplotlib.pyplot as plt # Main program if __name__=='__main__': pp = PdfPages('Output.pdf') arrays = [np.hstack([ ['one']*3, ['two']*3]), ['Dog', 'Bird', 'Cat']*2] columns = pd.MultiIndex.from_arrays(arrays, names=['foo', 'bar']) df =pd.DataFrame(np.zeros((3,6)),columns=columns,index=pd.date_range('20000103',periods=3)) plt.plot(range(20)) pp.savefig() plt.close() # Calculate some sizes for formatting - constants are arbitrary - play around nrows, ncols = len(df)+1, len(df.columns) + 10 hcell, wcell = 0.3, 1. hpad, wpad = 0, 0 #put the table on a correctly sized figure fig=plt.figure(figsize=(ncols*wcell+wpad, nrows*hcell+hpad)) plt.gca().axis('off') matplotlib_tab = pd.tools.plotting.table(plt.gca(),df, loc='center') pp.savefig() plt.close() #Add another matplotlib figure(s) plt.plot(range(70,100)) pp.savefig() plt.close() pp.close()