在Matplotlib中设置绘图画布的大小

22

我希望Matplotlib/Pyplot能够生成具有一致画布大小的图表。也就是说,图形可以根据轴标注的不同占用不同的大小,但绘图区域(曲线绘制的矩形区域)的大小应始终保持相同。

是否有一种简单的方法来实现这一点? pyplot.figure() 的选项 figsize 似乎设置整个图形的大小,而不是画布的大小,因此每当轴描述占用更多或更少的空间时,我都会得到不同的画布大小。


有可能 gridspec 允许您控制您想要的内容(请参见此处的最后3个示例)。您能否添加一些示例,显示导致问题的不同轴描述? - Bonlenfum
这是MPL解耦描述绘制内容和如何绘制的代价。我相信手动完成这个过程,并刻意避免使用tight_layout,是最好的选择。 - tacaswell
2个回答

21
这是我对Matplotlib最大的不满之一。我经常处理栅格数据,在其中添加色图、图例和标题等,但从Matplotlib库中使用的任何简单示例都会导致分辨率不同,因此需要重新采样数据。特别是在进行图像分析时,您不希望有任何(不必要的)重新采样。
以下是我通常做的事情,尽管我很想知道是否有更简单或更好的方法。
首先载入一张图片并将其原样输出,分辨率相同:
import matplotlib.pyplot as plt
import urllib2

# load the image
img = plt.imread(urllib2.urlopen('http://upload.wikimedia.org/wikipedia/en/thumb/5/56/Matplotlib_logo.svg/500px-Matplotlib_logo.svg.png'))

# get the dimensions
ypixels, xpixels, bands = img.shape

# get the size in inches
dpi = 72.
xinch = xpixels / dpi
yinch = ypixels / dpi

# plot and save in the same size as the original
fig = plt.figure(figsize=(xinch,yinch))

ax = plt.axes([0., 0., 1., 1.], frameon=False, xticks=[],yticks=[])
ax.imshow(img, interpolation='none')

plt.savefig('D:\\mpl_logo.png', dpi=dpi, transparent=True)
注意,我手动定义了轴的位置,以使其覆盖整个图形。
与上面类似,您可以在图像周围添加一些边距,以便添加标签或色条等内容。
此示例在图像上方添加了20%的边距,然后用于绘制标题:
fig = plt.figure(figsize=(xinch,yinch/.8))

ax = plt.axes([0., 0., 1., .8], frameon=False, xticks=[],yticks=[])
ax.imshow(img, interpolation='none')
ax.set_title('Matplotlib is fun!', size=16, weight='bold')

plt.savefig('D:\\mpl_logo_with_title.png', dpi=dpi)

因此,图形的y尺寸(高度)增加,轴的y尺寸也同样减小。这将产生一个较大(总体)的输出图像,但轴区域仍将保持相同的大小。

如果有像.set_scale()这样的图形或轴属性来强制实现真正的1-on-x输出,那就太好了。


你能使用一些矢量格式吗?这样应该(我认为)可以将每个像素绘制成一个矩形。或者只是过度采样。 - tacaswell
3
谢谢,你的建议很有用!顺便说一下,我发现了一个稍微更加优雅的方法,就是在调用figure()后立即使用subplot_adjust(0,0,1,1)。这样,你不需要定义轴的位置,因为它们已经和图形一样大了。 最后,如果你不想手动指定边距,你可以在调用savefig()时使用bbox_inches='tight'参数。在这种情况下,绘图区域将完全由(xinch,yinch)定义,并且图形将足够大以容纳轴描述。 (正如tcaswell所指出的那样,请勿使用tight_layout!) - Dario
听起来确实更容易,谢谢你的建议。我稍后会尝试你的建议。 @tcaswell,谢谢,这在某些情况下可能有效,我认为pcolor应该可以很容易地做到这一点。不过其他的后处理可能会更困难。 - Rutger Kassies
@Dario 如果你这样做,那么你就把所有的轴标签都推出去了。如果你正在处理光栅图像,最好使用PIL来保存图像。 - tacaswell
@tcaswell 它会将标签推出,但如果您调用savefig(bbox_inches='tight'),则可以将它们恢复。或者我误解了您的意思? - Dario
@Dario 这是对系统的可怕滥用。这在每个后端上都有效吗? - tacaswell

4
您可以在Matplotlib rc中指定以下设置:
import matplotlib
matplotlib.rcParams['figure.figsize'] = [10, 10] # for square canvas
matplotlib.rcParams['figure.subplot.left'] = 0
matplotlib.rcParams['figure.subplot.bottom'] = 0
matplotlib.rcParams['figure.subplot.right'] = 1
matplotlib.rcParams['figure.subplot.top'] = 1

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