如何将 Pandas 数据框/系列数据保存为图形?
Posted
技术标签:
【中文标题】如何将 Pandas 数据框/系列数据保存为图形?【英文标题】:How to save the Pandas dataframe/series data as a figure? 【发布时间】:2013-11-12 15:33:09 【问题描述】:听起来有些奇怪,但我需要将 Pandas 控制台输出字符串保存为 png pics。例如:
>>> df
sales net_pft ROE ROIC
STK_ID RPT_Date
600809 20120331 22.1401 4.9253 0.1651 0.6656
20120630 38.1565 7.8684 0.2567 1.0385
20120930 52.5098 12.4338 0.3587 1.2867
20121231 64.7876 13.2731 0.3736 1.2205
20130331 27.9517 7.5182 0.1745 0.3723
20130630 40.6460 9.8572 0.2560 0.4290
20130930 53.0501 11.8605 0.2927 0.4369
有没有像df.output_as_png(filename='df_data.png')
这样的方法来生成一个只显示上面内容的图片文件?
【问题讨论】:
看这个答案的第二部分:***.com/a/10195347/1755432 目前没有像df.plot(how='table')
这样简单的方法。
@bigbug,你能把答案贴出来并标记为已解决吗?
这可能是同一个问题,但我有点不清楚***.com/questions/24574976/…
看到这个问题***.com/q/35634238/1321452,但不是公认的答案,而是其他一些,特别是***.com/a/63387275/1321452
【参考方案1】:
Option-1:使用 matplotlib 表格功能,以及一些额外的样式:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
df = pd.DataFrame()
df['date'] = ['2016-04-01', '2016-04-02', '2016-04-03']
df['calories'] = [2200, 2100, 1500]
df['sleep hours'] = [8, 7.5, 8.2]
df['gym'] = [True, False, False]
def render_mpl_table(data, col_width=3.0, row_height=0.625, font_size=14,
header_color='#40466e', row_colors=['#f1f1f2', 'w'], edge_color='w',
bbox=[0, 0, 1, 1], header_columns=0,
ax=None, **kwargs):
if ax is None:
size = (np.array(data.shape[::-1]) + np.array([0, 1])) * np.array([col_width, row_height])
fig, ax = plt.subplots(figsize=size)
ax.axis('off')
mpl_table = ax.table(cellText=data.values, bbox=bbox, colLabels=data.columns, **kwargs)
mpl_table.auto_set_font_size(False)
mpl_table.set_fontsize(font_size)
for k, cell in mpl_table._cells.items():
cell.set_edgecolor(edge_color)
if k[0] == 0 or k[1] < header_columns:
cell.set_text_props(weight='bold', color='w')
cell.set_facecolor(header_color)
else:
cell.set_facecolor(row_colors[k[0]%len(row_colors) ])
return ax.get_figure(), ax
fig,ax = render_mpl_table(df, header_columns=0, col_width=2.0)
fig.savefig("table_mpl.png")
Options-2 使用 Plotly + kaleido
import plotly.figure_factory as ff
import pandas as pd
df = pd.DataFrame()
df['date'] = ['2016-04-01', '2016-04-02', '2016-04-03']
df['calories'] = [2200, 2100, 1500]
df['sleep hours'] = [8, 7.5, 8.2]
df['gym'] = [True, False, False]
fig = ff.create_table(df)
fig.update_layout(
autosize=False,
width=500,
height=200,
)
fig.write_image("table_plotly.png", scale=2)
fig.show()
对于上述情况,font size 可以使用font
属性进行更改:
fig.update_layout(
autosize=False,
width=500,
height=200,
font='size':8
)
【讨论】:
您的代码非常适合我,谢谢。您是否还可以添加一些方法来更改一列的宽度 - 例如,我在最左边的列中有很长的“标签”字符串,并且希望它比其他列更宽。 所有你需要做的就是改变size
数组是代码的方式。
嗨@volodymyr 感谢您的卓越建议。我可以知道如何将标题文本旋转到 40 度或 90 度吗?【参考方案2】:
你必须使用DataFrame.plot()
命令返回的数字:
ax = df.plot()
fig = ax.get_figure()
fig.savefig('asdf.png')
【讨论】:
OP 似乎对保存表格描述而不是情节感兴趣。 使用 Python 3.x 这将返回“'numpy.ndarray' 对象没有属性 'get_figure'”。 在我看来,这应该是公认的答案。 @Pat:它适用于 Python 3.x 中的 pandas 因为这个问题是关于 pandas 而不是 numpy。 @strpeter:只有当你有一个单一的情节时它才有效。如果您有子图,pandas plot 会返回一个 numpy 图形数组。要获取包含所有子图的单个图形的句柄,请执行以下操作:import matplotlib.pyplot as plt; fig=plt.gcf()
【参考方案3】:
我有兴趣将我的数据框保存为报表附录的表格。我发现这是最简单的解决方案:
import pandas as pd
from matplotlib.backends.backend_pdf import PdfPages
import matplotlib.pyplot as plt
# Assuming that you have a dataframe, df
pp = PdfPages('Appendix_A.pdf')
total_rows, total_cols = df.shape; #There were 3 columns in my df
rows_per_page = 40; # Assign a page cut off length
rows_printed = 0
page_number = 1;
while (total_rows >0):
#put the table on a correctly sized figure
fig=plt.figure(figsize=(8.5, 11))
plt.gca().axis('off')
matplotlib_tab = pd.tools.plotting.table(plt.gca(),df.iloc[rows_printed:rows_printed+rows_per_page],
loc='upper center', colWidths=[0.2, 0.2, 0.2])
# Give you cells some styling
table_props=matplotlib_tab.properties()
table_cells=table_props['child_artists'] # I have no clue why child_artists works
for cell in table_cells:
cell.set_height(0.024)
cell.set_fontsize(12)
# Add a header and footer with page number
fig.text(4.25/8.5, 10.5/11., "Appendix A", ha='center', fontsize=12)
fig.text(4.25/8.5, 0.5/11., 'A'+str(page_number), ha='center', fontsize=12)
pp.savefig()
plt.close()
#Update variables
rows_printed += rows_per_page;
total_rows -= rows_per_page;
page_number+=1;
pp.close()
【讨论】:
【参考方案4】:我对我正在做的一个项目有同样的要求。但是根据我的要求,没有一个答案是优雅的。这是最终帮助我的东西,并且可能对这种情况有用,使用 Bokeh:
from bokeh.io import export_png, export_svgs
from bokeh.models import ColumnDataSource, DataTable, TableColumn
def save_df_as_image(df, path):
source = ColumnDataSource(df)
df_columns = [df.index.name]
df_columns.extend(df.columns.values)
columns_for_table=[]
for column in df_columns:
columns_for_table.append(TableColumn(field=column, title=column))
data_table = DataTable(source=source, columns=columns_for_table,height_policy="auto",width_policy="auto",index_position=None)
export_png(data_table, filename = path)
样本输出:
【讨论】:
【参考方案5】:这是一个有点老套的解决方案,但它可以完成工作。
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")
【讨论】:
【参考方案6】:您可能希望将 df 保存为 pdf,在这种情况下,reportlab Table 将完成这项工作。
【讨论】:
【参考方案7】:您也可以只使用 Dask 从 RAM 中卸载工作负载,它也适用于 Pandas 数据帧、Numpy 和 Sklearn 以及 ML。
【讨论】:
以上是关于如何将 Pandas 数据框/系列数据保存为图形?的主要内容,如果未能解决你的问题,请参考以下文章