【问题标题】:Save the "Out[]" table of a pandas dataframe as a figure将 pandas 数据框的“Out[]”表另存为图形
【发布时间】:2014-07-04 13:00:56
【问题描述】:

这似乎是一个无用的功能,但它对我很有帮助。我想保存我在 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()

注意:我知道之前有人问过一个非常相似的问题 (How to save the Pandas dataframe/series data as a figure?),但它从未得到答案,我想我已经更清楚地说明了这个问题。

【问题讨论】:

  • 如果你愿意重新开始stackoverflow.com/questions/8524401/…
  • 那么DataFrame.to_html() 的输出有什么问题,它允许您使用诸如Beautiful Soup 之类的相当标准的HTML 分析来抓取单元格内容?你想要一个显示如何的答案吗?你说你想访问单元格内容,但你也说你想要一个 PDF。这两个要求似乎有冲突
  • 我对你想要什么赏金感到有点困惑,不想仅仅提供一个不会让你更接近的答案。您显然知道to_html(和to_latex 给出的链接)DataFrame 的选项。那没有给你什么?您可以将乳胶嵌入到 matplotlib 图中。您想知道如何将 HTML 嵌入到 pdf 中吗?
  • @Keith 我猜到了你可能想要做什么并添加了一个答案 - 如果它符合你的要求,请告诉我。它以不同的方式解决问题,不使用 matplotlib 的 pdf 后端作为 pdf 渲染解决方案。

标签: python matplotlib pandas ipython canopy


【解决方案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】:

    我相信,您的 IDE 正在呈现的 HTML 表格。这就是 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()
    

    【讨论】:

    • 好吧,这让我成功了一半,但我的 HTML 经验为零。我想将 HTML 对象放入我保存绘图的 pdf 文件中。我的原始问题中有一个玩具示例。
    • 正如你所说'所以我的问题是,我怎样才能掌握这个数字?',这就是我的回答。表格是否需要另存为.pdf?我已经更新了将 html 对象保存到文件的答案。
    • @user262536 我不知道如何将 HTML 转换为 .pdf。这个 SO 问题可能会有所帮助:(stackoverflow.com/questions/4659058/…)。另一种方法可能是pandas.DataFrame.to_latex() 方法,并与图形一起使用 pdflatex 或类似方法进行编译。不过,我也从未尝试过这样做。
    • 对不起,我的意思是如何获得与 matplotlib 类相关的句柄。正如我怎样才能让该表具有与从 matplotlib.pyplot.imread 或 matplotlib.pyplot.plot 返回的内容相似的输出。我应该更清楚。
    【解决方案3】:

    我认为这里需要一种在输出到 pdf 的图形中将表格输出到 pdf 文件的一致方式。

    我的第一个想法是不要使用 matplotlib 后端,即

    from matplotlib.backends.backend_pdf import PdfPages
    

    因为它似乎在格式化选项方面有些限制,并且倾向于将表格格式化为图像(从而以不可选择的格式呈现表格的文本)

    如果您想在不使用 matplotlib pdf 后端的情况下在 pdf 中混合数据帧输出和 matplotlib 图,我可以想到两种方法。

    1. 像以前一样生成 matplotlib 图形的 pdf,然后插入包含数据框表的页面。我认为这是一个困难的选择。
    2. 使用不同的库来生成 pdf。我在下面说明了一种选择。

    首先,安装xhtml2pdf 库。这似乎有点不完整,但它是active on Github 并且有一些basic usage documentation here。您可以通过pippip 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 不受尊重。与这个问题特别相关的是,似乎不可能在桌子周围设置双边框


    编辑

    在响应 cmets 时,很明显一些用户(嗯,至少 @Keith 既回答了又奖励了赏金!)希望表格可选择,但绝对在 matplotlib 轴上。这在某种程度上更符合原始方法。因此 - 这是一种仅将 pdf 后端用于 matplotlib 和 matplotlib 对象的方法。我不认为该表看起来那么好 - 特别是分层列标题的显示,但我猜这是一个选择问题。我很感谢 this answer 和 cmets 为表格显示格式化轴的方式。

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

    【讨论】:

    • 谢谢,这让我走得更远。上面的图像选项获得格式但没有选择,这获得选择但没有格式。我会给你赏金,但我会尝试看看我是否可以获得更合理的格式。
    • 好的,谢谢。现在我知道这是你想要的,我会看看引入一些 CSS 来设置表格的样式,文档暗示这是可能的。
    • 在一些 CSS 中添加 - 不幸的是,它看起来忽略了 border-style: double 指令,但 border-width 和填充似乎受到尊重,并使布局更好。如果你真的需要一个特定的布局,我相信 CSS 可以做更多的事情
    • 我不认为我需要一个特定的布局,我只是觉得上图中来自 ipython 的那个看起来不错。我相信很多都同样好,但最初我认为有一些方法可以直接得到这个。无论如何,您上面的代码不适合我。我得到 >> CSSParseError: Selector name or qualifier expected:: (u'', u'\n

    • 抱歉,打错了。
    猜你喜欢
    • 1970-01-01
    • 2013-11-12
    • 2015-10-30
    • 1970-01-01
    • 2021-09-17
    • 1970-01-01
    • 2014-12-27
    • 1970-01-01
    相关资源
    最近更新 更多