如何通过Pandas GroupBy.agg()实现基于c4多值的c3分组条件求和
问题描述
给定如下表格:
| c1 | c2 | c3 | c4 |
|---|---|---|---|
| a | 0 | 1 | 4 |
| b | 0 | 2 | 6 |
| b | 0 | 3 | 4 |
| c | 0 | 1 | 6 |
| d | 1 | 2 | 4 |
| a | 0 | 3 | 0 |
| a | 1 | 0 | 0 |
对应的DataFrame定义:
import pandas as pd import numpy as np df = pd.DataFrame() df['c1'] = ['a', 'b', 'b', 'c', 'd', 'a', 'a'] df['c2'] = [0, 0, 0, 0, 1, 0, 1] df['c3'] = [1, 2, 3, 1, 2, 3, 0] df['c4'] = [4, 6, 4, 6, 4, 0, 0]
需求是按['c1', 'c2']分组,分别计算c4等于0、4、6时对应的c3列求和结果。已知无限制的分组求和代码,但希望用自定义的calc_conditional_sum函数在.agg()中实现条件求和,同时需要覆盖所有c4唯一值的计算。
解决方案
方法1:在.agg()中使用自定义函数实现
可以通过lambda在agg中传递c3、c4列和目标值给自定义函数,具体实现如下:
先简化自定义函数(利用pandas Series的布尔索引,无需转numpy数组):
def calc_conditional_sum(c3_series, c4_series, val): return c3_series[c4_series == val].sum()
然后在分组聚合时调用:
result = df.groupby(['c1', 'c2']).agg( c3_sum_0=('c3', lambda x: calc_conditional_sum(x, df.loc[x.index, 'c4'], 0)), c3_sum_4=('c3', lambda x: calc_conditional_sum(x, df.loc[x.index, 'c4'], 4)), c3_sum_6=('c3', lambda x: calc_conditional_sum(x, df.loc[x.index, 'c4'], 6)) ).reset_index() print(result)
输出结果:
c1 c2 c3_sum_0 c3_sum_4 c3_sum_6 0 a 0 3 1 0 1 a 1 0 0 0 2 b 0 0 3 2 3 c 0 0 0 1 4 d 1 0 2 0
方法2:使用pivot_table(推荐,简洁高效)
这是最贴合需求的原生pandas方法,无需自定义函数,直接通过透视表实现分组条件求和:
result = df.pivot_table( index=['c1', 'c2'], columns='c4', values='c3', aggfunc='sum', fill_value=0 ).reset_index() # 重命名列名,增强可读性 result.columns = ['c1', 'c2', 'c3_sum_0', 'c3_sum_4', 'c3_sum_6'] print(result)
输出与方法1完全一致,代码更简洁,大数据量下效率更高。
方法3:多列分组后展开
先按c1、c2、c4三列分组求和,再用unstack将c4的不同值转为列:
result = df.groupby(['c1', 'c2', 'c4'])['c3'].sum().unstack(fill_value=0).reset_index() # 重命名列 result.columns = ['c1', 'c2', 'c3_sum_0', 'c3_sum_4', 'c3_sum_6'] print(result)
同样得到目标结果,逻辑直观,适合理解分组展开的过程。
内容的提问来源于stack exchange,提问作者Ghanashyam
相关产品推荐
相关产品推荐

