【问题标题】:matplotlib iterate subplot axis array through single listmatplotlib 通过单个列表迭代子图轴数组
【发布时间】:2013-11-29 15:18:13
【问题描述】:

是否有一种简单/干净的方法来迭代由子图返回的轴数组,如

nrow = ncol = 2
a = []
fig, axs = plt.subplots(nrows=nrow, ncols=ncol)
for i, row in enumerate(axs):
    for j, ax in enumerate(row):
        a.append(ax)

for i, ax in enumerate(a):
    ax.set_ylabel(str(i))

它甚至适用于nrowncol == 1

我尝试过这样的列表理解:

[element for tupl in tupleOfTuples for element in tupl]

但如果nrowsncols == 1 会失败

【问题讨论】:

    标签: python matplotlib


    【解决方案1】:

    ax 返回值是一个 numpy 数组,我相信它可以重新整形,而无需复制任何数据。如果您使用以下内容,您将获得一个可以干净地迭代的线性数组。

    nrow = 1; ncol = 2;
    fig, axs = plt.subplots(nrows=nrow, ncols=ncol)
    
    for ax in axs.reshape(-1): 
      ax.set_ylabel(str(i))
    

    这在 ncols 和 nrows 都为 1 时不成立,因为返回值不是数组;您可以将返回值转换为具有一个元素的数组以保持一致性,尽管它感觉有点像一个杂物:

    nrow = 1; ncol = 1;
    fig, axs = plt.subplots(nrows=nrow, ncols=nrow)
    axs = np.array(axs)
    
    for ax in axs.reshape(-1):
      ax.set_ylabel(str(i))
    

    reshape docs。 参数 -1 导致 reshape 推断输出的尺寸。

    【讨论】:

    • 对于nrow=ncol=1,您可以使用squeeze=0plt.subplots(nrows=nrow, ncols=nrow, squeeze=0) 始终为轴返回一个二维数组,即使两者都是一个。
    【解决方案2】:

    plt.subplots 的返回值 fig 包含所有轴的列表。要遍历图中的所有子图,您可以使用:

    nrow = 2
    ncol = 2
    fig, axs = plt.subplots(nrow, ncol)
    for i, ax in enumerate(fig.axes):
        ax.set_ylabel(str(i))
    

    这也适用于nrow == ncol == 1

    【讨论】:

    • 那么我们就不需要axs了吗?
    • 这太简单了,太有用了!
    【解决方案3】:

    我不确定它是何时添加的,但现在有一个 squeeze 关键字参数。这样可以确保结果始终是 2D numpy 数组。将其转换为一维数组很容易:

    fig, ax2d = subplots(2, 2, squeeze=False)
    axli = ax2d.flatten()
    

    适用于任意数量的子图,单斧没有技巧,所以比公认的答案要容易一些(也许当时squeeze 还不存在)。

    【讨论】:

    • 你的意思是ax2d.flatten() 在你的第二行吗?否则不清楚ax1d 引用的是什么。
    • @notlink 哦,是的,这更有意义
    【解决方案4】:

    Matplotlib 在轴上有自己的 flatten 函数。

    你为什么不试试下面的代码?

    fig, axes = plt.subplots(2, 3)
    for ax in axes.flat:
        ## do something with instance of 'ax'
    

    【讨论】:

    • .flat是numpy数组的一个属性,与matplotlib无关。
    • @ImportanceOfBeingErnest 感谢您纠正我的回答。我很困惑。
    【解决方案5】:

    TLDR; axes.flat 是最 Pythonic 的遍历轴的方式

    正如其他人指出的那样, plt.subplots() 的返回值是一个 Axes 对象的 numpy 数组,因此有大量内置的 numpy 方法用于展平数组。在这些选项中,axes.flat 是最不冗长的访问方法。此外,axes.flatten() 返回数组的 copy,而 axes.flat 返回数组的迭代器。这意味着从长远来看,axes.flat 会更有效率。

    窃取@Sukjun-Kim 的例子:

    fig, axes = plt.subplots(2, 3)
    for ax in axes.flat:
        ## do something with instance of 'ax'
    

    来源: axes.flat docs Matplotlib tutorial

    【讨论】:

      【解决方案6】:

      这是一个很好的做法:
      例如,我们需要一组 4 x 4 的子图,因此我们可以像下面这样拥有它们:

      rows = 4; cols = 4;
      fig, axes = plt.subplots(nrows=rows, ncols=cols, figsize=(20, 16), squeeze=0, sharex=True, sharey=True)
      axes = np.array(axes)
      
      for i, ax in enumerate(axes.reshape(-1)):
        ax.set_ylabel(f'Subplot: {i}')
      

      输出美观清晰。

      【讨论】:

        猜你喜欢
        • 2020-04-17
        • 2019-04-30
        • 1970-01-01
        • 1970-01-01
        • 2013-12-27
        • 2019-05-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多