【问题标题】:How to plot stacked bar-charts in pandastic way?如何以熊猫方式绘制堆叠条形图?
【发布时间】:2020-02-04 16:24:17
【问题描述】:

我的数据框主要包含分类列:

df = pd.DataFrame({
     'col_to_group': ['A', 'A', 'B', 'B', 'A'],
     'col_1': ['a', 'b', 'c', 'a', 'a'],
     'col_2': ['x', 'y', 'y', 'y','x'],
     'col_3': [.1, .2, .1, .9, .7]
})

基本上,我想为col_1col_2 按来自col_to_group(A、B)的子组和整个数据框(ALL)绘制条形图。

这是我目前的解决方案:

import pandas as pd
import matplotlib.pyplot as plt


df = pd.DataFrame({
     'col_to_group': ['A', 'A', 'B', 'B', 'A'],
     'col_1': ['a', 'b', 'c', 'a', 'a'],
     'col_2': ['x', 'y', 'y', 'y','x'],
     'col_3': [.1, .2, .1, .9, .7]
})

for i in ['col_1', 'col_2']: 
    L = df.groupby('col_to_group')[i].value_counts(normalize=True).unstack().T
    R = df[i].value_counts(normalize=True).rename('ALL')
    z = pd.concat([L, R], axis=1, sort=True).T
    #z.T.to_csv(i+'_bar.csv')
    #plotting:
    zz = z.plot.bar(stacked=True).legend(bbox_to_anchor=(1.0, 1.0)).get_figure()
    plt.title(i, fontsize = 12)
    zz.savefig(i+'_bar.png', dpi=300, bbox_inches='tight') 
    plt.show()

z 的创作很复杂,我也不是matplotlib 的粉丝 - 可以一行完成吗?

我正在为此寻找熊猫解决方案。

【问题讨论】:

  • pandastic 这个词简直荒谬。我希望这永远不会赶上。
  • 但是,说真的,您能提供一张您预期输出的图片吗?
  • @adrianp 问题描述中的片段会生成预期的图表。 Pandastic,类似于 pythonic,但适用于 pandas ;)

标签: python pandas matplotlib group-by bar-chart


【解决方案1】:

深入研究文档后,我发现crosstabmarginsnormalize=index 更巧妙地解决了我的问题。

import pandas as pd


df = pd.DataFrame({
     'col_to_group': ['A', 'A', 'B', 'B', 'A'],
     'col_1': ['a', 'b', 'c', 'a', 'a'],
     'col_2': ['x', 'y', 'y', 'y','x'],
     'col_3': [.1, .2, .1, .9, .7]
})


for i in ['col_1', 'col_2']:
    (pd.crosstab(df['col_to_group'], df[i], margins=True, margins_name='ALL', normalize='index')
       .plot.bar(stacked=True).legend(title=i, bbox_to_anchor=(1.0, 1.0)).get_figure()
       .savefig(i + '_bar.png', dpi=300, bbox_inches='tight')
    )

【讨论】:

    【解决方案2】:

    我会这样做:

    df1=df.groupby('col_to_group')['col_1','col_2'].apply(lambda x: x.apply(lambda x: x.value_counts(normalize=True),axis=0)).unstack(level=1).dropna(how='all',axis=1).fillna(0)
    print(df1)
    

                     col_1                    col_2          
                         a         b    c         x         y
    col_to_group                                             
    A             0.666667  0.333333  0.0  0.666667  0.333333
    B             0.500000  0.000000  0.5  0.000000  1.000000
    

    df2=df[['col_1','col_2']].apply(lambda x: x.value_counts(normalize=True)).unstack().dropna().rename('ALL').to_frame().T
    print(df2)
    
    
        col_1           col_2     
            a    b    c     x    y
    ALL   0.6  0.2  0.2   0.4  0.6
    

    plot_df=pd.concat([df1,df2])
    print(plot_df)
    
    
            col_1                    col_2          
                a         b    c         x         y
    A    0.666667  0.333333  0.0  0.666667  0.333333
    B    0.500000  0.000000  0.5  0.000000  1.000000
    ALL  0.600000  0.200000  0.2  0.400000  0.600000
    

    plot_df['col_1'].plot(kind='bar',stacked=True)
    plot_df['col_2'].plot(kind='bar',stacked=True)
    

    【讨论】:

    • 谢谢。我发现crosstab 解决了我的问题。
    • 现在,我想如何将您的想法结合到一个数据框中并使用子图来消除循环。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-29
    • 1970-01-01
    • 1970-01-01
    • 2021-06-16
    • 2016-09-27
    相关资源
    最近更新 更多