Pandas分组后获取各分类列的众数、次数、最新值及flag状态
问题描述
现有包含分类变量与多列属性的DataFrame,数据示例如下:
import pandas as pd df = pd.DataFrame({ 'ID': [1, 1, 1, 1, 2], 'C1': ['a', 'a', 'q', 'g', 'r'], 'C2': ['b', 'c', 't', 'y', 'h'], 'Cn': ['c', 'd', 'p', 'p', 'k'], 'flag': [True, False, False, False, False] })
需按ID分组后完成以下操作:
- 对
C1、C2…Cn每列分别计算:众数、众数出现次数、该列最后一个值 - 判断每组
flag列是否至少存在一个True值
最终期望输出结果如下:
# 简化展示结构 out = pd.DataFrame({ 'ID': [1, 2], 'c1_common': ['a', 'r'], 'c1_common_n': [2, 1], 'c1_latest': ['g', 'r'], 'c2_common': ['y', 'h'], 'c2_common_n': [1, 1], 'c2_latest': ['y', 'h'], 'cn_common': ['p', 'k'], 'cn_common_n': [2, 1], 'cn_latest': ['p', 'k'], 'has_flag': [True, False] })
请问实现该需求的最优方法是什么?
最优实现方法
借助pandas的分组聚合功能,结合自定义函数与内置方法可高效完成需求,具体步骤如下:
1. 定义辅助聚合函数
针对众数及众数次数的计算,编写两个自定义函数:
def get_mode(x): # 获取众数,若存在多个则取第一个;空分组返回None mode_result = x.mode() return mode_result.iloc[0] if not mode_result.empty else None def get_mode_count(x): # 获取众数的出现次数;空分组返回0 mode_result = x.mode() if mode_result.empty: return 0 return x.value_counts().loc[mode_result.iloc[0]]
2. 构建聚合规则并执行分组
一次性指定所有列的聚合逻辑,避免多次分组损耗性能:
# 筛选出需要处理的特征列(排除ID和flag) feature_cols = [col for col in df.columns if col not in ['ID', 'flag']] # 构建聚合字典:每个特征列对应3种聚合操作,flag列判断是否存在True agg_dict = {} for col in feature_cols: agg_dict[col] = [('common', get_mode), ('common_n', get_mode_count), ('latest', 'last')] agg_dict['flag'] = [('has_flag', 'any')] # 执行分组聚合 result = df.groupby('ID').agg(agg_dict) # 展平多级列名,格式化输出结构 result.columns = [f'{col.lower()}_{stat}' for col, stat in result.columns] # 将ID从索引转为普通列 result = result.reset_index()
核心优势
- 一次分组完成所有计算,效率远高于多次分组操作
- 自定义函数处理了空分组边界情况,保证结果鲁棒性
- 列名格式化后直接匹配需求输出结构,无需额外调整
内容的提问来源于stack exchange,提问作者Cranjis
相关产品推荐
相关产品推荐

