【问题标题】:One colorbar for multiple pandas subplots多个熊猫子图的一个颜色条
【发布时间】:2021-08-14 07:30:53
【问题描述】:

我终其一生都无法弄清楚如何为多个 pandas 子图附加一个颜色条。几乎所有其他解决为多个子图放置一个颜色条的问题的问题都使用 np 数组而不是数据框来绘制。

有一个问题,One colorbar for seaborn heatmaps in subplot,这似乎很有用,但是我不知道如何将其扩展到我的情况。

有人可以帮忙吗?以下是我当前代码的示例。提前致谢!

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

# If you're using a notebook:
# %matplotlib inline

df = pd.DataFrame({"BASE": np.random.randn(10),
            "A": np.random.randn(10),
            "B": np.random.randn(10),
             "C": np.random.randn(10), 
             "D": np.random.randn(10),
            "color_col": [1,1,2,2,1,1,2,1,2,2]})




plt.figure(1, figsize = (15,15))

plt.subplot(2,2,1)
df.plot.scatter(x = "BASE", y = "A", c = df["color_col"], ax = plt.gca())

plt.subplot(2,2,2)
df.plot.scatter(x = "BASE", y = "B", c = df["color_col"], ax = plt.gca())

plt.subplot(2,2,3)
df.plot.scatter(x = "BASE", y = "C", c = df["color_col"], ax = plt.gca())

plt.subplot(2,2,4)
df.plot.scatter(x = "BASE", y = "D", c = df["color_col"], ax = plt.gca())

【问题讨论】:

    标签: python pandas matplotlib plot


    【解决方案1】:

    Matplotlib 2 Subplots, 1 Colorbar 的问题可能更符合您的要求。 但问题是您无法直接访问在 pandas 散点图中创建的可映射对象。

    这里的解决方案是使用 plt.gca().get_children()[0] 从轴中提取此可映射(在本例中为 PatchCollection),这会从轴中获取第一个子艺术家。

    只要所有散点图共享相同的颜色和 只要轴上没有其他艺术家。

    import pandas as pd
    import numpy as np
    import matplotlib.pyplot as plt
    
    df = pd.DataFrame({"BASE": np.random.randn(10),
                "A": np.random.randn(10),
                "B": np.random.randn(10),
                 "C": np.random.randn(10), 
                 "D": np.random.randn(10),
                "color_col": np.random.randn(10)})
    
    fig = plt.figure(1, figsize = (6,6))
    plt.subplots_adjust(wspace=0.5, right=0.8, top=0.9, bottom=0.1)
    for i, col in enumerate("ABCD"):
        plt.subplot(2,2,i+1)
        df.plot.scatter(x = "BASE", y = col, ax = plt.gca(), 
                        c = df["color_col"], cmap="jet", colorbar=False)
    
    # we now take the first axes and 
    # create a colorbar for it's first child (the PathCollection from scatter)
    # this is save as long as all scatterplots share the same colors and
    # as long as there are no other artists in the axes.
    im = plt.gca().get_children()[0]
    cax = fig.add_axes([0.85,0.1,0.03,0.8]) 
    fig.colorbar(im, cax=cax)
    
    plt.show()
    

    【讨论】:

      【解决方案2】:

      目标上有几块石头。我很确定至少还有一种方法存在(使用 GridSpec 与下面概述的不同),但我喜欢后两种。

      1.您可以简单地选择何时绘制彩条,只要您不关心是否修剪了其中一个子图以为彩条腾出空间。

      df = pd.DataFrame({"BASE": np.random.randn(10),
                  "A": np.random.randn(10),
                  "B": np.random.randn(10),
                   "C": np.random.randn(10), 
                   "D": np.random.randn(10),
                  "color_col": np.random.randn(10)})
      
      fig,axis = plt.subplots(nrows=1,ncols=4,figsize=(18,6)) 
      
      for i, col in enumerate("ABCD"):
          ax = axis[i]
          df.plot.scatter(ax=ax, x = "BASE", y = col, c = df["color_col"], s = 55, cmap="jet", colorbar=(i==len("ABCD")-1))
      fig.tight_layout()
      plt.show()
      

      2. 如果你真的想要 2X2 网格,并且所有子图必须相同大小,你可以试试这个。我喜欢第一个答案,不必将彩条放在特定位置。我宁愿画出我想要的一切,使用现有的 tight_layout() 功能,然后添加一个颜色条。我唯一保留的幻数是 figsize。

      fig,axes = plt.subplots(2,2, figsize = (9,4))
      
      df = pd.DataFrame({"BASE": np.random.randn(10),
                  "A": np.random.randn(10),
                  "B": np.random.randn(10),
                   "C": np.random.randn(10), 
                   "D": np.random.randn(10),
                  "color_col": np.random.randn(10)})
      
      for i, col in enumerate("ABCD"):
          ax = axes[i/2][i%2]
          im = df.plot.scatter(x = "BASE", y = col, ax = ax, s = 35,
                      c = df["color_col"], cmap="jet", colorbar=False)
      fig.tight_layout()
      # Note: since colorbar is manu`enter code here`ally added, tight_layout must be called before
      # rendering colorbar
      plt.colorbar(plt.gca().get_children()[0], ax=axes.ravel().tolist())
      

      3. 另一种方法是使用 gridspec 作为 suplots 构造函数的参数:

      import pandas as pd
      import numpy as np
      import matplotlib as mpl
      import matplotlib.gridspec as gridspec
      
      df = pd.DataFrame({"BASE": np.random.randn(10),
                  "A": np.random.randn(10),
                  "B": np.random.randn(10),
                   "C": np.random.randn(10), 
                   "D": np.random.randn(10),
                  "color_col": np.random.randn(10)})
      
      nrows,ncols = 2,2
      fig, axes = plt.subplots(nrows=nrows, ncols=ncols, sharex='col', sharey=False,
                                     gridspec_kw={'width_ratios': [1, 1,0.1]},
                                     figsize=(7, 4))
      
      for i, col in enumerate("ABCD"):
          ax = axes[i/(ncols)][i%(ncols)]
          im = df.plot.scatter(x = "BASE", y = col, ax = ax, s = 35
                               ,c = df["color_col"], cmap="jet", colorbar=False)
      
      fig.tight_layout()
      cax,kw = mpl.colorbar.make_axes([ax for ax in axes.flat])
      plt.colorbar(axes[0][0].get_children()[0], cax=cax, **kw)
      
      plt.show()
      

      【讨论】:

        猜你喜欢
        • 2023-03-17
        • 1970-01-01
        • 2019-08-03
        • 2018-11-30
        • 2016-01-16
        • 2021-02-09
        • 1970-01-01
        相关资源
        最近更新 更多