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

如何让Jupyter Notebook中渲染的matplotlib图与savefig导出PDF一致?

问题

使用fig.savefig()保存matplotlib图形时,其效果与Jupyter Notebook中渲染的图形存在差异。

需求

如何在Jupyter Notebook中渲染静态(非交互式)图形,使其效果与调用fig.savefig('example.pdf')保存的PDF完全一致?

背景

使用matplotlib制作图形时,我会仔细调整尺寸和布局,再通过fig.savefig('example.pdf')保存(不使用pad_inches=0和bbox_inches='tight'等自动调整参数),确保所有元素(尤其是文本)尺寸准确。示例代码如下:

import matplotlib.pyplot as plt

fig, ax = plt.subplots(figsize=(1,1))
ax.plot(WHATEVER)

# 根据需要进行精细调整
fig.subplots_adjust(left=0.15, right=0.8, bottom=0.1, top=0.95, wspace=0.1, hspace=0.1)

fig.savefig('my_fig.pdf')

为了快速迭代调整图形,我希望运行脚本(或.py文件中的#%%单元格)后,通过plt.show()在IDE中立即查看图形,而非反复保存PDF并重新打开。但Jupyter Notebook中渲染的图形与保存的PDF差异明显,尤其是画布边缘部分。

这显然与渲染后端有关:保存PDF时使用pdf后端,而Notebook中使用inline后端。此前使用PyCharm的SciView功能,调用plt.show()时会以png格式渲染图形,其效果与fig.savefig保存的完全一致,但不清楚所用的matplotlib后端。

相关问题

已有多个问题讨论plt.show()与fig.savefig()的输出差异,但大多是调整fig.savefig()的输出以匹配plt.show(),而非反向调整。

解决方案

1. 配置inline后端遵循原始布局

在Notebook开头添加以下配置,禁用inline后端的自动调整逻辑,让渲染严格匹配你设置的边距和尺寸:

%matplotlib inline
import matplotlib.pyplot as plt

# 关闭自动布局,确保与savefig行为一致
plt.rcParams['figure.autolayout'] = False
# 统一DPI:savefig默认使用figure.dpi(默认值100),同步inline渲染的DPI
plt.rcParams['figure.dpi'] = 100

这样inline渲染会完全尊重fig.subplots_adjust()的设置,不会自动填充或裁剪边缘。

2. 复用savefig逻辑直接展示

绕过plt.show(),直接用savefig生成临时文件并在Notebook中展示,完全复用PDF的渲染逻辑:

import matplotlib.pyplot as plt
from IPython.display import display, Image
from io import BytesIO

fig, ax = plt.subplots(figsize=(1,1))
ax.plot([1,2,3])
fig.subplots_adjust(left=0.15, right=0.8, bottom=0.1, top=0.95)

# 保存到内存缓冲区,避免写入磁盘
buffer = BytesIO()
fig.savefig(buffer, format='png', dpi=100)
buffer.seek(0)
display(Image(buffer.getvalue()))

这种方式的展示效果和最终保存的PDF完全一致,没有额外的布局调整。

3. 切换到GUI后端

如果是本地运行的Notebook,可以切换到类似PyCharm SciView使用的GUI后端,弹出独立窗口展示图形,渲染逻辑与savefig完全对齐:

%matplotlib qt5  # 或qt4、tkagg等,根据环境支持选择

调用plt.show()后会弹出独立窗口,图形的边距、元素尺寸都会和savefig输出一致。注意该方式不适合远程Jupyter环境。

4. 直接预览PDF

生成PDF并嵌入Notebook中展示,直接查看最终效果:

import matplotlib.pyplot as plt
from matplotlib.backends.backend_pdf import PdfPages
from IPython.display import display, PDF
from io import BytesIO

fig, ax = plt.subplots(figsize=(1,1))
ax.plot([1,2,3])
fig.subplots_adjust(left=0.15, right=0.8, bottom=0.1, top=0.95)

# 将PDF写入内存缓冲区
buffer = BytesIO()
with PdfPages(buffer) as pdf:
    pdf.savefig(fig)
buffer.seek(0)
display(PDF(buffer.read()))

内容的提问来源于Stack Exchange,提问作者Heisenbugs

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 01:50:54