Pandas groupby聚合后如何链式实现avg列多条件if-else分级
Pandas链式调用实现分组统计与分级计算
原始数据
CSV文件内容如下:
key1 key2 Key3 key4 key5 Val1 A 51 'True' 25 Val1 A 50 'False' 25 Val1 A 49 'True' 25 Val1 A 48 'True' 25 Val2 A 47 'False' 25 Val2 A 46 'True' 25 Val2 A 45 'False' 25 Val2 A 44 'True' 25 Val2 A 43 'True' 25
期望输出
key1 key2 max_key5 total_key4 total_true_key4 grade Val1 A 51 4 3 1 Val2 A 47 5 3 2
需求规则
按key1和key2分组,依次完成以下计算:
- 统计key5的最大值
- 统计key4列总记录行数
- 统计key4值为
'True'的总行数 - 计算True占比百分比:
avg = total_true_key4 * 100 / total_key4 - 按占比分级:
avg > 70等级为150 < avg ≤ 70等级为2- 其余情况等级为3
现有问题
当前代码中eval方法无法解析多分支if-else逻辑,且不希望拆分链式调用单独使用apply方法,原有代码如下:
grd = "1 if avg > 70 else 2 if avg > 50 else c" pct = lambda x: (1 if x > 70 else (2 if x > 50 else 3)) json_data .assign(_key4=lambda df_: df_['key4'] == "'True'") .groupby(['key1', 'key2']) .agg( maxkey5=('key5', 'max'), total_key4=('key4', 'count'), total_true_key4=('_key4', 'sum') ) .eval('avg = (total_true_key4 * 100) / total_key4') .eval('feg = grd') #.apply(pct(avg))
实现方案
pandas内置eval不支持嵌套多分支三元表达式,直接在链式调用中使用numpy.select或者assign配合where即可保持完整链式结构,无需拆分中间变量。
方案1:numpy.select(可读性最优)
import numpy as np result = ( json_data .assign(_key4=lambda df_: df_['key4'] == "'True'") .groupby(['key1', 'key2'], as_index=False) .agg( max_key5=('key5', 'max'), total_key4=('key4', 'count'), total_true_key4=('_key4', 'sum') ) .assign( avg = lambda x: (x.total_true_key4 * 100) / x.total_key4, grade = lambda x: np.select( condlist=[x.avg > 70, x.avg > 50], choicelist=[1, 2], default=3 ) ) .drop(columns=['avg']) # 不需要保留中间占比列可直接删除 )
方案2:Series.where嵌套(无额外依赖)
如果不想导入numpy,可使用pandas原生where方法链式判断:
result = ( json_data .assign(_key4=lambda df_: df_['key4'] == "'True'") .groupby(['key1', 'key2'], as_index=False) .agg( max_key5=('key5', 'max'), total_key4=('key4', 'count'), total_true_key4=('_key4', 'sum') ) .assign( avg = lambda x: (x.total_true_key4 * 100) / x.total_key4, grade = 3 ) .assign(grade = lambda x: x.grade.where(x.avg <= 50, 2)) .assign(grade = lambda x: x.grade.where(x.avg <= 70, 1)) .drop(columns=['avg']) )
*注:如果需要匹配你给出的示例输出数值,请将聚合逻辑中max_key5=('key5', 'max')改为max_key5=('Key3', 'max'),原始数据中key5列全为25,示例输出的51、47实际是Key3列的分组最大值。
内容的提问来源于stack exchange,提问作者Md. Parvez Alam
相关产品推荐
相关产品推荐

