Pandas如何通过groupby+agg优化按日期统计True占比的聚合逻辑
按日期统计T值占比的简化实现
问题说明
现有测试记录数据结构如下:
Ddate Test Name T/F 01-01-2019 Haem T 02-01-2019 Haem T 03-01-2019 Haem T 04-01-2019 Haem F 05-01-2019 Haem F 01-01-2019 CBC T 02-01-2019 CBC T 03-01-2019 CBC T 04-01-2019 CBC F 05-01-2019 CBC F 01-01-2019 KFT T 02-01-2019 KFT T 03-01-2019 KFT T 04-01-2019 KFT F 05-01-2019 KFT F
需求为按Ddate分组,统计T/F字段取值为T的记录占比。原有实现需要提前生成多列中间字段,流程冗余,完全可以通过groupby + agg一次性完成聚合计算,不需要修改原DataFrame结构。
原有实现代码:
import pandas as pd import numpy as np df['T/F'] = df['T/F'].map({'T':1, 'F':0}) df['T'] = np.where(df['T/F']==1, 1, 0) df['F'] = 1 - df['T'] df = df.groupby('Ddate').agg( { 'T': sum, 'F': sum, } ) df['Total'] = df['T'] + df['F'] df['per T'] = df['T'] / df['Total'] * 100
优化方案
方案1:无中间列直接聚合
不需要提前做值映射、生成中间列,直接在聚合逻辑中完成判断,代码最简洁:
result = df.groupby('Ddate')['T/F'].agg( T_count = lambda s: (s == 'T').sum(), F_count = lambda s: (s == 'F').sum(), total = 'count', T_percent = lambda s: (s == 'T').mean() * 100 )
各聚合字段逻辑:
T_count:统计组内值为T的记录数F_count:统计组内值为F的记录数total:调用pandas内置count方法统计组内总记录数T_percent:布尔序列的均值即为True的占比,乘100得到百分比结果
方案2:临时映射列聚合(可读性更高)
如果觉得直接在lambda中写判断不够直观,可以用assign生成不修改原表的临时列再聚合,逻辑更清晰:
result = df.assign( flag = df['T/F'].map({'T': 1, 'F': 0}) ).groupby('Ddate').agg( T_count = ('flag', 'sum'), F_count = ('flag', lambda s: len(s) - s.sum()), total = ('flag', 'count'), T_percent = ('flag', lambda s: s.mean() * 100) )
两种方案输出结果和原有实现完全一致,且不需要提前修改原DataFrame、生成冗余中间列,代码更简洁高效。
内容的提问来源于stack exchange,提问作者Anant
相关产品推荐
相关产品推荐

