【问题标题】:Groupby sum and count on multiple columns under multiple conditions in Python在Python中的多个条件下对多列进行分组求和和计数
【发布时间】:2019-05-23 08:09:16
【问题描述】:

我有一个看起来像这样的 pandas 数据框:

import pandas as pd
import numpy as np
data = {
    "Type": ["A", "A", "B", "B", "B"],
    "Project": ["X123", "X123", "X21", "L31", "L31"],
    "Number": [100, 300, 100, 200, 500],
    "Status": ['Y', 'Y', 'N', 'Y', 'N']
}
df = pd.DataFrame.from_dict(data)

我想按Type分组,并在几个条件下得到count和sum,得到的结果如下:

Type  Total_Count  Total_Number  Count_Status=Y  Number_Status=Y  Count_Status=N  Number_Status=N 
 A        2          400              2               400              0               0
 B        5          800              1               200              2              600

我已经尝试过,但不完全是我需要的。请分享您可能有的任何想法。谢谢!

df1 = pd.pivot_table(df, index = 'Type', values = 'Number', aggfunc = np.sum)
df2 = pd.pivot_table(df, index = 'Type', values = 'Project', aggfunc = 'count')
pd.concat([df1, df2], axis=1)

【问题讨论】:

    标签: python pandas numpy


    【解决方案1】:

    处理

    s1 = df.groupby('Type').Number.agg(['count', 'sum'])
    s2 = df.groupby(['Type', 'Status']).Number.agg(['count', 'sum']).unstack(fill_value=0).sort_index(level=1, axis=1)
    s2.columns = s2.columns.map('_Status='.join)
    s1 = s1.add_prefix('Total_')
    s = pd.concat([s1, s2], axis=1)
    s
          Total_count  Total_sum  count_Status=N  sum_Status=N  count_Status=Y  \
    Type                                                                         
    A               2        400               0             0               2   
    B               3        800               2           600               1   
          sum_Status=Y  
    Type                
    A              400  
    B              200  
    

    【讨论】:

      【解决方案2】:

      您可以使用pd.pivot_tablemargins 参数。将列总数放在最后,因为您只需要逐行边距。

      import pandas as pd
      
      df1 = df.pivot_table(index='Type', columns='Status', values='Number', 
                           aggfunc=['sum', 'count'], 
                           margins=True, 
                           margins_name='Total').fillna(0).drop('Total')
      #          sum              count           
      #Status      N      Y Total     N    Y Total
      #Type                                       
      #A         0.0  400.0   400   0.0  2.0     2
      #B       600.0  200.0   800   2.0  1.0     3
      

      如果需要,重命名列:

      d = {'Y': 'Status=Y', 'N': 'Status=N', 'Total': 'Total'}
      df1.columns = [f'{x}_{d.get(y)}' for x,y in df1.columns]
      

      输出df1:

            sum_Status=N  sum_Status=Y  sum_Total  count_Status=N  count_Status=Y  count_Total
      Type                                                                                    
      A              0.0         400.0        400             0.0             2.0            2
      B            600.0         200.0        800             2.0             1.0            3
      

      【讨论】:

        【解决方案3】:

        如果你想创建一个函数:

        def my_agg(x):
            names = {
                'Total_Count': x['Type'].count(),
                'Total_Number': x['Number'].sum(),
                'Count_Status=Y': x[x['Status']=='Y']['Type'].count(),
                'Number_Status=Y': x[x['Status']=='Y']['Number'].sum(),
                'Count_Status=N': x[x['Status']=='N']['Type'].count(),
                'Number_Status=N': x[x['Status']=='N']['Number'].sum()}
        
            return pd.Series(names)
        
        df.groupby('Type').apply(my_agg)
        
            Total_Count   Total_Number  Count_Status=Y  Number_Status=Y Count_Status=N  Number_Status=N
        Type                        
        A      2           400                2                400            0             0
        B      3           800                1                200            2            600
        

        【讨论】:

          【解决方案4】:

          您可以使用pandas.core.groupby.GroupBy.apply 来完成此任务。例如,您可以在获取 Groupby 对象后编写一个函数来处理每一列的数据。

          def compute_metrics(x):
              result = {'Total_Number': x['Number'].sum(), 'Count_Status=Y': len(x['Status'] == "Y")}
              return pd.Series(result)
          

          然后df.groupby('Type').apply(compute_metrics) 将返回这样的数据框:

          Type  Total Number Count_Status=Y
          A     400          2             
          B     800          3
          

          希望这会有所帮助。

          干杯。

          【讨论】:

            【解决方案5】:

            pivot_table开头:

            pv = (df.pivot_table(index='Type', 
                                 columns='Status', 
                                 values='Number', 
                                 aggfunc='sum')
                    .add_prefix('Number_Status='))
            
            print(pv)
            Status  Number_Status=N  Number_Status=Y
            Type                                    
            A                   NaN            400.0
            B                 600.0            200.0
            

            接下来,groupby

            totals = df.groupby('Type').Number.agg([
                ('Total_Count', 'count'),  ('Total_Number', 'sum')])
            
            print(totals)
                  Total_Count  Total_Number
            Type                           
            A               2           400
            B               3           800
            

            最后,状态对 OHE 很重要:

            cnts = (df.set_index('Type').Status
                      .str.get_dummies()
                      .sum(level=0)
                      .add_prefix('Count_Status='))
            
                  Count_Status=N  Count_Status=Y
            Type                                
            A                  0               2
            B                  2               1
            

            把它们放在一起:

            pd.concat([pv, totals, cnts], axis=1).sort_index(axis=1)
            
                  Count_Status=N  Count_Status=Y  Number_Status=N  Number_Status=Y  \
            Type                                                                                             
            A                  0               2              NaN            400.0            
            B                  2               1            600.0            200.0            
            
            Total_Count  Total_Number
                      2           400
                      3           800
            

            【讨论】:

              猜你喜欢
              • 2015-05-17
              • 1970-01-01
              • 1970-01-01
              • 2022-10-06
              • 2016-08-08
              • 1970-01-01
              • 2016-04-11
              • 2021-01-31
              相关资源
              最近更新 更多