Pandas按subject_id和3M频率分组后仅返回Prod_id聚合值的方法
问题解决:按分组聚合后仅返回去重计数值并去除索引
原始数据与需求
原始DataFrame代码
import pandas as pd df = pd.DataFrame({'subject_id':[1,1,1,1,1,1,1,2,2,2,2,2], 'time_1' :['2017-04-03 12:35:00','2017-04-03 12:50:00','2018-04-05 12:59:00','2018-05-04 13:14:00','2017-05-05 13:37:00','2018-07-06 13:39:00','2018-07-08 11:30:00','2017-04-08 16:00:00','2019-04-09 22:00:00','2019-04-11 04:00:00','2018-04-13 04:30:00','2017-04-14 08:00:00'], 'val' :[5,5,5,5,1,6,5,5,8,3,4,6], 'Prod_id':['A','B','C','A','E','Q','G','F','G','H','J','A']}) df['time_1'] = pd.to_datetime(df['time_1'])
需求
- a) 按
subject_id和time_1(按3个月频率freq='3M')分组 - b) 仅返回
Prod_id列的去重计数值,并且去除分组索引
用户尝试的错误代码
第一次尝试(返回了分组列作为索引):
df.groupby(['subject_id',pd.Grouper(key='time_1', freq='3M')])['Prod_id'].nunique()
第二次尝试(语法错误,as_index=False位置错误):
df.groupby(['subject_id',pd.Grouper(key='time_1', freq='3M'),as_index=False])['Prod_id'].nunique()
预期输出
uniq_prod_cnt 0 2 1 1 2 1 3 3 4 2 5 1 6 2
正确解决方案
问题出在as_index=False的参数位置:它是groupby()的参数,不能放在分组列的列表中。正确代码如下:
方法一:分步实现
# 分组聚合,设置as_index=False避免分组列为索引 agg_result = df.groupby( ['subject_id', pd.Grouper(key='time_1', freq='3M')], as_index=False )['Prod_id'].nunique() # 仅保留聚合结果列,并重命名为预期列名 final_output = agg_result.rename(columns={'Prod_id': 'uniq_prod_cnt'})[['uniq_prod_cnt']] print(final_output)
方法二:链式调用简化
final_output = df.groupby( ['subject_id', pd.Grouper(key='time_1', freq='3M')], as_index=False )['Prod_id'].nunique().rename(columns={'Prod_id': 'uniq_prod_cnt'})[['uniq_prod_cnt']]
执行后即可得到仅包含uniq_prod_cnt列的结果,且无分组索引。
内容的提问来源于stack exchange,提问作者The Great
相关产品推荐
相关产品推荐

