如果我想展示 5 个图,是否可以将它们分成 2 行,顶行有 3 个图,底行有 2 个图,但底行居中?
我可以将它们绘制为顶部 3、底部 2,但我不知道如何将底行居中。
例如:
import matplotlib.pyplot as plt
fig, axs = plt.subplots(2, 3, figsize=(10,5), sharey=True)
for i in range(5):
row,col = divmod(i,3)
axs[row,col].plot([0, 1], [0, i])
fig.delaxes(axs[1,2])
plt.tight_layout()
plt.show()
但我不知道如何将底行居中。
我尝试使用 gridspec,创建一个 2x1 网格,然后将顶行放在主网格的顶部单元格中,将底行放在底部单元格中,但这只是拉伸了底部的图,因此它们占据了整个网格最下面一排。是否可以使所有图保持相同大小,但将底部两个居中?
GridSpec
设置自定义布局。为每个顶行列分配 2 个虚拟列,以便能够移动最后一行上的图形,并可能有半个图形偏移。
剩下的只是仔细计算位置:
from matplotlib.gridspec import GridSpec
# defining grid and number of plots
rows, cols = 3, 5
n_plots = 12
axs = np.full((rows, cols), None)
fig = plt.figure(figsize=(5, 3))
gs = GridSpec(rows, cols*2)
full_rows = n_plots//cols
extra = cols - n_plots % cols
for i in range(n_plots):
r, c = divmod(i, cols)
if r < full_rows:
axs[r, c] = fig.add_subplot(gs[r, 2*c:2*(c+1)], sharey=axs[0, 0] if i else None)
else:
axs[r, c] = fig.add_subplot(gs[r, 2*c+extra:2*(c+1)+extra], sharey=axs[0, 0] if i else None)
if c:
plt.setp(axs[r, c].get_yticklabels(), visible=False)
# plotting demo
for i in range(n_plots):
row,col = divmod(i, cols)
axs[row,col].plot([0, 1], [0, i])
fig.tight_layout()
fig.subplots_adjust(wspace=0.5)
(2, 3) 网格上有 5 个图:
(2, 3) 网格上的 4 个图:
(3, 5) 网格上有 12 个图:
(3, 6) 网格上有 14 个图:
def custom_layout(n_plots, cols, fig_kwargs={}):
import math
rows = math.ceil(n_plots/cols)
axs = np.full((rows, cols), None)
fig = plt.figure(**fig_kwargs)
gs = GridSpec(rows, cols*2)
full_rows = n_plots//cols
extra = cols - n_plots % cols
for i in range(n_plots):
r, c = divmod(i, cols)
if r < full_rows:
axs[r, c] = fig.add_subplot(gs[r, 2*c:2*(c+1)], sharey=axs[0, 0] if i else None)
else:
axs[r, c] = fig.add_subplot(gs[r, 2*c+extra:2*(c+1)+extra], sharey=axs[0, 0] if i else None)
if c:
plt.setp(axs[r, c].get_yticklabels(), visible=False)
return fig, axs
fig, axs = custom_layout(n_plots=5, cols=3, fig_kwargs={'figsize': (5, 3)})
for i, ax in enumerate(axs.flat):
if ax:
ax.plot([0, 1], [0, i])