如何将 pandas DataFrame 表保存为 png

2025-01-09 08:47:00
admin
原创
112
摘要:问题描述:我构建了一个结果的 pandas 数据框。此数据框充当表格。有 MultiIndexed 列,每行代表一个名称,即index=['name1','name2',...]在创建 DataFrame 时。我想显示此表并将其保存为 png(或任何图形格式)。目前,我能得到的最接近的方法是将其转换为 htm...

问题描述:

我构建了一个结果的 pandas 数据框。此数据框充当表格。有 MultiIndexed 列,每行代表一个名称,即index=['name1','name2',...]在创建 DataFrame 时。我想显示此表并将其保存为 png(或任何图形格式)。目前,我能得到的最接近的方法是将其转换为 html,但我想要一个 png。看起来有人问过类似的问题,例如如何将 Pandas 数据框/系列数据保存为图形?

但是,标记的解决方案将数据框转换为线图(而不是表格),而另一个解决方案依赖于 PySide,我想远离它,因为我无法在 Linux 上 pip 安装它。我希望此代码易于移植。我真的希望使用 python 可以轻松创建 png 表格。感谢所有帮助。


解决方案 1:

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() 函数的其他参数。


编辑:

这是使用上述方法绘图时模拟多索引的一种(诚然,相当古怪)方法。如果您有一个名为 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(ax, df, rowLabels=['']*df.shape[0], loc='center')

瞧:

在此处输入图片描述

虽然不太漂亮,但功能齐全的多索引表。

编辑:弃用警告

正如评论中指出的那样,导入声明table

from pandas.tools.plotting import table

在较新版本的 Pandas 中已被弃用,取而代之的是:

from pandas.plotting import table 

编辑:弃用警告 2

索引器ix现已完全弃用,因此我们应该改用loc索引器。替换:

df.ix[df.duplicated('first') , 'first'] = ''

df.loc[df.duplicated('first') , 'first'] = ''

解决方案 2:

实际上有一个名为 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")

解决方案 3:

解决您的问题的最佳方法可能是先将数据框导出为 HTML,然后使用 HTML 转图像工具进行转换。最终外观可以通过 CSS 进行调整。

HTML 到图像渲染的热门选项包括:

  • WeasyPrint

  • wkhtmltopdf/wkhtmltoimage


假设我们有一个名为的数据框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

使用WeasyPrint

