Matplotlib - 将子图添加到子图中?

Posted

技术标签:

【中文标题】Matplotlib - 将子图添加到子图中?【英文标题】:Matplotlib - adding subplots to a subplot? 【发布时间】:2016-04-28 07:08:43 【问题描述】:

我正在尝试创建一个由 2x2 网格组成的图形,其中每个象限中有 2 个垂直堆叠的子图(即 2x1 网格)。不过,我似乎无法弄清楚如何实现这一目标。

我得到的最接近的是使用 gridspec 和一些丑陋的代码(见下文),但因为 gridspec.update(hspace=X) 改变了所有子图的间距,我仍然不是我想要的。

理想情况下,我想要的是,以下图为例,减小每个象限内子图之间的间距,同时增加顶部和底部象限之间的垂直间距(即在 1-3 和 2-4 之间) .

有没有办法做到这一点(使用或不使用 gridspec)?我最初设想的是生成每个子图网格(即每个 2x1 网格)并将它们插入到更大的 2x2 子图网格中,但我还没有弄清楚如何将子图添加到子图,如果甚至离开。

import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
plt.figure(figsize=(10, 8))
gs = gridspec.GridSpec(4,2)
gs.update(hspace=0.4)
for i in range(2):
    for j in range(4):
        ax = plt.subplot(gs[j,i])
        ax.spines['top'].set_visible(False)
        ax.spines['right'].set_visible(False)
        plt.tick_params(which='both', top='off', right='off')
        if j % 2 == 0:
            ax.set_title(str(i+j+1))
            ax.plot([1,2,3], [1,2,3])
            ax.spines['bottom'].set_visible(False)
            ax.get_xaxis().set_visible(False)   
        else:
            ax.plot([1,2,3], [3,2,1])

【问题讨论】:

【参考方案1】:

您可以nest your GridSpec using SubplotSpec。外部网格为 2 x 2,内部网格为 2 x 1。下面的代码应该可以为您提供基本概念。

import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec

fig = plt.figure(figsize=(10, 8))
outer = gridspec.GridSpec(2, 2, wspace=0.2, hspace=0.2)

for i in range(4):
    inner = gridspec.GridSpecFromSubplotSpec(2, 1,
                    subplot_spec=outer[i], wspace=0.1, hspace=0.1)

    for j in range(2):
        ax = plt.Subplot(fig, inner[j])
        t = ax.text(0.5,0.5, 'outer=%d, inner=%d' % (i, j))
        t.set_ha('center')
        ax.set_xticks([])
        ax.set_yticks([])
        fig.add_subplot(ax)

fig.show()

【讨论】:

而不是 a 内 b ,跨越网格并调整 matplotlib.org/users/gridspec.html 如何修改它以使子网格中的所有子图共享相同的 x 和 y 轴?【参考方案2】:

您现在可以使用figure.subfigure 嵌套子图:https://matplotlib.org/stable/gallery/subplots_axes_and_figures/subfigures.html

你也可以很好地使用 subplot_mosaic,因为它支持嵌套: https://matplotlib.org/stable/tutorials/provisional/mosaic.html

虽然嵌套总是有点痛苦,但可以说这两种方法都使过程更容易、更灵活。

取自上面的例子:

import matplotlib.pyplot as plt

fig = plt.figure(constrained_layout=True)

subfigs = fig.subfigures(2, 2)

for outerind, subfig in enumerate(subfigs.flat):
    subfig.suptitle(f'Subfig outerind')
    axs = subfig.subplots(2, 1)
    for innerind, ax in enumerate(axs.flat):
        ax.set_title(f'outer=outerind, inner=innerind', fontsize='small')
        ax.set_xticks([])
        ax.set_yticks([])
 
plt.show()

【讨论】:

【参考方案3】:

由于我不得不依赖 Suever 的回答,但必须根据自己的需要对其进行修改,我想我可能会做出贡献,以防有人觉得它有帮助:

import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec

channelArrangement = [16, 17, 18 , 19 , 22, 25, 28 , 29 , 31]

fig = plt.figure(figsize=(10, 8))
outer = gridspec.GridSpec(1, 2, wspace=0.2, hspace=0.2)

for i in range(2):
    inner = gridspec.GridSpecFromSubplotSpec(3, 3, subplot_spec=outer[i],
                                             wspace=0.1, hspace=0.1)
    row     = 0
    col     = 0
    maxCol  = 3

    for chan in channelArrangement:
        ax = plt.Subplot(fig, inner[row,col])
        t= ax.text(0.5,0.5, 'outer=%d\nrow=%d\ncol=%d' % (i,row,col))
        ax.set_xticks([])
        ax.set_yticks([])
        t.set_ha('center')
        fig.add_subplot(ax)
        col += 1
        if col == maxCol:
            col = 0
            row += 1
plt.show()

【讨论】:

【参考方案4】:

将子图添加到子图的简单方法是将图形划分为子图,然后向它们添加子图。

import matplotlib.pyplot as plt

fig = plt.figure(constrained_layout=True,figsize=(10,10))
subplots = fig.subfigures(2,2)

ax0 = subplots[0][0].subplots(2,1)
ax1 = subplots[0][1].subplots(2,1)
ax2 = subplots[1][0].subplots(2,1)
ax3 = subplots[1][1].subplots(2,1)

plt.show()

可以参考这个 Matplotlib 官方文档here

希望对你有所帮助。

【讨论】:

以上是关于Matplotlib - 将子图添加到子图中?的主要内容,如果未能解决你的问题,请参考以下文章

尝试将 3d 子图添加到 matplotlib 图

Matplotlib“实时”在python中绘图

在子图 Matplotlib 中按列表添加图例

python使用matplotlib可视化subplots绘制子图自定义几行几列子图,如果M行N列,那么最终包含M*N个子图在指定的子图中添加可视化结果

在Matplotlib中为子图添加边距[重复]

在带有子图的 geopandas 图中添加图例会改变图的大小