Сохраните таблицу "Out[]" информационного кадра pandas как рисунок

Это может показаться бесполезной функцией, но это было бы очень полезно для меня. Я хотел бы сохранить вывод, который я получаю внутри Canopy IDE. Я не думаю, что это специфично для Canopy, но для ясности я использую это. Например, моя консоль Out[2] - это то, что я хотел бы получить от этого:

Я думаю, что форматирование довольно приятное, и воспроизводить его каждый раз вместо сохранения результата было бы пустой тратой времени. Итак, мой вопрос, как я могу справиться с этой фигурой? В идеале имплиментация должна быть аналогична стандартным методам, так что это можно сделать так:

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

ПРИМЕЧАНИЕ: я понимаю, что ранее был задан очень похожий вопрос ( Как сохранить данные из серии / серии данных Pandas в виде рисунка?), Но он так и не получил ответа, и я думаю, что сформулировал вопрос более четко.

3 ответа

Решение

Вот несколько хакерское решение, но оно выполняет свою работу. Вы хотели.pdf, но вы получаете бонус.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()

Редактирование приветствуется.

Я считаю, что это HTML-таблица, которую визуализирует ваша IDE. Это то, что делает ноутбук ipython.

Вы можете справиться с этим таким образом:

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

и сохраните в файл HTML:

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

Я думаю, что здесь необходим согласованный способ вывода таблицы в файл PDF среди графиков, выводимых в файл PDF.

Моя первая мысль - не использовать бэкэнд matplotlib, т.е.

from matplotlib.backends.backend_pdf import PdfPages

потому что он казался несколько ограниченным в параметрах форматирования и склонялся к форматированию таблицы как изображения (таким образом, отображая текст таблицы в невыбираемом формате)

Если вы хотите смешать выходные данные с данными и графики Matplotlib в формате PDF без использования PDF-файла Matplotlib, я могу подумать о двух способах.

  1. Создайте свой pdf из рисунков matplotlib, как и раньше, а затем вставьте страницы с таблицей данных. Я рассматриваю это как сложный вариант.
  2. Используйте другую библиотеку для создания PDF. Я проиллюстрирую один вариант сделать это ниже.

Сначала установите xhtml2pdf библиотека. Кажется, это немного поддерживается, но оно активно на Github и содержит некоторую базовую документацию по использованию. Вы можете установить его через pip т.е. pip install xhtml2pdf

Как только вы это сделаете, вот простой пример, в который встраивается фигура matplotlib, затем таблица (можно выбрать весь текст), затем другая фигура. Вы можете поэкспериментировать с CSS и т. Д., Чтобы изменить форматирование в соответствии с вашими точными спецификациями, но я думаю, что это выполнит краткое изложение:

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)

Примечание. На момент написания статьи в xhtml2pdf, похоже, была ошибка, означающая, что некоторые CSS не соблюдаются. Особенно уместен этот вопрос в том, что невозможно получить двойные границы вокруг стола


РЕДАКТИРОВАТЬ

В ответных комментариях стало очевидно, что некоторые пользователи (по крайней мере, @Keith, которые и ответили, и присудили награду!) Хотят, чтобы таблица выбиралась, но определенно по оси matplotlib. Это несколько больше соответствует первоначальному методу. Следовательно - вот метод, использующий pdf бэкэнд только для объектов matplotlib и matplotlib. Я не думаю, что таблица выглядит так хорошо - в частности, отображение заголовков иерархических столбцов, но это вопрос выбора, я думаю. Я обязан этому ответу и комментариям о способе форматирования осей для отображения таблицы.

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()
Другие вопросы по тегам