这种方法使用了一个pip-installable 包,它允许您使用 Python 生态系统完成所有操作。 的一个缺点是它似乎没有提供根据内容调整图像大小weasyprint的方法。 无论如何,在 Python/PIL 中从图像中删除一些背景相对容易,它是在下面的功能中实现的(改编自此处)。 还需要确保图像足够大,这可以通过 CSS 的属性来实现。trim()`@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)

table_weasyprint


使用wkhtmltopdf/wkhtmltoimage

此方法使用外部开源工具,需要在生成映像之前安装。还有一个 Python 包,pdfkit可作为其前端(它不会免除您自行安装核心软件的义务),但我不会使用它。

wkhtmltoimage可以简单地使用subprocess(或任何其他类似的在 Python 中运行外部程序的方法)进行调用。还需要将 HTML 文件输出到磁盘。

代码如下:

import subprocess


df.to_html('table2.html')
subprocess.call(
    'wkhtmltoimage -f png --width 0 table2.html table2.png', shell=True)

table_wkhtml 到图像

并且其外观可以像其他方法一样使用 CSS 进行进一步调整。


解决方案 4:

虽然我不确定这是否是你期望的结果,但是你可以通过使用 Seaborn Heatmap 绘制带有注释的 DataFrame 来将 DataFrame 保存为 png 格式,如下所示:

http://stanford.edu/~mwaskom/software/seaborn/ generated/seaborn.heatmap.html#seaborn.heatmap

带有注释的 Seaborn 热图示例

它可立即与 Pandas Dataframe 配合使用。您可以查看此示例:使用 Python 高效绘制 csv 格式的表格

您可能想要更改颜色图以便它仅显示白色背景。

希望这有帮助。

编辑:这是一个执行此操作的片段:

import matplotlib
import seaborn as sns

def save_df_as_image(df, path):
    # Set background to white
    norm = matplotlib.colors.Normalize(-1,1)
    colors = [[norm(-1.0), "white"],
            [norm( 1.0), "white"]]
    cmap = matplotlib.colors.LinearSegmentedColormap.from_list("", colors)
    # Make plot
    plot = sns.heatmap(df, annot=True, cmap=cmap, cbar=False)
    fig = plot.get_figure()
    fig.savefig(path)

解决方案 5:

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

结果:
桌子

解决方案 6:

有一个名为https://pypi.org/project/df2img/df2img的 Python 库可用(免责声明:我是作者)。它是一个用作后端的包装器/便利函数。plotly

您可以在https://df2img.dev找到文档。

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

pd.DataFrame png 文件

解决方案 7:

我正在进行的项目也有同样的要求。但没有一个答案能满足我的要求。下面这个终于对我有帮助,可能对这个案例有用:

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)

在此处输入图片描述

解决方案 8:

如果您对在编码环境中调用 DataFrame 时出现的格式感到满意,那么最简单的方法就是使用打印屏幕并使用基本的图像编辑软件裁剪图像。

以下是我使用 Jupyter Notebook 和 Pinta Image Editor(Ubuntu 免费软件)的结果。

解决方案 9:

以下内容需要大量定制才能正确格式化表格,但其基本原理是可行的:

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

输出如下所示:

在此处输入图片描述

解决方案 10:

正如jcdoming所建议的,使用 Seaborn 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')

DataFrame 作为热图

解决方案 11:

使用 Anaconda Spyder IDE 将 Pandas 数据框转换为 png 图像的最简单、最快捷的方法 - 只需双击变量资源管理器中的数据框,IDE 表就会出现,并带有自动格式和配色方案。只需使用截图工具捕获表格以用于报告,然后保存为 png:

2020 年蓝筹股比率

这让我节省了很多时间,而且依然优雅而专业。

解决方案 12:

用于数据可视化的人员Plotly

  • 您可以轻松地将数据框转换为go.Table。

  • 您可以使用列名保存数据框。

  • 您可以通过 来格式化数据框go.Table

  • 您可以将数据框保存为具有不同比例和高分辨率的 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文件运行的同一目录中。

输出:

在此处输入图片描述

解决方案 13:

我真的很喜欢 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)
相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   1579  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1355  
  信创产品在政府采购中的占比分析随着信息技术的飞速发展以及国家对信息安全重视程度的不断提高,信创产业应运而生并迅速崛起。信创,即信息技术应用创新,旨在实现信息技术领域的自主可控,减少对国外技术的依赖,保障国家信息安全。政府采购作为推动信创产业发展的重要力量,其对信创产品的采购占比情况备受关注。这不仅关系到信创产业的发展前...
信创和国产化的区别   8  
  信创,即信息技术应用创新产业,旨在实现信息技术领域的自主可控,摆脱对国外技术的依赖。近年来,国货国用信创发展势头迅猛,在诸多领域取得了显著成果。这一发展趋势对科技创新产生了深远的推动作用,不仅提升了我国在信息技术领域的自主创新能力,还为经济社会的数字化转型提供了坚实支撑。信创推动核心技术突破信创产业的发展促使企业和科研...
信创工作   9  
  信创技术,即信息技术应用创新产业,旨在实现信息技术领域的自主可控与安全可靠。近年来,信创技术发展迅猛,对中小企业产生了深远的影响,带来了诸多不可忽视的价值。在数字化转型的浪潮中,中小企业面临着激烈的市场竞争和复杂多变的环境,信创技术的出现为它们提供了新的发展机遇和支撑。信创技术对中小企业的影响技术架构变革信创技术促使中...
信创国产化   8  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用