将matplotlib子图保存为图像文件

6
我对matplotlib还比较新,进展缓慢。话虽如此,我还没有找到一个明显的答案来解决这个问题。
我想要给散点图按组着色,看起来通过循环绘制是可行的方法。
以下是我根据上面提供的第一个链接创建的可复现示例:
import matplotlib.pyplot as plt
import pandas as pd
from pydataset import data

df = data('mtcars').iloc[0:10]
df['car'] = df.index

fig, ax = plt.subplots(1)
plt.figure(figsize=(12, 9))
for ind in df.index:
    ax.scatter(df.loc[ind, 'wt'], df.loc[ind, 'mpg'], label=ind)
ax.legend(bbox_to_anchor=(1.05, 1), loc=2)
# plt.show()
# plt.savefig('file.png')

取消注释plt.show()会得到我想要的结果。

good plot

搜索一番,看起来plt.savefig()是保存文件的方法;如果我重新注释掉plt.show()并运行plt.savefig(),得到的是一张空白的图片。这个问题表明在调用savefig()之前调用show()可能会导致这个问题,但是我已经完全注释掉了它。另一个问题中有一个评论建议我可以直接保存ax对象,但是那样会截断我的图例:

chopped legend

同一个问题有一个替代方案,可以使用 fig.savefig()。我得到了相同的被截断的图例。
这里有一个相关的问题,但我没有直接绘制一个 DataFrame,所以不确定如何应用答案(其中 dtf 是他们正在绘制的 pd.DataFrame)。
plot = dtf.plot()
fig = plot.get_figure()
fig.savefig("output.png")

谢谢任何建议。


编辑:为了测试下面的建议,尝试使用tight_layout(),我运行了这个命令,但仍然得到一个空白的白色图像文件:

fig, ax = plt.subplots(1)
plt.figure(figsize=(12, 9))
for ind in df.index:
    ax.scatter(df.loc[ind, 'wt'], df.loc[ind, 'mpg'], label=ind)
ax.legend(bbox_to_anchor=(1.05, 1), loc=2)
fig.tight_layout()
plt.savefig('test.png')

你尝试过使用 plt.tight_layout() 吗?这可能会有所帮助。 - lkriener
好吧,这有点作弊,但你可以尝试更改图形的大小 plt.figure(figsize=(20,10)) - lkriener
@lkriener 基于您的 tight_layout 建议,我更新了回答并提供了我正在运行的内容。一个答案(即使只是草稿)或者要点概括将会非常有帮助以确保我们之间的理解是相同的。我的意思是,我认为我在两者结合起来使用。 - Hendy
@ImportanceOfBeingErnest,你看过代码了吗?这里没有包含彩色分组。如果需要的话,我可以更新为更简单的东西。我来自于 R,在那里 data(mtcars) 是相当标准的。我不知道在 python 中这是常见的做法。 - Hendy
1
问题与“彩色组”完全无关。请将其删除。请参见[mcve]。无论如何,我在下面给出了解决方案。 - ImportanceOfBeingErnest
显示剩余7条评论
2个回答

10

移除 plt.figure(figsize=(12, 9)) 这一行代码,它将按预期工作。也就是在调用 show 之前调用 savefig

问题在于被保存的图形是由 plt.figure() 创建的,而所有数据都是绘制在之前创建的 ax 上(在另一个图形中,而不是正在保存的那个)。

如果要保存包括图例在内的图形,请使用 bbox_inches="tight" 选项。

plt.savefig('test.png', bbox_inches="tight")

当然,直接保存图形对象也是同样可能的。


fig.savefig('test.png', bbox_inches="tight")

想要更深入地了解如何将图例移出绘图区,请参见此答案


1
在 @ImportanceOfBeingErnest 的答案上补充一点,当 bbox_inches='tight' 时,'pad_inches=0.1' 可能需要设置为更大的值。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接