子图:tight_layout改变图形大小

时间:2014-03-03 11:01:07

标签: python subplot

使用tight_layout(h_pad = -1)更改两个子图之间的垂直距离会更改总图形大小。如何使用tight_layout定义figureize?

以下是代码:

#define figure
pl.figure(figsize=(10, 6.25))

ax1=subplot(211)
img=pl.imshow(np.random.random((10,50)), interpolation='none')
ax1.set_xticklabels(()) #hides the tickslabels of the first plot

subplot(212)
x=linspace(0,50)
pl.plot(x,x,'k-')
xlim( ax1.get_xlim() ) #same x-axis for both plots

以下是结果:

如果我写

pl.tight_layout(h_pad=-2)

在最后一行,然后我明白了:

enter image description here

如你所见,这个数字更大......

2 个答案:

答案 0 :(得分:1)

您可以使用GridSpec对象精确控制宽度和高度比率,如on this threaddocumented here所示。

尝试使用您的代码,我可以使用height_ratio为上部子图分配两倍的空间,并将h_pad参数增加到{{1}打电话。这听起来并不完全正确,但也许你可以进一步调整......

tight_layout

还有其他问题,例如纠正导入,添加numpy以及绘制到import numpy as np from matplotlib.pyplot import * import matplotlib.pyplot as pl import matplotlib.gridspec as gridspec #define figure fig = pl.figure(figsize=(10, 6.25)) gs = gridspec.GridSpec(2, 1, height_ratios=[2,1]) ax1=subplot(gs[0]) img=pl.imshow(np.random.random((10,50)), interpolation='none') ax1.set_xticklabels(()) #hides the tickslabels of the first plot ax2=subplot(gs[1]) x=np.linspace(0,50) ax2.plot(x,x,'k-') xlim( ax1.get_xlim() ) #same x-axis for both plots fig.tight_layout(h_pad=-5) show() 而不是直接使用ax2。我看到的输出是:

Corrected figure

答案 1 :(得分:0)

这种情况很特殊,因为图像和绘图的默认纵横比不同。因此,对于希望删除仅由图像或仅由图组成的子图网格中的空格的人来说,值得注意的是,您可能会在此问题的答案(以及与之相关的答案中找到合适的解决方案):{{3} }.

此特定示例中子图的纵横比如下:

# Default aspect ratio of images:
ax1.get_aspect()
# 1.0

# Which is as it is expected based on the default settings in rcParams file:
matplotlib.rcParams['image.aspect']
# 'equal'
# Default aspect ratio of plots:
ax2.get_aspect()
# 'auto'

ax1 的大小及其下方的空间根据沿 x 轴(即宽度)的像素数自动调整,以保持“相等”的纵横比,同时将两个子图拟合到数字。正如您所提到的,使用 How to remove the space between subplots in matplotlib.pyplot? 或类似的 fig.tight_layout(h_pad=xxx) 不是一个好的选择,因为这会使数字更大。

要在保留原始图形大小的同时消除间隙,您可以使用 fig.subplots_adjust(hspace=xxx) 或等效的 plt.subplots(gridspec_kw=dict(hspace=xxx)),如下例所示:

import numpy as np                 # v 1.19.2
import matplotlib.pyplot as plt    # v 3.3.2
np.random.seed(1)

fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(10, 6.25),
                               gridspec_kw=dict(hspace=-0.206))

# For those not using plt.subplots, you can use this instead:
# fig.subplots_adjust(hspace=-0.206)

size = 50
ax1.imshow(np.random.random((10, size)))
ax1.xaxis.set_visible(False)

# Create plot of a line that is aligned with the image above
x = np.arange(0, size)
ax2.plot(x, x, 'k-')
ax2.set_xlim(ax1.get_xlim())

plt.show()

fig.set_constrained_layout_pads(hspace=xxx)

我不知道有什么方法可以自动定义适当的 hspace,以便可以消除任何图像宽度的间隙。如 no_hspace 的文档字符串所述,它对应于 子图之间填充的高度,作为平均轴高度的一部分。因此,我尝试通过将子图之间的间隙除以两个子图的平均高度来计算 hspace,如下所示:

# Extract axes positions in figure coordinates
ax1_x0, ax1_y0, ax1_x1, ax1_y1 = np.ravel(ax1.get_position())
ax2_x0, ax2_y0, ax2_x1, ax2_y1 = np.ravel(ax2.get_position())

# Compute negative hspace to close the vertical gap between subplots
ax1_h = ax1_y1-ax1_y0
ax2_h = ax2_y1-ax2_y0
avg_h = (ax1_h+ax2_h)/2
gap = ax1_y0-ax2_y1
hspace=-(gap/avg_h) # this divided by 2 also does not work

fig.subplots_adjust(hspace=hspace)

不幸的是,这不起作用。也许其他人对此有解决方案。

还值得一提的是,我尝试通过编辑 y 位置来消除子图之间的间隙,如本例所示:

# Extract axes positions in figure coordinates
ax1_x0, ax1_y0, ax1_x1, ax1_y1 = np.ravel(ax1.get_position())
ax2_x0, ax2_y0, ax2_x1, ax2_y1 = np.ravel(ax2.get_position())

# Set new y positions: shift ax1 down over gap
gap = ax1_y0-ax2_y1
ax1.set_position([ax1_x0, ax1_y0-gap, ax1_x1, ax1_y1-gap])
ax2.set_position([ax2_x0, ax2_y0, ax2_x1, ax2_y1])

不幸的是,这(及其变体)产生了看似不可预测的结果,包括与使用 fig.tight_layout() 时类似的图形大小调整。也许其他人对幕后发生的事情有一个解释。