【问题标题】:Pandas: How to find percentage of group members type per subgroup?Pandas:如何查找每个子组的组成员类型百分比?
【发布时间】:2020-05-13 18:26:13
【问题描述】:

问题结束时的数据样本和尝试

使用这样的数据框:

    Type    Class   Area    Decision
0   A       1       North   Yes
1   B       1       North   Yes
2   C       2       South   No
3   A       3       South   No
4   B       3       South   No
5   C       1       South   No
6   A       2       North   Yes
7   B       3       South   Yes
8   B       1       North   No
9   C       1       East    No
10  C       2       West    Yes 

如何找到每个类型[A, B, C, D] 属于每个区域[North, South, East, West] 的百分比?

期望的输出:

    North   South   East    West
A   0.66    0.33    0       0
B   0.5     0.5     0       0
C   0       0.5     0.25    0.25

到目前为止我最好的尝试是:

df_attempt1= df.groupby(['Area', 'Type'])['Type'].aggregate('count').unstack().T

返回:

Area  East  North  South  West
Type                          
A      NaN    2.0    1.0   NaN
B      NaN    2.0    2.0   NaN
C      1.0    NaN    2.0   1.0

我想我可以通过计算边距中的总和并附加0 来弥补缺失的观察结果,但我非常感谢有关更优雅方法的建议。

感谢您的任何建议!

代码:

import pandas as pd

df = pd.DataFrame(
    {
        "Type": {0: "A", 1: "B", 2: "C", 3: "A", 4: "B", 5: "C", 6: "A", 7: "B", 8: "B", 9: "C", 10: "C"},
        "Class": {0: 1, 1: 1, 2: 2, 3: 3, 4: 3, 5: 1, 6: 2, 7: 3, 8: 1, 9: 1, 10: 2},
        "Area": {0: "North", 1: "North", 2: "South", 3: "South", 4: "South", 5: "South", 6: "North", 7: "South", 8: "North", 9: "East", 10: "West"},
        "Decision": {0: "Yes", 1: "Yes", 2: "No", 3: "No", 4: "No", 5: "No", 6: "Yes", 7: "Yes", 8: "No", 9: "No", 10: "Yes"},
    }
)

dfg = df[['Area', 'Type']].groupby(['Area']).agg('count').unstack()

df_attempt1 = df.groupby(['Area', 'Type'])['Type'].aggregate('count').unstack().T

【问题讨论】:

    标签: python pandas dataframe group-by


    【解决方案1】:

    你可以这样做:

    import pandas as pd
    df = pd.DataFrame([r.split() for r in '''Index Type    Class   Area    Decision
    0   A       1       North   Yes
    1   B       1       North   Yes
    2   C       2       South   No
    3   A       3       South   No
    4   B       3       South   No
    5   C       1       South   No
    6   A       2       North   Yes
    7   B       3       South   Yes
    8   B       1       North   No
    9   C       1       East    No
    10  C       2       West    Yes'''.split('\n')])
    df.columns = df.iloc[0]
    df = df.iloc[1:]
    
    table = pd.pivot_table(df, values='Class', index=['Type'], columns=['Area'], aggfunc='count').fillna(0)
    table = table.div(table.sum(axis=1), axis=0)
    

    我们将每一列除以表行的相应总和。

    它给出了:

    Area  East     North     South  West
    Type                                
    A     0.00  0.666667  0.333333  0.00
    B     0.00  0.500000  0.500000  0.00
    C     0.25  0.000000  0.500000  0.25 
    

    【讨论】:

      【解决方案2】:

      你已经很接近了。以下应该可以解决问题:

      df.groupby('Type')['Area'].value_counts(normalize = True).unstack(fill_value=0)
      

      输出:

      Area    East    North       South       West
      Type                
      A       0.00    0.666667    0.333333    0.00
      B       0.00    0.500000    0.500000    0.00
      C       0.25    0.000000    0.500000    0.25
      

      如果顺序很重要,您可以通过操作它的列属性重新排序数据框

      【讨论】:

      • @MykolaZotko 整洁 :)
      • 我确实做到了:)
      【解决方案3】:

      我觉得你可以去value_counts(normalize = True):

      >>> df.groupby('Type')['Area'].value_counts(normalize = True).unstack().fillna(0)
      Area  East     North     South  West
      Type                                
      A     0.00  0.666667  0.333333  0.00
      B     0.00  0.500000  0.500000  0.00
      C     0.25  0.000000  0.500000  0.25
      

      【讨论】:

      • 很好,不知道normalize 参数:-)
      • @LukasThaler 有句话说,Pandas 拥有你所需要的一切...... ;)
      【解决方案4】:
      (
          df.groupby('Type')
          .apply(lambda x: x.groupby('Area').Class.count()).unstack(fill_value=0)
          .transform(lambda x: x/x.sum(), axis=1)
      )
      

      【讨论】:

        【解决方案5】:

        你可以使用函数crosstab:

        pd.crosstab(index=df['Type'], columns=df['Area'], normalize='index')
        

        输出:

        Area  East     North     South  West
        Type                                
        A     0.00  0.666667  0.333333  0.00
        B     0.00  0.500000  0.500000  0.00
        C     0.25  0.000000  0.500000  0.25
        

        【讨论】:

          猜你喜欢
          • 2019-10-26
          • 1970-01-01
          • 2018-09-09
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-08-30
          • 2021-12-18
          • 2022-01-26
          相关资源
          最近更新 更多