将 matplotlib 网格中子图的底行居中

问题描述 投票:0回答:1

如果我想展示 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()

给了我这个情节: enter image description here

但我不知道如何将底行居中。

我尝试使用 gridspec,创建一个 2x1 网格,然后将顶行放在主网格的顶部单元格中,将底行放在底部单元格中,但这只是拉伸了底部的图,因此它们占据了整个网格最下面一排。是否可以使所有图保持相同大小,但将底部两个居中?

python matplotlib plot layout
1个回答
0
投票

您必须使用

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 个图:

enter image description here

(2, 3) 网格上的 4 个图:

enter image description here

(3, 5) 网格上有 12 个图:

enter image description here

(3, 6) 网格上有 14 个图:

enter image description here

作为函数

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])
© www.soinside.com 2019 - 2024. All rights reserved.