matplotlib savefig() 绘图不同于 show()
Posted
技术标签:
【中文标题】matplotlib savefig() 绘图不同于 show()【英文标题】:matplotlib savefig() plots different from show() 【发布时间】:2011-12-15 22:07:49 【问题描述】:当我使用show()
在X
中绘制图形时,图形看起来非常好。但是,当我开始使用savefig()
生成大量图形时,savefig()
生成的图形
' 字体、线条、多边形看起来都比show()
生成的图形小。我的环境是 Ubuntu,show()
的后端是 Qt4Agg
。如何使show()
图和savefig()
图看起来一致?
【问题讨论】:
【参考方案1】:savefig
指定已保存图形的 DPI(如果未在 .matplotlibrc 中指定,则默认为 100,请查看 dpi
kwarg to savefig
)。它不会从原始图形的 DPI 继承它。
DPI 会影响文本的相对大小和线条笔划的宽度等。如果您希望看起来相同,则将fig.dpi
传递给fig.savefig
。
例如
import matplotlib.pyplot as plt
fig = plt.figure()
plt.plot(range(10))
fig.savefig('temp.png', dpi=fig.dpi)
【讨论】:
似乎适用于 .png,但不适用于 .jpg。发现它适用于 jpg,我不得不添加 bbox_inches='tight'【参考方案2】:您将 matplotlib 绘图渲染到不同的设备(例如,通过 Quartz 在屏幕上显示与使用不同功能通过 pdf 的 to-file(plot 与 savefig) 的参数几乎相同,但两个函数的这些参数的默认值并不相同。
换句话说,savefig默认参数不同于默认显示强>参数。
如果你在 matplotlib 配置文件中对齐它们很简单。模板文件包含在源包中,并命名为 matplotlibrc.template。如果您在安装 matplotlib 时没有创建模板,您可以从 matplotlib 源或 matplotlib website 获取此模板。
一旦你按照你想要的方式自定义了这个文件,把它重命名为 matplotlibrc(没有扩展名)并将它保存到目录 .matplotlib (注意前导的“.”)应该在你的主目录中。
保存数字的配置参数从提供的matplotlibrc.template中的第314行开始(本节之前的第一行是:# ## 保存数据)。
特别是,你会想看看这些:
savefig.dpi : 100 # figure dots per inch
savefig.facecolor : white # figure facecolor when saving
savefig.edgecolor : white # figure edgecolor when saving
savefig.extension : auto # what extension to use for savefig('foo'), or 'auto'
这些行下面是字体类型和各种图像格式特定参数的设置。
这些相同的参数用于显示,即PLT.show(),大约从第 277 行开始matplotlibrc.template 中的 a(本节前面有一行:### 图形):
figure.figsize : 8, 6
figure.dpi : 80
figure.facecolor : 0.75
figure.edgecolor : white
通过比较这两个参数块的值可以看出,同一图形属性的默认设置不同 savefig 与 display(显示)。
【讨论】:
更改这些配置仍然与 show() 和 savefig() 之间一致的字体大小和线宽不匹配。虽然我想添加从 Qt Widget 手动保存图表是可以的。只有在使用 savefig() 时才行【参考方案3】:老问题,但显然谷歌喜欢它,所以我想在对这个问题进行一些研究后在这里给出答案。
如果你从头开始创建一个图形,你可以在创建时给它一个大小选项:
import matplotlib.pyplot as plt
fig = plt.figure(figsize=(3, 6))
plt.plot(range(10)) #plot example
plt.show() #for control
fig.savefig('temp.png', dpi=fig.dpi)
figsize(width,height) 调整绘图的绝对尺寸并有助于确保两个绘图看起来相同。
正如另一个答案中所述,dpi 选项会影响文本的相对大小和线条笔触的宽度等。使用选项 dpi=fig.dpi确保 show() 和 savefig() 的相对大小相同。
或者,可以在创建后更改图形大小:
fig.set_size_inches(3, 6, forward=True)
forward 允许即时更改大小。
如果您在创建的图像中遇到过大边框的问题,您可以使用以下任一方法进行调整:
plt.tight_layout()
#or:
plt.tight_layout(pad=2)
或:
fig.savefig('temp.png', dpi=fig.dpi, bbox_inches='tight')
#or:
fig.savefig('temp.png', dpi=fig.dpi, bbox_inches='tight', pad_inches=0.5)
第一个选项只是最小化布局和边框,第二个选项允许手动调整边框。这些技巧至少帮助我解决了 savefig() 和 show() 图像不同的问题。
【讨论】:
【参考方案4】:我已经在我的 matplotlib 源代码中修复了这个问题,但这不是一个很好的修复。但是,如果您像我一样对图表的外观非常讲究,那就值得了。
问题似乎出在渲染后端;它们每个都得到了正确的线宽、字体大小等值,但是当呈现为 PDF 或 PNG 时比使用 show() 呈现时稍微大一些。
我在文件 matplotlib/backends/backend_agg.py 中添加了几行用于生成 PNG 的源代码。您可以对您使用的每个后端进行类似的更改,或者找到一种方法在单个位置进行更巧妙的更改;)
添加到我的 matplotlib/backends/backend_agg.py 文件中:
# The top of the file, added lines 42 - 44
42 # @warning: CHANGED FROM SOURCE to draw thinner lines
43 PATH_SCALAR = .8
44 FONT_SCALAR = .95
# In the draw_markers method, added lines 90 - 91
89 def draw_markers(self, *kl, **kw):
90 # @warning: CHANGED FROM SOURCE to draw thinner lines
91 kl[0].set_linewidth(kl[0].get_linewidth()*PATH_SCALAR)
92 return self._renderer.draw_markers(*kl, **kw)
# At the bottom of the draw_path method, added lines 131 - 132:
130 else:
131 # @warning: CHANGED FROM SOURCE to draw thinner lines
132 gc.set_linewidth(gc.get_linewidth()*PATH_SCALAR)
133 self._renderer.draw_path(gc, path, transform, rgbFace)
# At the bottom of the _get_agg_font method, added line 242 and the *FONT_SCALAR
241 font.clear()
242 # @warning: CHANGED FROM SOURCE to draw thinner lines
243 size = prop.get_size_in_points()*FONT_SCALAR
244 font.set_size(size, self.dpi)
所以这符合我现在的需要,但是,根据您正在做的事情,您可能希望在其他方法中实现类似的更改。或者找到一种更好的方法来做同样的事情,而不需要太多的换行!
更新: 在 Github 上向 matplotlib 项目发布问题后,我能够找到问题的根源:我更改了 matplotlibrc 文件中的 figure.dpi 设置。如果该值与默认值不同,我的 savefig() 图像会不同,即使我将 savefig dpi 设置为与图形 dpi 相同。因此,我没有像上面那样更改源,而是将 figure.dpi 设置保留为默认值 80,并且能够使用 savefig() 生成看起来像 show() 中的图像的图像。
Leon,您是否也更改了该设置?
【讨论】:
刚刚在这里添加了一个问题,希望可以创建更好的解决方案:github.com/matplotlib/matplotlib/issues/786以上是关于matplotlib savefig() 绘图不同于 show()的主要内容,如果未能解决你的问题,请参考以下文章
matplotlib和seaborn heatmap在Jupyter中呈现不同的savefig(标签截止)