设置 matplotlib 子图的绝对大小
Set absolute size of matplotlib subplots
我知道如何使用 gridspec 或 subplots_adjust 设置图形中子图的相对大小,并且我知道如何使用 figsize 设置图形的大小。我的问题是设置子图的绝对大小。
用例: 我正在制作两个单独的图,它们将保存为学术论文的 pdf 文件。一个有两个子图,一个有三个子图(两种情况都在 1 行中)。我需要 5 个子图中的每一个在生成的 PDF 中具有完全相同的大小和完全相同的字体大小(轴标签、刻度标签等)。在下面的示例中,字体大小相同,但子图不同。如果我使生成的 PDF 的高度相同(因此轴),则 3-subplots.pdf 上的字体小于 2-subplots.pdf.
上的字体
MWE:
import matplotlib.pyplot as plt
subplots = [2, 3]
for i, cols in enumerate(subplots):
fig, ax = plt.subplots(1, cols, sharey=True, subplot_kw=dict(box_aspect=1))
for j in range(cols):
ax[j].set_title(f'plot {j*cols}')
ax[j].set_xlabel('My x label')
ax[0].set_ylabel('My y label')
plt.tight_layout()
plt.savefig(f'{cols}-subplots.pdf', bbox_inches='tight', pad_inches=0)
plt.show()
输出:
我更喜欢使用 fig.add_axes([left, bottom, width, height])
,它可以让您精确控制每个子图的大小和位置。 left
和 bottom
决定子图的位置,而 width
和 height
决定大小。所有数量都是图形宽度和高度的分数,因此它们都在 0 和 1 之间浮动。
一个例子:
fig = plt.figure(figsize=(8.3, 11.7))
axs = {
"ax1": fig.add_axes([0.2, 0.7, 0.6, 0.2], xticklabels=[]),
"ax2": fig.add_axes([0.2, 0.49, 0.6, 0.2], xticklabels=[]),
"ax3": fig.add_axes([0.2, 0.28, 0.6, 0.2]),
}
有了这个,我在一张A4尺寸的图中创建了3个子图,每个子图的宽度为0.6x8.3,高度为0.2x11.7。它们之间的间距为 0.1x11.7。 "ax1"
和 "ax2"
不显示 xticklabels 以便我稍后可以为它们设置共享 x 刻度。
您可以查看 matplotlib API 参考以获取更多信息https://matplotlib.org/stable/api/figure_api.html
我最终通过以下方式解决了这个问题:
- 设置子图 width/height 的显式绝对长度,子图之间的 space 和子图外部的 space,
- 将它们相加得到绝对数字大小,
- 将子图 box_aspect 设置为 1 以使其保持正方形。
import matplotlib.pyplot as plt
num_subplots = [2, 3]
scale = 1 # scaling factor for the plot
subplot_abs_width = 2*scale # Both the width and height of each subplot
subplot_abs_spacing_width = 0.2*scale # The width of the spacing between subplots
subplot_abs_excess_width = 0.3*scale # The width of the excess space on the left and right of the subplots
subplot_abs_excess_height = 0.3*scale # The height of the excess space on the top and bottom of the subplots
for i, cols in enumerate(num_subplots):
fig_width = (cols * subplot_abs_width) + ((cols-1) * subplot_abs_spacing_width) + subplot_abs_excess_width
fig_height = subplot_abs_width+subplot_abs_excess_height
fig, ax = plt.subplots(1, cols, sharey=True, figsize=(fig_width, fig_height), subplot_kw=dict(box_aspect=1))
for j in range(cols):
ax[j].set_title(f'plot {j}')
ax[j].set_xlabel('My x label')
ax[0].set_ylabel('My y label')
plt.tight_layout()
plt.savefig(f'{cols}-subplots.pdf', bbox_inches='tight', pad_inches=0)
plt.show()
我知道如何使用 gridspec 或 subplots_adjust 设置图形中子图的相对大小,并且我知道如何使用 figsize 设置图形的大小。我的问题是设置子图的绝对大小。
用例: 我正在制作两个单独的图,它们将保存为学术论文的 pdf 文件。一个有两个子图,一个有三个子图(两种情况都在 1 行中)。我需要 5 个子图中的每一个在生成的 PDF 中具有完全相同的大小和完全相同的字体大小(轴标签、刻度标签等)。在下面的示例中,字体大小相同,但子图不同。如果我使生成的 PDF 的高度相同(因此轴),则 3-subplots.pdf 上的字体小于 2-subplots.pdf.
上的字体MWE:
import matplotlib.pyplot as plt
subplots = [2, 3]
for i, cols in enumerate(subplots):
fig, ax = plt.subplots(1, cols, sharey=True, subplot_kw=dict(box_aspect=1))
for j in range(cols):
ax[j].set_title(f'plot {j*cols}')
ax[j].set_xlabel('My x label')
ax[0].set_ylabel('My y label')
plt.tight_layout()
plt.savefig(f'{cols}-subplots.pdf', bbox_inches='tight', pad_inches=0)
plt.show()
输出:
我更喜欢使用 fig.add_axes([left, bottom, width, height])
,它可以让您精确控制每个子图的大小和位置。 left
和 bottom
决定子图的位置,而 width
和 height
决定大小。所有数量都是图形宽度和高度的分数,因此它们都在 0 和 1 之间浮动。
一个例子:
fig = plt.figure(figsize=(8.3, 11.7))
axs = {
"ax1": fig.add_axes([0.2, 0.7, 0.6, 0.2], xticklabels=[]),
"ax2": fig.add_axes([0.2, 0.49, 0.6, 0.2], xticklabels=[]),
"ax3": fig.add_axes([0.2, 0.28, 0.6, 0.2]),
}
有了这个,我在一张A4尺寸的图中创建了3个子图,每个子图的宽度为0.6x8.3,高度为0.2x11.7。它们之间的间距为 0.1x11.7。 "ax1"
和 "ax2"
不显示 xticklabels 以便我稍后可以为它们设置共享 x 刻度。
您可以查看 matplotlib API 参考以获取更多信息https://matplotlib.org/stable/api/figure_api.html
我最终通过以下方式解决了这个问题:
- 设置子图 width/height 的显式绝对长度,子图之间的 space 和子图外部的 space,
- 将它们相加得到绝对数字大小,
- 将子图 box_aspect 设置为 1 以使其保持正方形。
import matplotlib.pyplot as plt
num_subplots = [2, 3]
scale = 1 # scaling factor for the plot
subplot_abs_width = 2*scale # Both the width and height of each subplot
subplot_abs_spacing_width = 0.2*scale # The width of the spacing between subplots
subplot_abs_excess_width = 0.3*scale # The width of the excess space on the left and right of the subplots
subplot_abs_excess_height = 0.3*scale # The height of the excess space on the top and bottom of the subplots
for i, cols in enumerate(num_subplots):
fig_width = (cols * subplot_abs_width) + ((cols-1) * subplot_abs_spacing_width) + subplot_abs_excess_width
fig_height = subplot_abs_width+subplot_abs_excess_height
fig, ax = plt.subplots(1, cols, sharey=True, figsize=(fig_width, fig_height), subplot_kw=dict(box_aspect=1))
for j in range(cols):
ax[j].set_title(f'plot {j}')
ax[j].set_xlabel('My x label')
ax[0].set_ylabel('My y label')
plt.tight_layout()
plt.savefig(f'{cols}-subplots.pdf', bbox_inches='tight', pad_inches=0)
plt.show()