You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将for循环生成的Plotly Express图表保存到单个PDF?

如何将Plotly循环生成的图表保存到单个PDF文件?

问题背景

我希望将通过for循环生成的所有图表保存到单个PDF文件中。

示例数据

import pandas as pd
import numpy as np
import plotly.io as pio
import plotly.express as px
import plotly.graph_objects as go

np.random.seed(0)
df = pd.DataFrame({'State' : np.repeat(['NY', 'TX', 'FL', 'PA'], 12),
                   'Month' : np.tile(pd.date_range('2023-09-01', '2024-08-01', freq = 'MS'), 4),
                   'Actual' : np.random.randint(1000, 1500, size = 48),
                   'Forecast' : np.random.randint(1000, 1500, size = 48)})

df['Month'] = pd.to_datetime(df['Month'])
df.set_index('Month', inplace = True)

当前已实现的图表生成代码

我已能在Jupyter Notebook中通过以下代码生成图表:

for s in df['State'].unique():
    d = df.loc[df['State'] == s, ['Actual', 'Forecast']]
    fig = px.line(d, x = d.index, y = d.columns)
    fig.update_layout(title = 'Actuals vs Forecast for ' + s, template = 'plotly_dark', xaxis_title = 'Month')
    fig.update_xaxes(tickformat = '%Y-%B', dtick = 'M1')
    fig.show()

尝试过使用fig_trace和make_subplots结合Graph Object go.Scatter替代px.line的方法,但无法生效。


解决方案

方法1:将图表转为图片后合并为PDF

Plotly本身不支持直接导出多页PDF,可先将每个图表导出为图片,再用PDF库合并成多页PDF。这里用plotly.io.to_image生成图片,结合reportlab创建PDF。

安装依赖库

pip install reportlab pillow plotly pandas numpy

完整代码

import pandas as pd
import numpy as np
import plotly.io as pio
import plotly.express as px
from reportlab.lib.pagesizes import letter
from reportlab.pdfgen import canvas
from PIL import Image
import io

# 生成示例数据
np.random.seed(0)
df = pd.DataFrame({'State' : np.repeat(['NY', 'TX', 'FL', 'PA'], 12),
                   'Month' : np.tile(pd.date_range('2023-09-01', '2024-08-01', freq = 'MS'), 4),
                   'Actual' : np.random.randint(1000, 1500, size = 48),
                   'Forecast' : np.random.randint(1000, 1500, size = 48)})
df['Month'] = pd.to_datetime(df['Month'])
df.set_index('Month', inplace = True)

# 初始化PDF画布
pdf_filename = 'state_forecasts.pdf'
c = canvas.Canvas(pdf_filename, pagesize=letter)
page_width, page_height = letter

# 循环生成图表并添加到PDF
for idx, s in enumerate(df['State'].unique()):
    d = df.loc[df['State'] == s, ['Actual', 'Forecast']]
    fig = px.line(d, x=d.index, y=d.columns)
    fig.update_layout(title='Actuals vs Forecast for ' + s, template='plotly_dark', xaxis_title='Month')
    fig.update_xaxes(tickformat='%Y-%B', dtick='M1')
    
    # 将Plotly图表转为PNG图片(内存中)
    img_bytes = pio.to_image(fig, format='png')
    img = Image.open(io.BytesIO(img_bytes))
    
    # 调整图片大小以适应PDF页面(保持比例)
    img_width, img_height = img.size
    scale = min(page_width / img_width, page_height / img_height)
    new_width = img_width * scale
    new_height = img_height * scale
    
    # 计算居中位置
    x = (page_width - new_width) / 2
    y = (page_height - new_height) / 2
    
    # 绘制图片到PDF
    c.drawImage(io.BytesIO(img_bytes), x, y, width=new_width, height=new_height)
    
    # 最后一页不添加新页面
    if idx != len(df['State'].unique()) - 1:
        c.showPage()

# 保存PDF
c.save()
print(f"PDF文件已保存为: {pdf_filename}")

方法2:用HTML嵌入图表后导出为PDF

将所有图表嵌入单个HTML页面,再用pdfkit将HTML转为多页PDF。该方法需要安装wkhtmltopdf工具。

安装依赖

  1. 安装Python库:
pip install pdfkit plotly pandas numpy
  1. 安装wkhtmltopdf:
    • Windows:从官网下载安装包
    • Linux:执行sudo apt-get install wkhtmltopdf
    • macOS:执行brew install wkhtmltopdf

完整代码

import pandas as pd
import numpy as np
import plotly.express as px
import plotly.io as pio
import pdfkit

# 生成示例数据
np.random.seed(0)
df = pd.DataFrame({'State' : np.repeat(['NY', 'TX', 'FL', 'PA'], 12),
                   'Month' : np.tile(pd.date_range('2023-09-01', '2024-08-01', freq = 'MS'), 4),
                   'Actual' : np.random.randint(1000, 1500, size = 48),
                   'Forecast' : np.random.randint(1000, 1500, size = 48)})
df['Month'] = pd.to_datetime(df['Month'])
df.set_index('Month', inplace = True)

# 构建HTML内容
html_content = "<html><body>"

for s in df['State'].unique():
    d = df.loc[df['State'] == s, ['Actual', 'Forecast']]
    fig = px.line(d, x=d.index, y=d.columns)
    fig.update_layout(title='Actuals vs Forecast for ' + s, template='plotly_dark', xaxis_title='Month')
    fig.update_xaxes(tickformat='%Y-%B', dtick='M1')
    
    # 将图表转为HTML片段
    html_content += pio.to_html(fig, full_html=False)
    # 添加分页符
    html_content += "<div style='page-break-after: always;'></div>"

html_content += "</body></html>"

# 导出为PDF
pdf_filename = 'state_forecasts_html.pdf'
pdfkit.from_string(html_content, pdf_filename)
print(f"PDF文件已保存为: {pdf_filename}")

内容的提问来源于stack exchange,提问作者Karthik S

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 04:27:36