我认为这里需要的是在将图表输出到PDF文件时,与表格输出方式保持一致的方法。
我的第一个想法不是使用matplotlib后端,即...
from matplotlib.backends.backend_pdf import PdfPages
因为它在格式选项上有些受限,并倾向于将表格格式化为图像(从而使表格文本无法选择),所以我认为这有些局限性。
如果你想在PDF中混合使用数据框输出和Matplotlib绘图,但不使用Matplotlib PDF后端,我可以想到两种方法:
- 像以前一样生成Matplotlib图的PDF,然后在之后插入包含数据框表格的页面。我认为这是一种困难的选择。
- 使用其他库来生成PDF。我下面演示了一种选项。
首先,安装
xhtml2pdf
库。这个库似乎支持有些不完整,但是
在Github上活跃 并且有一些
基本的使用文档在这里。你可以通过
pip
安装它,例如:
pip install xhtml2pdf
一旦你完成了安装,这里有一个最简单的示例,其中包含一个 matplotlib 图形,然后是表格(所有文本可选择),然后是另一个图形。你可以尝试调整 CSS 等来更改格式以满足您的确切要求,但我认为这已经符合要求了。
from xhtml2pdf import pisa
import numpy as np
import pandas as pd
from matplotlib.backends.backend_pdf import PdfPages
import matplotlib.pyplot as plt
def convertHtmlToPdf(sourceHtml, outputFilename):
resultFile = open(outputFilename, "w+b")
pisaStatus = pisa.CreatePDF(
sourceHtml,
dest=resultFile,
path='.')
resultFile.close()
return pisaStatus.err
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))
sourceHtml = '<html><head>'
sourceHtml += '''<style>
table, td, th {
border-style: double;
border-width: 3px;
}
td,th {
padding: 5px;
}
</style>'''
sourceHtml += '</head><body>'
plt.plot(range(20))
plt.savefig('tmp1.jpg')
sourceHtml += '\n<p><img src="tmp1.jpg"></p>'
sourceHtml += '\n<p>' + df.to_html() + '</p>'
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 轴上。这与原始方法有些更符合。因此,这里提供了一种仅使用 matplotlib 和 matplotlib 对象的 pdf
后端的方法。我不认为表格看起来很好 - 特别是层次列标题的显示,但我想这是一个选择问题。感谢 这个答案 和评论提供的关于表格显示格式的方式。
import numpy as np
import pandas as pd
from matplotlib.backends.backend_pdf import PdfPages
import matplotlib.pyplot as plt
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()
nrows, ncols = len(df)+1, len(df.columns) + 10
hcell, wcell = 0.3, 1.
hpad, wpad = 0, 0
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()
plt.plot(range(70,100))
pp.savefig()
plt.close()
pp.close()
DataFrame.to_html()
的输出有什么问题呢?使用类似 Beautiful Soup 的标准 HTML 分析工具,你可以轻松地抓取单元格内容。你想要一个展示如何实现的答案吗?你说你想要访问单元格内容,但你也说你想要一个 PDF。这两个要求似乎有冲突。 - holdenwebDataFrame
的to_html
(以及你提供的链接中的to_latex
)选项。那个选项不能满足你的需求吗?你可以将LaTeX嵌入到Matplotlib图中。你想知道如何将HTML嵌入到PDF中吗? - J Richard Snape