【问题标题】:Pandas Plotting with Multi-IndexPandas 多索引绘图
【发布时间】:2014-10-12 18:10:45
【问题描述】:

DataFrame 上执行groupby.sum() 后,我在尝试创建我想要的情节时遇到了一些麻烦。

import pandas as pd
import numpy as np

np.random.seed(365)
rows = 100
data = {'Month': np.random.choice(['2014-01', '2014-02', '2014-03', '2014-04'], size=rows),
        'Code': np.random.choice(['A', 'B', 'C'], size=rows),
        'ColA': np.random.randint(5, 125, size=rows),
        'ColB': np.random.randint(0, 51, size=rows),}
df = pd.DataFrame(data)

     Month Code  ColA  ColB
0  2014-03    C    59    47
1  2014-01    A    24     9
2  2014-02    C    77    50

dfg = df.groupby(['Code', 'Month']).sum()

              ColA  ColB
Code Month              
A    2014-01   124   102
     2014-02   398   282
     2014-03   474   198
     2014-04   830   237
B    2014-01   477   300
     2014-02   591   167
     2014-03   522   192
     2014-04   367   169
C    2014-01   412   180
     2014-02   275   205
     2014-03   795   291
     2014-04   901   309

如何为每个 Code 创建一个子图 (kind='bar'),其中 x 轴是 Month,条形是 ColAColB

【问题讨论】:

    标签: python pandas matplotlib seaborn bar-chart


    【解决方案1】:

    使用以下 DataFrame ...

    # using pandas version 0.14.1
    from pandas import DataFrame
    import pandas as pd
    import matplotlib.pyplot as plt
    
    data = {'ColB': {('A', 4): 3.0,
    ('C', 2): 0.0,
    ('B', 4): 51.0,
    ('B', 1): 0.0,
    ('C', 3): 0.0,
    ('B', 2): 7.0,
    ('Code', 'Month'): '',
    ('A', 3): 5.0,
    ('C', 1): 0.0,
    ('C', 4): 0.0,
    ('B', 3): 12.0},
    'ColA': {('A', 4): 66.0,
    ('C', 2): 5.0,
    ('B', 4): 125.0,
    ('B', 1): 5.0,
    ('C', 3): 41.0,
    ('B', 2): 52.0,
    ('Code', 'Month'): '',
    ('A', 3): 22.0,
    ('C', 1): 14.0,
    ('C', 4): 51.0,
    ('B', 3): 122.0}}
    
    df = DataFrame(data)
    

    ...您可以绘制以下内容(使用横截面):

    f, a = plt.subplots(3,1)
    df.xs('A').plot(kind='bar',ax=a[0])
    df.xs('B').plot(kind='bar',ax=a[1])
    df.xs('C').plot(kind='bar',ax=a[2])
    

    A 一个,B 一个,C 一个,x 轴:“月”,条形为 ColA 和 ColB。 也许这就是你要找的。​​p>

    【讨论】:

    • 当我尝试运行它时,这会给我一个“KeyError:'A'”(版本 0.13.0)。
    • 我刚刚编辑了帖子,添加了导入。我正在使用 0.14.1,对我来说粘贴在这里的代码有效。也许有 0.14.1 版本的人可以确认这一点。
    • 我建议通过遍历轴数组 a 和如下代码来改进此解决方案:for ax, code in zip(a.flat, df.index.levels[0]): df.xs(code).plot(kind='bar', ax=ax)
    【解决方案2】:

    我发现 unstack(level) 方法可以完美地工作,它的另一个好处是不需要先验知道有多少代码。

    ax = dfg.unstack(level=0).plot(kind='bar', subplots=True, rot=0, figsize=(9, 7), layout=(2, 3))
    plt.tight_layout()
    

    【讨论】:

      【解决方案3】:
      • 创建所需的可视化完全是为了调整数据框以适应绘图 API。
        • seaborn 无需.groupby.pivot_table 即可轻松聚合来自数据帧的长格式数据。
      • 给定原始数据框df,最简单的选择是使用pandas.DataFrame.melt 将其转换为长格式,然后使用seaborn.catplot 进行绘图,这是matplotlib 的高级API。
        • 将默认 estimatormean 更改为 sum
      • OP 中的'Month' 列是字符串类型。一般来说,最好使用pd._to_datetime 将列转换为 datetime dtype
      • python 3.8.11pandas 1.3.2matplotlib 3.4.2seaborn 0.11.2中测试

      seaborn.catplot

      import seaborn as sns
      
      dfm = df.melt(id_vars=['Month', 'Code'], var_name='Cols')
      
           Month Code  Cols  value
      0  2014-03    C  ColA     59
      1  2014-01    A  ColA     24
      2  2014-02    C  ColA     77
      3  2014-04    B  ColA    114
      4  2014-01    C  ColA     67
      
      # specify row and col to get a plot like that produced by the accepted answer
      sns.catplot(kind='bar', data=dfm, col='Code', x='Month', y='value', row='Cols', order=sorted(dfm.Month.unique()),
                  col_order=sorted(df.Code.unique()), estimator=sum, ci=None, height=3.5)
      

      sns.catplot(kind='bar', data=dfm, col='Code', x='Month', y='value', hue='Cols', estimator=sum, ci=None,
                  order=sorted(dfm.Month.unique()), col_order=sorted(df.Code.unique()))
      

      pandas.DataFrame.plot

      • pandas 使用 matplotlib 和默认的绘图后端。
      • 要生成像公认答案一样的图,最好使用pandas.DataFrame.pivot_table 而不是.groupby,因为生成的数据框形状正确,无需取消堆叠。
      dfp = df.pivot_table(index='Month', columns='Code', values=['ColA', 'ColB'], aggfunc='sum')
      
      dfp.plot(kind='bar', subplots=True, rot=0, figsize=(9, 7), layout=(2, 3))
      plt.tight_layout()
      

      【讨论】:

        猜你喜欢
        • 2015-10-28
        • 2016-03-18
        • 2019-07-26
        • 2018-10-29
        • 1970-01-01
        • 2021-07-20
        • 1970-01-01
        • 2013-11-09
        相关资源
        最近更新 更多