按列分组并为分组中使用的特定列分配不同的聚合函数

Grouping by a column and assigning different aggregation function for a certain column that is used in a group by

我有一个 df:

field           category            2022-01-10      2022-01-17      2022-01-24    2022-01-31 
A               Chair               50              100             200           150
B               Chair               75              15              57            75   
C               Chair               0.57            0.64            0.4           0.47
A               Table               50              100             200           150
B               Table               75              15              57            75   
C               Table               0.57            0.64            0.4           0.47
A               Mirror              50              100             200           150
B               Mirror              75              15              57            75   
C               Mirror              0.57            0.64            0.4           0.47

我正在尝试按 field 分组,或者只是删除 category 列并汇总每周的值,这样结果将如下所示:

field       2022-01-10      2022-01-17      2022-01-24    2022-01-31 
A           50+50+50        100+100+100     200+200+200   150+150+150
B           75+75+75        15+15+15        57+57+57      75+75+75
C           np.mean([0.57, 0.57, 0.57])     # each weeks average of field C

对于字段 A & B 每周我会在不同类别中总结该周的值,但对于字段 C 我想要平均值。

我试过: df.groupby(['field']).agg({'A':sum, 'B':sum, 'C'.np.mean}) 但这当然行不通,因为字段是分组依据而不是列。

我相信这个问题可以通过以某种方式删除 category 列然后根据 field 列转换值来解决,但我不确定它是如何工作的。

{A,B}和{C}需要不同的处理,所以我们可以分开处理

pd.concat([
    df[df['field'].isin(['A', 'B'])).groupby('field').sum(), #for AB
    df[df['field']=='C'].groupby('field').mean(),  #for C
])

创建要应用的函数字典,然后将数据框扁平化并按 fieldvariable(日期)列分组。使用 groupby 的第一个索引来获得正确的功能。最后重塑你的数据框。

aggfuncs = {'A': lambda x: np.sum(x),
            'B': lambda x: np.sum(x),
            'C': lambda x: np.mean(x)}

out = df.melt(['field', 'category']).groupby(['field', 'variable'])['value'] \
        .apply(lambda x: aggfuncs[x.name[0]](x)).unstack() \
        .rename_axis(columns=None).reset_index()
print(out)

# Output
  field  2022-01-10  2022-01-17  2022-01-24  2022-01-31
0     A      150.00      300.00       600.0      450.00
1     B      225.00       45.00       171.0      225.00
2     C        0.57        0.64         0.4        0.47

这是解决问题的一种方法:

s = df.set_index('field').select_dtypes(np.number)

out = s.drop('C').groupby(level=0).sum()
out.loc['C', :] = s.loc['C'].mean()

结果:

print(out)

       2022-01-10  2022-01-17  2022-01-24  2022-01-31
field                                                
A          150.00      300.00       600.0      450.00
B          225.00       45.00       171.0      225.00
C            0.57        0.64         0.4        0.47