如何消除子图之间的间隙
- 2025-03-05 09:14:00
- admin 原创
- 41
问题描述:
下面的代码在子图之间产生了间隙。如何消除子图之间的间隙并使图像成为紧密的网格?
import matplotlib.pyplot as plt
for i in range(16):
i = i + 1
ax1 = plt.subplot(4, 4, i)
plt.axis('on')
ax1.set_xticklabels([])
ax1.set_yticklabels([])
ax1.set_aspect('equal')
plt.subplots_adjust(wspace=None, hspace=None)
plt.show()
解决方案 1:
问题在于使用aspect='equal'
,这会阻止子图拉伸到任意纵横比并填满所有空白空间。
正常情况下,这样做是可行的:
import matplotlib.pyplot as plt
ax = [plt.subplot(2,2,i+1) for i in range(4)]
for a in ax:
a.set_xticklabels([])
a.set_yticklabels([])
plt.subplots_adjust(wspace=0, hspace=0)
结果是这样的:
但是,使用aspect='equal'
,如以下代码所示:
import matplotlib.pyplot as plt
ax = [plt.subplot(2,2,i+1) for i in range(4)]
for a in ax:
a.set_xticklabels([])
a.set_yticklabels([])
a.set_aspect('equal')
plt.subplots_adjust(wspace=0, hspace=0)
这是我们得到的:
第二种情况的不同之处在于,您强制 x 轴和 y 轴具有相同数量的单位/像素。由于轴默认从 0 到 1(即,在绘制任何内容之前),因此使用aspect='equal'
强制每个轴为正方形。由于图形不是正方形,pyplot 在水平方向上在轴之间添加了额外的间距。
为了解决这个问题,你可以将图形设置为正确的纵横比。我们将在这里使用面向对象的 pyplot 接口,我认为它总体上更优秀:
import matplotlib.pyplot as plt
fig = plt.figure(figsize=(8,8)) # Notice the equal aspect ratio
ax = [fig.add_subplot(2,2,i+1) for i in range(4)]
for a in ax:
a.set_xticklabels([])
a.set_yticklabels([])
a.set_aspect('equal')
fig.subplots_adjust(wspace=0, hspace=0)
结果如下:
解决方案 2:
您可以使用gridspec来控制轴之间的间距。 这里有更多信息。
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
plt.figure(figsize = (4,4))
gs1 = gridspec.GridSpec(4, 4)
gs1.update(wspace=0.025, hspace=0.05) # set the spacing between axes.
for i in range(16):
# i = i + 1 # grid spec indexes from 0
ax1 = plt.subplot(gs1[i])
plt.axis('on')
ax1.set_xticklabels([])
ax1.set_yticklabels([])
ax1.set_aspect('equal')
plt.show()
解决方案 3:
无需完全使用gridspec,也可以通过将wspace和hspace设置为零来消除间隙:
import matplotlib.pyplot as plt
plt.clf()
f, axarr = plt.subplots(4, 4, gridspec_kw = {'wspace':0, 'hspace':0})
for ax in axarr.flatten():
ax.grid('on', linestyle='--')
ax.set_xticklabels([])
ax.set_yticklabels([])
plt.show()
plt.close()
导致:
解决方案 4:
对于较新版本的 matplotlib,你可能想要尝试Constrained Layout。但是,这确实(或至少曾经)不起作用plt.subplot()
,因此你需要改用plt.subplots()
:
fig, axs = plt.subplots(4, 4, constrained_layout=True)
解决方案 5:
你试过嗎plt.tight_layout()
?
有无plt.tight_layout()
它:
或者:像这样(使用add_axes
)
left=[0.1,0.3,0.5,0.7]
width=[0.2,0.2, 0.2, 0.2]
rectLS=[]
for x in left:
for y in left:
rectLS.append([x, y, 0.2, 0.2])
axLS=[]
fig=plt.figure()
axLS.append(fig.add_axes(rectLS[0]))
for i in [1,2,3]:
axLS.append(fig.add_axes(rectLS[i],sharey=axLS[-1]))
axLS.append(fig.add_axes(rectLS[4]))
for i in [1,2,3]:
axLS.append(fig.add_axes(rectLS[i+4],sharex=axLS[i],sharey=axLS[-1]))
axLS.append(fig.add_axes(rectLS[8]))
for i in [5,6,7]:
axLS.append(fig.add_axes(rectLS[i+4],sharex=axLS[i],sharey=axLS[-1]))
axLS.append(fig.add_axes(rectLS[12]))
for i in [9,10,11]:
axLS.append(fig.add_axes(rectLS[i+4],sharex=axLS[i],sharey=axLS[-1]))
如果你不需要共享轴,那么只需axLS=map(fig.add_axes, rectLS)
解决方案 6:
另一种方法是使用pad
关键字 from plt.subplots_adjust()
,它也接受负值:
import matplotlib.pyplot as plt
ax = [plt.subplot(2,2,i+1) for i in range(4)]
for a in ax:
a.set_xticklabels([])
a.set_yticklabels([])
plt.subplots_adjust(pad=-5.0)
此外,要去除所有子图(即画布)外边缘的白色,请始终使用 进行保存plt.savefig(fname, bbox_inches="tight")
。
解决方案 7:
Matplotlib 将检查“subplotpars”参数来定义子图位置。因此这应该有效:
left = 0.03 #The position of the left edge of the subplots, as a fraction of the figure width.
bottom = 0.05 #The position of the bottom edge of the subplots, as a fraction of the figure height.
right = 0.99 #The position of the right edge of the subplots, as a fraction of the figure width.
top = 0.97 #The position of the top edge of the subplots, as a fraction of the figure height.
wspace = None #The width of the padding between subplots, as a fraction of the average Axes width.
hspace = None #The height of the padding between subplots, as a fraction of the average Axes height.
fig.subplotpars.update(left, bottom, right, top, wspace, hspace)
您可以根据需要单独调整上述参数(0 到 1 之间)。
解决方案 8:
如果在实施 apdnu 的答案后仍然得到图像列之间的水平间距,请尝试fig.subplots_adjust(wspace = -0.8)
(您可以通过尝试另一个负数来调整它)。
前任:
fig, axes = plt.subplots(nrows = 10, ncols = 10)
fig.subplots_adjust(hspace=0, wspace=-0.8)
for i, ax in enumerate(fig.axes):
ax.set_xticklabels([])
ax.set_yticklabels([])
ax.axis('off')
#imageGrid has dimensions 100 x 1 x 32 x 32
ax.imshow(imageGrid[i][0])
结果: