Подтвердить что ты не робот

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

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

enter image description here

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

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 как фигура?), но это никогда получил ответ, и я думаю, что я поставил вопрос более четко.

4b9b3361

Ответ 1

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

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

Ответ 2

Это, я считаю, таблица HTML, которую выполняет ваша среда IDE. Это то, что делает ipython notebook.

Вы можете получить к нему ручку:

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

Ответ 3

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

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

from matplotlib.backends.backend_pdf import PdfPages

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

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

  • Создайте свой pdf файл matplotlib как и раньше, а затем вставьте страницы, содержащие таблицу dataframe. Я рассматриваю это как сложный вариант.
  • Используйте другую библиотеку для создания pdf. Я иллюстрирую один из вариантов, чтобы сделать это ниже.

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

Как только вы это сделали, вот пример barebones, встраивающий фигуру 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()