[英]How to save a pandas DataFrame table as a tempory png file or bytes without saving locally
[英]How to save a pandas DataFrame table as a png
我構建了一個 pandas dataframe 的結果。 該數據框充當表格。 有 MultiIndexed 列,每行代表一個名稱,即創建 DataFrame 時index=['name1','name2',...]
。我想顯示此表並將其保存為 png(或任何圖形格式真的)。 目前,我能得到的最接近的是將它轉換為 html,但我想要一個 png。 看起來有人問過類似的問題,例如How to save the Pandas dataframe/series data as a figure?
但是,標記的解決方案將 dataframe 轉換為一行 plot(不是表格),而另一個解決方案依賴於 PySide,我想遠離它只是因為我不能 pip 在 linux 上安裝它。我希望這段代碼易於移植. 我真的很期待使用 python 輕松創建 png 表格。感謝所有幫助。
Pandas 允許您使用 matplotlib 繪制表格(詳情請點擊此處)。 通常這會將表格直接繪制到一個繪圖(帶有軸和所有內容)上,這不是您想要的。 但是,可以先刪除這些:
import matplotlib.pyplot as plt
import pandas as pd
from pandas.table.plotting import table # EDIT: see deprecation warnings below
ax = plt.subplot(111, frame_on=False) # no visible frame
ax.xaxis.set_visible(False) # hide the x axis
ax.yaxis.set_visible(False) # hide the y axis
table(ax, df) # where df is your data frame
plt.savefig('mytable.png')
輸出可能不是最漂亮的,但您可以在此處找到 table() 函數的其他參數。 還要感謝這篇文章提供了有關如何在 matplotlib 中刪除軸的信息。
這是使用上述方法進行繪圖時模擬多索引的一種(誠然非常hacky)的方法。 如果您有一個名為 df 的多索引數據框,如下所示:
first second
bar one 1.991802
two 0.403415
baz one -1.024986
two -0.522366
foo one 0.350297
two -0.444106
qux one -0.472536
two 0.999393
dtype: float64
首先重置索引,使它們成為普通列
df = df.reset_index()
df
first second 0
0 bar one 1.991802
1 bar two 0.403415
2 baz one -1.024986
3 baz two -0.522366
4 foo one 0.350297
5 foo two -0.444106
6 qux one -0.472536
7 qux two 0.999393
通過將它們設置為空字符串來刪除高階多索引列中的所有重復項(在我的示例中,我只有在“first”中有重復索引):
df.ix[df.duplicated('first') , 'first'] = '' # see deprecation warnings below
df
first second 0
0 bar one 1.991802
1 two 0.403415
2 baz one -1.024986
3 two -0.522366
4 foo one 0.350297
5 two -0.444106
6 qux one -0.472536
7 two 0.999393
將“索引”上的列名稱更改為空字符串
new_cols = df.columns.values
new_cols[:2] = '','' # since my index columns are the two left-most on the table
df.columns = new_cols
現在調用 table 函數,但將表中的所有行標簽設置為空字符串(這確保不顯示繪圖的實際索引):
table(ax, df, rowLabels=['']*df.shape[0], loc='center')
等等:
您不太漂亮但功能齊全的多索引表。
正如評論中所指出的, table
的導入語句:
from pandas.tools.plotting import table
現在在較新版本的熊貓中已棄用,以支持:
from pandas.plotting import table
ix
索引器現已完全棄用,因此我們應該改用loc
索引器。 代替:
df.ix[df.duplicated('first') , 'first'] = ''
和
df.loc[df.duplicated('first') , 'first'] = ''
實際上有一個叫做dataframe_image的python庫就做一個
pip install dataframe_image
做進口
import pandas as pd
import numpy as np
import dataframe_image as dfi
df = pd.DataFrame(np.random.randn(6, 6), columns=list('ABCDEF'))
如果需要,可以通過以下方式設置表格樣式:
df_styled = df.style.background_gradient() #adding a gradient based on values in cell
最后:
dfi.export(df_styled,"mytable.png")
解決您的問題的最佳解決方案可能是首先將您的數據框導出為 HTML,然后使用 HTML 到圖像工具將其轉換。 最終的外觀可以通過 CSS 進行調整。
HTML 到圖像渲染的流行選項包括:
讓我們假設我們有一個名為df
的數據df
。 我們可以使用以下代碼生成一個:
import string
import numpy as np
import pandas as pd
np.random.seed(0) # just to get reproducible results from `np.random`
rows, cols = 5, 10
labels = list(string.ascii_uppercase[:cols])
df = pd.DataFrame(np.random.randint(0, 100, size=(5, 10)), columns=labels)
print(df)
# A B C D E F G H I J
# 0 44 47 64 67 67 9 83 21 36 87
# 1 70 88 88 12 58 65 39 87 46 88
# 2 81 37 25 77 72 9 20 80 69 79
# 3 47 64 82 99 88 49 29 19 19 14
# 4 39 32 65 9 57 32 31 74 23 35
這種方法使用pip
-installable 包,它允許您使用 Python 生態系統完成所有操作。 weasyprint
一個缺點是它似乎沒有提供一種使圖像大小適應其內容的方法。 無論如何,從圖像中去除一些背景在 Python/PIL 中相對容易,它是在下面的trim()
函數中實現的(改編自這里)。 還需要確保圖像足夠大,這可以通過 CSS 的@page size
屬性來完成。
代碼如下:
import weasyprint as wsp
import PIL as pil
def trim(source_filepath, target_filepath=None, background=None):
if not target_filepath:
target_filepath = source_filepath
img = pil.Image.open(source_filepath)
if background is None:
background = img.getpixel((0, 0))
border = pil.Image.new(img.mode, img.size, background)
diff = pil.ImageChops.difference(img, border)
bbox = diff.getbbox()
img = img.crop(bbox) if bbox else img
img.save(target_filepath)
img_filepath = 'table1.png'
css = wsp.CSS(string='''
@page { size: 2048px 2048px; padding: 0px; margin: 0px; }
table, td, tr, th { border: 1px solid black; }
td, th { padding: 4px 8px; }
''')
html = wsp.HTML(string=df.to_html())
html.write_png(img_filepath, stylesheets=[css])
trim(img_filepath)
wkhtmltopdf
/ wkhtmltoimage
這種方法使用外部開源工具,需要在生成圖像之前安裝。 還有一個 Python 包pdfkit
可以作為它的前端(它並不免除您自己安裝核心軟件的責任),但我不會使用它。
wkhtmltoimage
可以使用subprocess
wkhtmltoimage
(或在 Python 中運行外部程序的任何其他類似方法)簡單地調用。 還需要將 HTML 文件輸出到磁盤。
代碼如下:
import subprocess
df.to_html('table2.html')
subprocess.call(
'wkhtmltoimage -f png --width 0 table2.html table2.png', shell=True)
和其他方法類似,它的方面可以用 CSS 進一步調整。
雖然我不確定這是否是您期望的結果,但您可以通過使用帶有注釋的 Seaborn Heatmap 繪制 DataFrame 以 png 格式保存您的 DataFrame,如下所示:
http://stanford.edu/~mwaskom/software/seaborn/generated/seaborn.heatmap.html#seaborn.heatmap
它可以立即與 Pandas Dataframe 配合使用。 你可以看看這個例子: Efficiently plotting a table in csv format using Python
您可能想要更改顏色圖,使其僅顯示白色背景。
希望這可以幫助。
@bunji 的解決方案對我有用,但默認選項並不總是能給出好的結果。 我添加了一些有用的參數來調整表格的外觀。
import pandas as pd
import matplotlib.pyplot as plt
from pandas.plotting import table
import numpy as np
dates = pd.date_range('20130101',periods=6)
df = pd.DataFrame(np.random.randn(6,4),index=dates,columns=list('ABCD'))
df.index = [item.strftime('%Y-%m-%d') for item in df.index] # Format date
fig, ax = plt.subplots(figsize=(12, 2)) # set size frame
ax.xaxis.set_visible(False) # hide the x axis
ax.yaxis.set_visible(False) # hide the y axis
ax.set_frame_on(False) # no visible frame, uncomment if size is ok
tabla = table(ax, df, loc='upper right', colWidths=[0.17]*len(df.columns)) # where df is your data frame
tabla.auto_set_font_size(False) # Activate set fontsize manually
tabla.set_fontsize(12) # if ++fontsize is necessary ++colWidths
tabla.scale(1.2, 1.2) # change size table
plt.savefig('table.png', transparent=True)
我對我正在做的項目有同樣的要求。 但是沒有一個答案符合我的要求。 這是最終幫助我的東西,可能對這種情況有用:
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)
如果您對在編碼環境中調用 DataFrame 時出現的格式感到滿意,那么絕對最簡單的方法是僅使用打印屏幕並使用基本圖像編輯軟件裁剪圖像。
這是我使用 Jupyter Notebook 和 Pinta Image Editor(Ubuntu 免費軟件)的結果。
正如jcdoming 所建議的,使用 Seaborn heatmap heatmap()
:
import seaborn as sns
import matplotlib.pyplot as plt
fig = plt.figure(facecolor='w', edgecolor='k')
sns.heatmap(df.head(), annot=True, cmap='viridis', cbar=False)
plt.savefig('DataFrame.png')
以下內容需要大量自定義才能正確設置表格格式,但它的主要內容是:
import numpy as np
from PIL import Image, ImageDraw, ImageFont
import pandas as pd
df = pd.DataFrame({ 'A' : 1.,
'B' : pd.Series(1,index=list(range(4)),dtype='float32'),
'C' : np.array([3] * 4,dtype='int32'),
'D' : pd.Categorical(["test","train","test","train"]),
'E' : 'foo' })
class DrawTable():
def __init__(self,_df):
self.rows,self.cols = _df.shape
img_size = (300,200)
self.border = 50
self.bg_col = (255,255,255)
self.div_w = 1
self.div_col = (128,128,128)
self.head_w = 2
self.head_col = (0,0,0)
self.image = Image.new("RGBA", img_size,self.bg_col)
self.draw = ImageDraw.Draw(self.image)
self.draw_grid()
self.populate(_df)
self.image.show()
def draw_grid(self):
width,height = self.image.size
row_step = (height-self.border*2)/(self.rows)
col_step = (width-self.border*2)/(self.cols)
for row in range(1,self.rows+1):
self.draw.line((self.border-row_step//2,self.border+row_step*row,width-self.border,self.border+row_step*row),fill=self.div_col,width=self.div_w)
for col in range(1,self.cols+1):
self.draw.line((self.border+col_step*col,self.border-col_step//2,self.border+col_step*col,height-self.border),fill=self.div_col,width=self.div_w)
self.draw.line((self.border-row_step//2,self.border,width-self.border,self.border),fill=self.head_col,width=self.head_w)
self.draw.line((self.border,self.border-col_step//2,self.border,height-self.border),fill=self.head_col,width=self.head_w)
self.row_step = row_step
self.col_step = col_step
def populate(self,_df2):
font = ImageFont.load_default().font
for row in range(self.rows):
print(_df2.iloc[row,0])
self.draw.text((self.border-self.row_step//2,self.border+self.row_step*row),str(_df2.index[row]),font=font,fill=(0,0,128))
for col in range(self.cols):
text = str(_df2.iloc[row,col])
text_w, text_h = font.getsize(text)
x_pos = self.border+self.col_step*(col+1)-text_w
y_pos = self.border+self.row_step*row
self.draw.text((x_pos,y_pos),text,font=font,fill=(0,0,128))
for col in range(self.cols):
text = str(_df2.columns[col])
text_w, text_h = font.getsize(text)
x_pos = self.border+self.col_step*(col+1)-text_w
y_pos = self.border - self.row_step//2
self.draw.text((x_pos,y_pos),text,font=font,fill=(0,0,128))
def save(self,filename):
try:
self.image.save(filename,mode='RGBA')
print(filename," Saved.")
except:
print("Error saving:",filename)
table1 = DrawTable(df)
table1.save('C:/Users/user/Pictures/table1.png')
輸出如下所示:
https://pypi.org/project/df2img/ 上有一個名為df2img
的 Python 庫(免責聲明:我是作者)。 這是一個使用plotly
作為后端的包裝器/便利功能。
import pandas as pd
import df2img
df = pd.DataFrame(
data=dict(
float_col=[1.4, float("NaN"), 250, 24.65],
str_col=("string1", "string2", float("NaN"), "string4"),
),
index=["row1", "row2", "row3", "row4"],
)
將pd.DataFrame
保存為 .png 文件可以很快完成。 您可以應用格式,例如背景顏色或交替行顏色以提高可讀性。
fig = df2img.plot_dataframe(
df,
title=dict(
font_color="darkred",
font_family="Times New Roman",
font_size=16,
text="This is a title",
),
tbl_header=dict(
align="right",
fill_color="blue",
font_color="white",
font_size=10,
line_color="darkslategray",
),
tbl_cells=dict(
align="right",
line_color="darkslategray",
),
row_fill_color=("#ffffff", "#d7d8d6"),
fig_size=(300, 160),
)
df2img.save_dataframe(fig=fig, filename="plot.png")
Plotly
做數據可視化的人:
您可以輕松地將 dataframe 轉換為go.Table 。
您可以使用列名保存 dataframe。
您可以格式化 dataframe 到go.Table
。
您可以將 dataframe 保存為具有不同比例和高分辨率的 pdf、jpg 或 png。
import plotly.express as px df = px.data.medals_long() fig = go.Figure(data=[ go.Table( header=dict(values=list(df.columns),align='center'), cells=dict(values=df.values.transpose(), fill_color = [["white","lightgrey"]*df.shape[0]], align='center' ) ) ]) fig.write_image('image.png',scale=6)
注意:圖像下載在當前 python 文件運行的同一目錄中。
Output:
我真的很喜歡 Jupyter 筆記本格式化 DataFrame 的方式,這個庫以相同的格式導出它:
import dataframe_image as dfi
dfi.export(df, "df.png")
如果您想提高圖像質量,還有一個 dpi 參數。 我建議 300 表示質量還行,600 表示出色,1200 表示完美,超過這個值可能太多了。
import dataframe_image as dfi
dfi.export(df, "df.png", dpi = 600)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.