我正在做一个项目,在这个项目中我需要把10行3列的绘图网格放在一起。虽然我已经能够绘制出图并排列出子图,但是没有空白,我无法生成一个很好的图,比如下面这张来自gridspec documentatationpython - 如何删除matplotlib.pyplot中子图之间的空间?-LMLPHP的空白图。
我尝试了下面的文章,但仍然无法完全删除示例图像中的空白。有人能给我一些指导吗?谢谢!
Matplotlib different size subplots
how to remove “empty” spacebetween subplots?
这是我的图片:python - 如何删除matplotlib.pyplot中子图之间的空间?-LMLPHP
下面是我的代码。The full script is here on GitHub
注:图像_2和图像_愚人都是形状为(1032,10)的扁平图像的麻木阵列,而delta是形状为(28,28)的图像阵列。

def plot_im(array=None, ind=0):
    """A function to plot the image given a images matrix, type of the matrix: \
    either original or fool, and the order of images in the matrix"""
    img_reshaped = array[ind, :].reshape((28, 28))
    imgplot = plt.imshow(img_reshaped)

# Output as a grid of 10 rows and 3 cols with first column being original, second being
# delta and third column being adversaril
nrow = 10
ncol = 3
n = 0

from matplotlib import gridspec
fig = plt.figure(figsize=(30, 30))
gs = gridspec.GridSpec(nrow, ncol, width_ratios=[1, 1, 1])

for row in range(nrow):
    for col in range(ncol):
        plt.subplot(gs[n])
        if col == 0:
            #plt.subplot(nrow, ncol, n)
            plot_im(array=images_2, ind=row)
        elif col == 1:
            #plt.subplot(nrow, ncol, n)
            plt.imshow(w_delta)
        else:
            #plt.subplot(nrow, ncol, n)
            plot_im(array=images_fool, ind=row)
        n += 1

plt.tight_layout()
#plt.show()
plt.savefig('grid_figure.pdf')

最佳答案

开始时要注意的一点是:如果您想完全控制间距,请避免使用plt.tight_layout(),因为它会尝试将图形中的绘图分割成均匀且良好的分布。这基本上是很好的,可以产生令人满意的结果,但是可以随意调整间距。
您引用Matplotlib示例库中的gridspec示例效果很好的原因是子批次的方面没有预先定义。也就是说,子块只会在网格上展开,并使设置的间距(在本例中为wspace=0.0, hspace=0.0)独立于图形大小。
与此相反,您使用imshow绘制图像,并且默认情况下图像的纵横比设置为相等(相当于ax.set_aspect("equal"))。也就是说,您当然可以将set_aspect("auto")放到每个图中(另外还可以将wspace=0.0, hspace=0.0作为参数添加到gridspec中,如Gallery示例中所示),这样可以生成一个不带间距的图。
然而,当使用图像时,保持相同的纵横比是很有意义的,这样每一个像素都像高一样宽,一个正方形阵列显示为一个正方形图像。
然后,您需要做的是利用图像大小和图形边界来获得预期的结果。figure的参数是以英寸为单位的数字(宽度、高度),这里可以播放两个数字的比率。并且可以手动调整子批次参数figsize以获得所需的结果。
下面是一个例子:

import numpy as np
import matplotlib.pyplot as plt
from matplotlib import gridspec

nrow = 10
ncol = 3

fig = plt.figure(figsize=(4, 10))

gs = gridspec.GridSpec(nrow, ncol, width_ratios=[1, 1, 1],
         wspace=0.0, hspace=0.0, top=0.95, bottom=0.05, left=0.17, right=0.845)

for i in range(10):
    for j in range(3):
        im = np.random.rand(28,28)
        ax= plt.subplot(gs[i,j])
        ax.imshow(im)
        ax.set_xticklabels([])
        ax.set_yticklabels([])

#plt.tight_layout() # do not use this!!
plt.show()

python - 如何删除matplotlib.pyplot中子图之间的空间?-LMLPHP
编辑:
当然,不必手动调整参数。因此,我们可以根据行和列的数量来计算一些最佳的值。
nrow = 7
ncol = 7

fig = plt.figure(figsize=(ncol+1, nrow+1))

gs = gridspec.GridSpec(nrow, ncol,
         wspace=0.0, hspace=0.0,
         top=1.-0.5/(nrow+1), bottom=0.5/(nrow+1),
         left=0.5/(ncol+1), right=1-0.5/(ncol+1))

for i in range(nrow):
    for j in range(ncol):
        im = np.random.rand(28,28)
        ax= plt.subplot(gs[i,j])
        ax.imshow(im)
        ax.set_xticklabels([])
        ax.set_yticklabels([])

plt.show()

10-06 07:07