【问题标题】:How can I plot separate Pandas DataFrames as subplots?如何将单独的 Pandas DataFrames 绘制为子图?
【发布时间】:2014-04-24 09:11:47
【问题描述】:

我有几个 Pandas DataFrame 共享相同的值标度,但具有不同的列和索引。调用 df.plot() 时,我得到单独的绘图图像。我真正想要的是将它们全部与子情节放在同一个情节中,但不幸的是,我未能提出解决方案,并且非常感谢一些帮助。

【问题讨论】:

    标签: python matplotlib pandas


    【解决方案1】:

    您可以使用 matplotlib 手动创建子图,然后使用 ax 关键字在特定子图上绘制数据框。例如对于 4 个子图 (2x2):

    import matplotlib.pyplot as plt
    
    fig, axes = plt.subplots(nrows=2, ncols=2)
    
    df1.plot(ax=axes[0,0])
    df2.plot(ax=axes[0,1])
    ...
    

    这里的axes 是一个包含不同子图轴的数组,您可以通过索引axes 来访问一个。
    如果你想要一个共享的x轴,那么你可以提供sharex=Trueplt.subplots

    【讨论】:

      【解决方案2】:

      你可以看到例如在 documentation 演示 joris 答案中。同样从文档中,您还可以在 pandas plot 函数中设置 subplots=Truelayout=(,)

      df.plot(subplots=True, layout=(1,2))
      

      您还可以使用fig.add_subplot(),它采用子图网格参数,例如 221、222、223、224 等,如帖子here 中所述。可以在this ipython notebook 中看到关于 pandas 数据框的绘图(包括子图)的不错示例。

      【讨论】:

      • 虽然 joris 的回答非常适合一般的 matplotlib 使用,但这对于任何想要使用 pandas 进行快速数据可视化的人来说都是极好的。它也更适合内联问题。
      • 请记住,subplotslayout kwargs 只会为单个数据帧生成多个图。这与 OP 将多个数据帧绘制到单个图中的问题有关,但不是解决方案。
      • 这是纯 Pandas 使用的更好答案。这不需要直接导入 matplotlib(尽管您通常应该这样做)并且不需要循环任意形状(例如,可以使用 layout=(df.shape[1], 1))。
      【解决方案3】:

      您可以使用熟悉的 Matplotlib 样式调用 figuresubplot,但您只需使用 plt.gca() 指定当前轴。一个例子:

      plt.figure(1)
      plt.subplot(2,2,1)
      df.A.plot() #no need to specify for first axis
      plt.subplot(2,2,2)
      df.B.plot(ax=plt.gca())
      plt.subplot(2,2,3)
      df.C.plot(ax=plt.gca())
      

      等等……

      【讨论】:

      • 我认为在第一个情节上也可以使用ax=plt.gca()
      【解决方案4】:

      您可以使用 matplotlib 绘制多个 pandas 数据帧的多个子图,并使用一个简单的技巧来制作所有数据帧的列表。然后使用 for 循环绘制子图。

      工作代码:

      import matplotlib.pyplot as plt
      import pandas as pd
      import numpy as np
      # dataframe sample data
      df1 = pd.DataFrame(np.random.rand(10,2)*100, columns=['A', 'B'])
      df2 = pd.DataFrame(np.random.rand(10,2)*100, columns=['A', 'B'])
      df3 = pd.DataFrame(np.random.rand(10,2)*100, columns=['A', 'B'])
      df4 = pd.DataFrame(np.random.rand(10,2)*100, columns=['A', 'B'])
      df5 = pd.DataFrame(np.random.rand(10,2)*100, columns=['A', 'B'])
      df6 = pd.DataFrame(np.random.rand(10,2)*100, columns=['A', 'B'])
      
      #define number of rows and columns for subplots
      nrow=3
      ncol=2
      
      # make a list of all dataframes 
      df_list = [df1 ,df2, df3, df4, df5, df6]
      fig, axes = plt.subplots(nrow, ncol)
      
      # plot counter
      count=0
      for r in range(nrow):
          for c in range(ncol):
              df_list[count].plot(ax=axes[r,c])
              count+=1
      

      使用此代码,您可以在任何配置中绘制子图。您需要定义行数nrow 和列数ncol。此外,您需要列出要绘制的数据框df_list

      【讨论】:

        【解决方案5】:

        你可以用这个:

        fig = plt.figure()
        ax = fig.add_subplot(221)
        plt.plot(x,y)
        
        ax = fig.add_subplot(222)
        plt.plot(x,z)
        ...
        
        plt.show()
        

        【讨论】:

          【解决方案6】:

          您可能根本不需要使用 Pandas。这是猫频率的matplotlib图:

          x = np.linspace(0, 2*np.pi, 400)
          y = np.sin(x**2)
          
          f, axes = plt.subplots(2, 1)
          for c, i in enumerate(axes):
            axes[c].plot(x, y)
            axes[c].set_title('cats')
          plt.tight_layout()
          

          【讨论】:

            【解决方案7】:

            在上面的@joris 响应的基础上,如果您已经建立了对子图的引用,您也可以使用该引用。例如,

            ax1 = plt.subplot2grid((50,100), (0, 0), colspan=20, rowspan=10)
            ...
            
            df.plot.barh(ax=ax1, stacked=True)
            

            【讨论】:

              【解决方案8】:

              如何从具有长(整齐)数据的数据框字典创建多个图

              • 假设:

                • 有一个包含多个数据帧的字典
                  • 通过从文件中读取创建
                  • 通过将单个数据帧分成多个数据帧创建
                • 类别cat 可能重叠,但所有数据帧可能不包含cat 的所有值
                • hue='cat'
              • 由于数据框正在迭代,因此不能保证每个绘图的颜色映射相同

                • 需要根据所有数据帧的唯一 'cat' 值创建自定义颜色图
                • 由于颜色相同,请将一个图例放在图的一侧,而不是在每个图中都放置一个图例

              导入和合成数据

              import pandas as pd
              import numpy as np  # used for random data
              import random  # used for random data
              import matplotlib.pyplot as plt
              from matplotlib.patches import Patch  # for custom legend
              import seaborn as sns
              import math import ceil  # determine correct number of subplot
              
              
              # synthetic data
              df_dict = dict()
              for i in range(1, 7):
                  np.random.seed(i)
                  random.seed(i)
                  data_length = 100
                  data = {'cat': [random.choice(['A', 'B', 'C']) for _ in range(data_length)],
                          'x': np.random.rand(data_length),
                          'y': np.random.rand(data_length)}
                  df_dict[i] = pd.DataFrame(data)
              
              
              # display(df_dict[1].head())
              
                cat         x         y
              0   A  0.417022  0.326645
              1   C  0.720324  0.527058
              2   A  0.000114  0.885942
              3   B  0.302333  0.357270
              4   A  0.146756  0.908535
              

              创建颜色映射和绘图

              # create color mapping based on all unique values of cat
              unique_cat = {cat for v in df_dict.values() for cat in v.cat.unique()}  # get unique cats
              colors = sns.color_palette('husl', n_colors=len(unique_cat))  # get a number of colors
              cmap = dict(zip(unique_cat, colors))  # zip values to colors
              
              # iterate through dictionary and plot
              col_nums = 3  # how many plots per row
              row_nums = math.ceil(len(df_dict) / col_nums)  # how many rows of plots
              plt.figure(figsize=(10, 5))  # change the figure size as needed
              for i, (k, v) in enumerate(df_dict.items(), 1):
                  plt.subplot(row_nums, col_nums, i)  # create subplots
                  p = sns.scatterplot(data=v, x='x', y='y', hue='cat', palette=cmap)
                  p.legend_.remove()  # remove the individual plot legends
                  plt.title(f'DataFrame: {k}')
              
              plt.tight_layout()
              # create legend from cmap
              patches = [Patch(color=v, label=k) for k, v in cmap.items()]
              # place legend outside of plot; change the right bbox value to move the legend up or down
              plt.legend(handles=patches, bbox_to_anchor=(1.06, 1.2), loc='center left', borderaxespad=0)
              plt.show()
              

              【讨论】:

                【解决方案9】:

                这是一个工作的 pandas 子图示例,其中模式是数据框的列名。

                    dpi=200
                    figure_size=(20, 10)
                    fig, ax = plt.subplots(len(modes), 1, sharex="all", sharey="all", dpi=dpi)
                    for i in range(len(modes)):
                        ax[i] = pivot_df.loc[:, modes[i]].plot.bar(figsize=(figure_size[0], figure_size[1]*len(modes)),
                                                                   ax=ax[i], title=modes[i], color=my_colors[i])
                        ax[i].legend()
                    fig.suptitle(name)
                

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 2014-02-01
                  • 1970-01-01
                  • 2019-08-06
                  • 1970-01-01
                  • 1970-01-01
                  • 2021-02-22
                  • 1970-01-01
                  • 2015-05-24
                  相关资源
                  最近更新 更多