Pandas如何自动生成虚拟变量并按分组聚合计数
pandas按分组自动统计value取值计数、保留固定字段实现方案
适用场景
处理包含id、sub_id、value、total_stuff四个字段的DataFrame,满足以下需求:
- 同一
id与sub_id组合对应的total_stuff取值固定 - 需要按
id、sub_id分组,自动统计每个分组内所有value取值的出现次数,同时保留分组对应的total_stuff值 - 避免手动枚举所有value生成的虚拟列做聚合,适配value取值较多的场景
核心思路
你之前用get_dummies生成虚拟变量的思路是可行的,问题出在聚合环节手动列所有列效率太低。只要基于原始数据里value列的唯一取值自动生成聚合规则字典,直接传入agg()即可,不需要手动枚举任何列名,不管value有多少种取值都能自动适配。
实现代码
import pandas as pd # -------------------------- # 1. 生成value列的虚拟变量 # -------------------------- # prefix和prefix_sep参数设置后,生成的虚拟列名直接对应value的原始取值 df_dummy = pd.get_dummies(df, columns=['value'], prefix='', prefix_sep='') # -------------------------- # 2. 自动构造聚合规则字典 # -------------------------- # 所有value取值对应的列统一做求和统计(即计数) agg_config = {val: 'sum' for val in df['value'].unique()} # 同组total_stuff取值固定,取first即可拿到正确值,比mean运算效率更高 agg_config['total_stuff'] = 'first' # -------------------------- # 3. 分组聚合得到最终结果 # -------------------------- result = df_dummy.groupby(['id', 'sub_id'], as_index=False).agg(agg_config)
可选低内存方案:如果数据量较大、value取值极多,不想生成全量虚拟变量占用内存,可以直接用交叉表统计计数后合并固定字段,代码如下:
# 交叉表直接统计每个分组下value的计数 count_res = pd.crosstab([df['id'], df['sub_id']], df['value']).reset_index() # 去重拿到每个分组对应的total_stuff值 stuff_res = df[['id', 'sub_id', 'total_stuff']].drop_duplicates() # 合并得到最终结果 result = count_res.merge(stuff_res, on=['id', 'sub_id'], how='left')该方案运行效率更高,内存占用更低。
说明
- 生成虚拟变量时设置
prefix=''、prefix_sep='',可以让虚拟列名直接和value的原始取值一致,不需要额外处理列名 - 因为同组
total_stuff取值完全相同,用first/last/max/min/mean都能拿到正确值,其中first运算开销最小 - 无论
value列有多少个不同取值,上述代码都可以自动适配,不需要手动修改聚合规则里的列名
内容的提问来源于stack exchange,提问作者PizzaKebab
相关产品推荐
相关产品推荐

