【问题标题】:Python subplot used to show one figure用于显示一个图形的 Python 子图
【发布时间】:2019-08-13 18:24:28
【问题描述】:

当我使用子图时,尝试使用下面的子图只绘制一个图形,它会报错:

AttributeError: 'AxesSubplot' 对象没有属性 'flat'

fig, ax = plt.subplots(nrows=nrows, ncols=ncols,figsize=figsize)
for i, ax in enumerate(ax.flat):
    ax.plot(X, Y, color='k')

如果我想任意设置子图的个数怎么解决这个问题?ax.flat怎么容易理解?

【问题讨论】:

  • 为什么不用 enumerate(ax)?

标签: python matplotlib ipython spyder


【解决方案1】:

代码只有一种情况

fig, ax = plt.subplots(nrows=nrows, ncols=ncols,figsize=figsize)
for i, ax in enumerate(ax.flat):
    ax.plot(X, Y, color='k')

无法按预期工作。这是给nrows = ncols = 1的。这是因为对于单个行和列,ax 是单个子图,而不是多个子图的数组。

要避免这个问题,并且能够在不知道nrowsncols 的情况下使用相同的代码,请使用squeeze=False 选项。这将确保ax 始终是一个数组,因此具有.flat 属性。为了更好地理解,请勿使用与坐标区本身相同的名称来调用坐标区数组。

fig, axs = plt.subplots(nrows=nrows, ncols=ncols, squeeze=False, figsize=figsize)
for i, ax in enumerate(axs.flat):
    ax.plot(X, Y, color='k')

【讨论】:

    【解决方案2】:

    flatnumpy 数组的一个属性,它返回一个迭代器。例如,如果你有一个这样的二维数组:

    import numpy as np
    arr2d = np.arange(4).reshape(2, 2)
    arr2d
    # array([[0, 1],
    #        [2, 3]])
    

    flat 属性提供了一种方便的方式来遍历此数组,就像它是一维数组一样:

    for value in arr2d.flat:
        print(value)
    # 0
    # 1
    # 2
    # 3
    

    您还可以使用flatten 方法展平数组:

    arr2d.flatten()
    # array([0, 1, 2, 3])
    

    所以回到你的问题,当你指定时:

    • ncols 到 1 和 nrows 到大于 1 的值或相反,您将获得一维 numpy 数组中的轴,在这种情况下,flat 属性返回相同的数组。
    • ncolsnrows 的值都大于 1,您将获得二维数组中的坐标区,在这种情况下,flat 属性返回扁平数组。
    • ncolsnrows 都为 1,您将获得没有 flat 属性的坐标区对象。

    因此,一个可能的解决方案是每次都将您的 ax 对象转换为 numpy 数组:

    fig, ax = plt.subplots(nrows=nrows, ncols=ncols, figsize=figsize)
    
    ax = np.array(ax)
    for i, axi in enumerate(ax.flat):
        axi.plot(...)
    

    【讨论】:

      【解决方案3】:

      当您使用命令fig,ax=plt.subplots() 创建一组具有多行/多列的子图时,它会返回一个fig 和一个坐标轴列表axax 列表的形状是二维的(行、列)。这就是为什么在迭代ax 列表时需要将其展平为一维的原因。要访问特定轴,您需要行/列索引,例如,ax[r][c] 是第 (r+1) 行/第 (c+1) 列上的轴。索引从零开始。下面的工作代码演示了如何做到这一点。

      import matplotlib.pyplot as plt
      import numpy as np
      
      nrows,ncols = 3,2
      figsize = [5,9]
      X = np.random.rand(6)
      Y = np.random.rand(6)
      
      fig, ax = plt.subplots(nrows=nrows, ncols=ncols, figsize=figsize)
      for i, axi in enumerate(ax.flat):
          axi.plot(X, Y, color='k')
          rowid = i // ncols
          colid = i % ncols
          axi.set_title("row:"+str(rowid)+",col:"+str(colid))
      
      # You can access the axes by row_id, col_id.
      # Now let's plot on ax[row_id][col_id] of your choice
      ax[0][1].plot(Y,X,color='red')    # plot 2nd line in red
      ax[2][0].plot(Y,X,color='green')  # plot 2nd line in green
      
      plt.tight_layout(True)
      plt.show()
      

      输出图:

      【讨论】:

        【解决方案4】:

        您可以使用ax.ravel()ax.flatten()。下面是一个简单的例子

        import matplotlib.pyplot as plt
        
        fig, ax = plt.subplots(nrows=2, ncols=3, figsize=(8, 6))
        
        # for i, ax in enumerate(ax.flatten()):
        for i, ax in enumerate(ax.ravel()):
            ax.plot([1,2,3], color='k')
        plt.show()
        

        【讨论】:

        • @Gamp:是的,因为你只有一个轴
        猜你喜欢
        • 2015-12-28
        • 1970-01-01
        • 2018-09-28
        • 2021-02-28
        • 2020-01-02
        • 1970-01-01
        • 1970-01-01
        • 2017-10-31
        • 2021-09-22
        相关资源
        最近更新 更多