如何将嵌套分组结果直接分配到新列?Pandas学生数据聚合优化
高效实现Pandas学生数据嵌套分组聚合
核心解决方案:用groupby.agg()一次性完成多指标聚合
你当前反复创建临时表再合并的方式确实冗余,Pandas的groupby结合agg()方法可以让你在一次分组操作中完成所有需要的统计指标,无需拆分临时表。
简化单指标统计(以唯一活动数为例)
你原来统计非预测试活动唯一数的代码可以直接简化为:
# 替代你原来的临时表写法 unique_activity_stats = df[df['IS_PRETEST_ACTIVITY'] == 0].groupby('STUDENT_ID')['ACTIVITY_ID'].nunique().reset_index(name='unique_activity_count')
这里直接用nunique()统计唯一值,比value_counts()+二次分组高效得多。
一次性完成所有聚合指标
如果需要同时统计唯一活动数、唯一节点数、总时长、分类型时长等多个指标,可以通过agg()传入字典一次性定义所有规则:
假设你的原始数据包含STUDENT_ID、ACTIVITY_ID、NODE_ID、IS_PRETEST_ACTIVITY、ACTIVITY_TYPE、DURATION列,代码如下:
# 第一步:先过滤掉预测试活动 filtered_df = df[df['IS_PRETEST_ACTIVITY'] == 0] # 第二步:一次性聚合所有需要的指标 summary_df = filtered_df.groupby('STUDENT_ID').agg( # 统计唯一值数量 unique_activity_count=('ACTIVITY_ID', 'nunique'), unique_node_count=('NODE_ID', 'nunique'), # 统计总时长 total_learning_duration=('DURATION', 'sum'), # 统计平均时长 avg_activity_duration=('DURATION', 'mean'), # 自定义分类型时长统计(比如统计类型A的总时长) duration_type_A=('DURATION', lambda x: x[filtered_df.loc[x.index, 'ACTIVITY_TYPE'] == 'A'].sum()), duration_type_B=('DURATION', lambda x: x[filtered_df.loc[x.index, 'ACTIVITY_TYPE'] == 'B'].sum()) ).reset_index()
处理多类型时长的更优雅方式
如果活动类型较多,用lambda会显得繁琐,可以结合pivot_table生成维度化的时长统计,再与基础指标合并:
# 生成分类型时长统计 type_duration_stats = filtered_df.pivot_table( index='STUDENT_ID', columns='ACTIVITY_TYPE', values='DURATION', aggfunc='sum', fill_value=0 ).rename(columns=lambda t: f'duration_{t.lower()}') # 重命名列名,比如duration_reading、duration_quiz # 生成基础统计指标 basic_stats = filtered_df.groupby('STUDENT_ID').agg( unique_activity_count=('ACTIVITY_ID', 'nunique'), unique_node_count=('NODE_ID', 'nunique'), total_duration=('DURATION', 'sum') ).reset_index() # 合并所有统计结果 final_summary = basic_stats.merge(type_duration_stats, on='STUDENT_ID', how='left')
为什么这种方法更高效
- 避免多次创建临时DataFrame和重复合并操作,减少内存占用
- 一次分组完成多指标计算,代码更简洁易维护
- 利用Pandas内置聚合函数(
nunique、sum等)的优化,比手动二次分组更快
内容的提问来源于stack exchange,提问作者CiviLearner
相关产品推荐
相关产品推荐

