Frage Speichere die "Out []" - Tabelle eines Pandas-Datenrahmens als eine Figur


Dies scheint eine nutzlose Funktion zu sein, aber es wäre sehr hilfreich für mich. Ich möchte die Ausgabe, die ich in Canopy IDE erhalte, speichern. Ich würde nicht denken, dass dies für Canopy spezifisch ist, aber aus Gründen der Klarheit verwende ich das. Zum Beispiel, meine Konsole Out [2] ist, was ich von diesem wollen würde:

enter image description here

Ich denke, dass die Formatierung ziemlich nett ist und dies jedes Mal zu reproduzieren, anstatt nur die Ausgabe zu speichern wäre eine Zeitverschwendung. Meine Frage ist also, wie kann ich diese Figur in den Griff bekommen? Idealerweise wäre die Implementierung ähnlich wie bei Standardmethoden, so dass es so gemacht werden könnte:

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

HINWEIS: Ich stelle fest, dass eine sehr ähnliche Frage schon einmal gestellt wurde ( Wie speichert man die Pandas Daten / Serien Daten als Figur? ) aber es hat nie eine Antwort erhalten und ich denke, ich habe die Frage klarer formuliert.


18
2017-07-04 13:00


Ursprung


Antworten:


Hier ist eine etwas hackische Lösung, aber es macht den Job erledigt. Sie wollten ein .pdf, aber Sie erhalten einen Bonus .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 = "<!DOCTYPE html> <html> <body> <p> " + df.to_html() + " </p> </body> </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()

Bearbeitungen willkommen.


6
2017-07-07 11:49



Es ist, glaube ich, eine HTML-Tabelle, die Ihre IDE rendert. Dies ist, was Ipython Notebook tut.

Sie können damit einen Griff bekommen:

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

und in einer HTML-Datei speichern:

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

4
2017-07-04 15:03



Ich denke, was hier benötigt wird, ist eine konsistente Art und Weise der Ausgabe einer Tabelle in eine PDF-Datei unter Graphen, die als PDF ausgegeben werden.

Mein erster Gedanke ist nicht, das Backend von Matplotlib zu verwenden, d.h.

from matplotlib.backends.backend_pdf import PdfPages

weil es in den Formatierungsoptionen etwas begrenzt schien und sich darauf vorbereitete, die Tabelle als Bild zu formatieren (wodurch der Text der Tabelle in einem nicht auswählbaren Format dargestellt wurde)

Wenn Sie Datenframe-Ausgabe und Matplotlib-Plots in einer PDF-Datei mischen möchten, ohne das Matplotlib-PDF-Backend zu verwenden, kann ich mir zwei Möglichkeiten vorstellen.

  1. Generieren Sie wie zuvor Ihre PDF-Datei mit den Matplotlib-Abbildungen und fügen Sie anschließend Seiten mit der Dataframe-Tabelle ein. Ich betrachte dies als eine schwierige Option.
  2. Verwenden Sie eine andere Bibliothek, um das PDF zu generieren. Ich zeige eine Option, um dies zu tun.

Zuerst installieren xhtml2pdf Bibliothek. Dies scheint ein wenig lückenhaft unterstützt, ist aber aktiv auf Github und hat einige grundlegende Nutzungsdokumentation hier. Sie können es über installieren pip d.h. pip install xhtml2pdf

Sobald Sie das getan haben, ist hier ein Barebones-Beispiel, das eine Matplotlib-Figur einbettet, dann die Tabelle (alles Text wählbar), dann eine weitere Figur. Sie können mit CSS usw. herumspielen, um die Formatierung an Ihre genauen Spezifikationen anzupassen, aber ich denke, das erfüllt die Aufgabe:

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 = '<html><head>'         
    # add some table CSS in head
    sourceHtml += '''<style>
                     table, td, th {
                           border-style: double;
                           border-width: 3px;
                     }

                     td,th {
                           padding: 5px;
                     }
                     </style>'''
    sourceHtml += '</head><body>'
    #Add a matplotlib figure(s)
    plt.plot(range(20))
    plt.savefig('tmp1.jpg')
    sourceHtml += '\n<p><img src="tmp1.jpg"></p>'

    # Add the dataframe
    sourceHtml += '\n<p>' + df.to_html() + '</p>'

    #Add another matplotlib figure(s)
    plt.plot(range(70,100))
    plt.savefig('tmp2.jpg')
    sourceHtml += '\n<p><img src="tmp2.jpg"></p>'

    sourceHtml += '</body></html>'
    outputFilename = 'test.pdf'

    convertHtmlToPdf(sourceHtml, outputFilename)

Hinweis Es scheint einen Fehler in xhtml2pdf zum Zeitpunkt des Schreibens zu geben, was bedeutet, dass einige CSS nicht respektiert werden. Besonders relevant für diese Frage ist, dass es unmöglich scheint, doppelte Grenzen um den Tisch zu legen


BEARBEITEN

In Antwortkommentaren wurde es offensichtlich, dass einige Benutzer (gut, zumindest @Keith, die beide antworteten und ein Kopfgeld verliehen!) Die Tabelle auswählbar, aber definitiv auf einer Matplotlib-Achse wollen. Dies entspricht etwas mehr der ursprünglichen Methode. Daher - hier ist eine Methode mit der pdfBackend nur für Matplotlib- und Matplotlib-Objekte. Ich denke nicht, dass die Tabelle so gut aussieht - insbesondere die Anzeige von hierarchischen Spaltenüberschriften, aber das ist eine Frage der Wahl, denke ich. Ich bin dazu verpflichtet diese Antwort und Kommentare für die Art, Achsen für die Tabellenanzeige zu formatieren.

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

2
2018-06-11 13:30