本文目录导读:

- 使用Matplotlib + PdfPages(最常用)
- 使用ReportLab(专业PDF生成)
- 使用Plotly生成交互式图表并导出为PDF
- 使用Seaborn + Matplotlib
- 完整示例:生成报告PDF
- 安装必要的库
- 关键提示
我来介绍几种在Python中生成PDF图表的方法:
使用Matplotlib + PdfPages(最常用)
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.backends.backend_pdf import PdfPages
# 创建数据
x = np.linspace(0, 10, 100)
y1 = np.sin(x)
y2 = np.cos(x)
y3 = x * 0.5
# 创建PDF文件
with PdfPages('charts.pdf') as pdf:
# 图表1: 折线图
plt.figure(figsize=(8, 6))
plt.plot(x, y1, label='sin(x)', linewidth=2)
plt.plot(x, y2, label='cos(x)', linewidth=2)
plt.title('三角函数曲线')
plt.xlabel('x值')
plt.ylabel('y值')
plt.legend()
plt.grid(True, alpha=0.3)
pdf.savefig() # 保存当前图表到PDF
plt.close()
# 图表2: 柱状图
plt.figure(figsize=(8, 6))
categories = ['A', 'B', 'C', 'D', 'E']
values = [23, 45, 56, 78, 32]
plt.bar(categories, values, color='skyblue')
plt.title('分类数据柱状图')
plt.xlabel('类别')
plt.ylabel('数值')
pdf.savefig()
plt.close()
# 图表3: 散点图
plt.figure(figsize=(8, 6))
np.random.seed(42)
x_scatter = np.random.randn(100)
y_scatter = 2 * x_scatter + np.random.randn(100) * 0.5
plt.scatter(x_scatter, y_scatter, alpha=0.6, c='red')
plt.title('散点图示例')
plt.xlabel('X值')
plt.ylabel('Y值')
pdf.savefig()
plt.close()
使用ReportLab(专业PDF生成)
from reportlab.lib import colors
from reportlab.graphics.shapes import Drawing
from reportlab.graphics.charts.barcharts import VerticalBarChart
from reportlab.graphics.charts.lineplots import LinePlot
from reportlab.lib.pagesizes import A4
from reportlab.platypus import SimpleDocTemplate, Paragraph
def create_reportlab_charts():
# 创建PDF文档
doc = SimpleDocTemplate("reportlab_charts.pdf", pagesize=A4)
# 创建柱状图
d = Drawing(400, 200)
bar_chart = VerticalBarChart()
bar_chart.x = 50
bar_chart.y = 50
bar_chart.height = 125
bar_chart.width = 300
bar_chart.data = [[13, 42, 49, 103, 85]]
bar_chart.categoryAxis.categoryNames = ['Q1', 'Q2', 'Q3', 'Q4', 'Q5']
bar_chart.valueAxis.valueMin = 0
bar_chart.valueAxis.valueMax = 120
bar_chart.bars[0].fillColor = colors.HexColor('#2563EB')
d.add(bar_chart)
# 保存PDF
doc.build([d])
create_reportlab_charts()
使用Plotly生成交互式图表并导出为PDF
import plotly.express as px
import plotly.graph_objects as go
import plotly.io as pio
# 创建数据
df = px.data.iris()
# 创建散点图
fig = px.scatter(df, x="sepal_width", y="sepal_length",
color="species", size="petal_length",
title="鸢尾花数据集散点图")
# 导出为PDF(需要安装kaleido)
# pip install -U kaleido
fig.write_image("plotly_chart.pdf", format="pdf")
# 或者创建多个图表到一个PDF
import pdfkit # 需要安装: pip install pdfkit
# 创建html内容包含多个图表
html_content = """
<html>
<body>
<h2>图表报告</h2>
<div id="chart1"></div>
<div id="chart2"></div>
</body>
</html>
"""
# 转换为PDF
pdfkit.from_string(html_content, 'charts_report.pdf')
使用Seaborn + Matplotlib
import seaborn as sns
import matplotlib.pyplot as plt
from matplotlib.backends.backend_pdf import PdfPages
# 设置风格
sns.set_theme(style="whitegrid")
# 加载示例数据
tips = sns.load_dataset("tips")
with PdfPages('seaborn_charts.pdf') as pdf:
# 图表1: 箱线图
plt.figure(figsize=(10, 6))
sns.boxplot(x="day", y="total_bill", data=tips, palette="Set2")
plt.title('每日消费金额分布')
pdf.savefig()
plt.close()
# 图表2: 热力图
plt.figure(figsize=(10, 8))
correlation = tips.corr()
sns.heatmap(correlation, annot=True, cmap='coolwarm', center=0)
plt.title('相关性热力图')
pdf.savefig()
plt.close()
# 图表3: 分布图
plt.figure(figsize=(12, 6))
fig, axes = plt.subplots(1, 2, figsize=(12, 5))
sns.histplot(tips['total_bill'], kde=True, ax=axes[0])
axes[0].set_title('消费金额分布')
sns.scatterplot(x='total_bill', y='tip', hue='time',
data=tips, ax=axes[1])
axes[1].set_title('消费与小费关系')
pdf.savefig()
plt.close()
完整示例:生成报告PDF
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.backends.backend_pdf import PdfPages
from datetime import datetime
def generate_report_pdf():
"""生成包含多个图表和文字说明的PDF报告"""
with PdfPages('report.pdf') as pdf:
# 封面信息
plt.figure(figsize=(8.5, 11))
plt.axis('off')
plt.text(0.5, 0.6, '数据分析报告', fontsize=24,
ha='center', fontweight='bold')
plt.text(0.5, 0.5, f'生成日期: {datetime.now().strftime("%Y-%m-%d")}',
fontsize=14, ha='center')
plt.text(0.5, 0.4, '作者: Python脚本', fontsize=14, ha='center')
pdf.savefig()
plt.close()
# 图表1: 趋势分析
fig, ax1 = plt.subplots(figsize=(10, 6))
months = ['1月', '2月', '3月', '4月', '5月', '6月']
sales_2023 = [120, 135, 110, 180, 165, 200]
sales_2024 = [130, 150, 125, 195, 180, 220]
x = np.arange(len(months))
width = 0.35
ax1.bar(x - width/2, sales_2023, width, label='2023年', color='#3498db')
ax1.bar(x + width/2, sales_2024, width, label='2024年', color='#e74c3c')
ax1.set_xlabel('月份')
ax1.set_ylabel('销售额(万元)')
ax1.set_title('月销售额对比分析')
ax1.set_xticks(x)
ax1.set_xticklabels(months)
ax1.legend()
ax1.grid(True, alpha=0.3)
# 添加文字说明
plt.figtext(0.5, 0.01,
'图1显示2024年上半年销售额较2023年同期有所增长,'
'其中3月和4月增长最为明显。',
ha='center', fontsize=10, style='italic')
pdf.savefig()
plt.close()
# 图表2: 饼图
plt.figure(figsize=(8, 8))
categories = ['电子产品', '服装', '食品', '家居', '其他']
proportions = [35, 25, 20, 12, 8]
colors = ['#FF6B6B', '#4ECDC4', '#45B7D1', '#96CEB4', '#FFEAA7']
plt.pie(proportions, labels=categories, colors=colors,
autopct='%1.1f%%', startangle=90, explode=(0.05, 0, 0, 0, 0))
plt.title('产品销售占比分析')
plt.figtext(0.5, 0.01,
'图2显示电子产品占比最高(35%),为主要收入来源。',
ha='center', fontsize=10, style='italic')
pdf.savefig()
plt.close()
# 添加元数据
d = pdf.infodict()
d['Title'] = '销售数据分析报告'
d['Author'] = 'Python脚本'
d['Subject'] = '2024年上半年销售数据分析'
d['CreationDate'] = datetime.now()
# 生成报告
generate_report_pdf()
print("PDF报告已生成:report.pdf")
安装必要的库
pip install matplotlib numpy seaborn # 如果需要ReportLab pip install reportlab # 如果需要Plotly导出PDF pip install plotly kaleido
关键提示
- Matplotlib + PdfPages 是最常用和灵活的方式
- ReportLab 适合专业的PDF生成,但不如图表库方便
- Plotly 适合交互式图表,但导出PDF需要额外工具
- 设置中文字体以避免乱码:
plt.rcParams['font.sans-serif'] = ['SimHei', 'DejaVu Sans'] plt.rcParams['axes.unicode_minus'] = False
根据你的具体需求选择合适的方案,通常Matplotlib+PdfPages就能满足大多数场景。