Pandas Grouper结合datetime对象的多维度分组异常问题
问题分析:按ID+7天分组时结果差异的原因
这个问题我之前也碰到过,核心原因是Pandas的pd.Grouper在多维度分组时的全局对齐特性,咱们一步步拆解:
先看数据背景
你的测试数据里:
- id=1的日期范围是
2018-01-01到2018-01-10(共10天) - id=2的日期范围是
2018-01-11到2018-02-09(共30天)
为什么全局分组和单独分组结果不一样?
1. 全局多维度分组时的逻辑
当你用['id', pd.Grouper(key='dates', freq='7D')]做分组时,pd.Grouper的7天时间窗口是从整个DataFrame的最早日期(2018-01-01)开始统一划分的:
- 第一个窗口:
2018-01-01 ~ 2018-01-07→ 只有id=1的7条数据 - 第二个窗口:
2018-01-08 ~ 2018-01-14→ id=1占3条(01-08到01-10),id=2占4条(01-11到01-14) - 后续窗口以此类推,所以id=2的首组自然只有4条数据,这是全局窗口对齐导致的。
2. 单独分组id=2时的逻辑
当你单独提取id=2的数据再分组时,pd.Grouper会以该子DataFrame的最早日期(2018-01-11)作为窗口起始点来划分7天周期:
- 第一个窗口:
2018-01-11 ~ 2018-01-17→ 正好7条数据 - 后续每个窗口都是完整的7天,最后一组剩下2条,这就是你预期的结果。
解决办法:实现每个ID内独立按7天分组
要让每个ID的时间分组独立计算,需要用groupby('id')结合apply,让每个ID的子DataFrame单独处理时间分组:
import numpy as np import pandas as pd # 生成测试数据 df = pd.DataFrame( {'dates':pd.date_range('2018-1-1',periods=40,freq='D'), 'id': np.concatenate((np.repeat(1,10),np.repeat(2,30))), 'amount':np.random.random(40) } ) # 每个ID内独立按7天分组的正确写法 result = (df.groupby('id') .apply(lambda sub_df: sub_df.groupby(pd.Grouper(key='dates', freq='7D'))['amount'].agg(['mean', 'count'])) .reset_index(level=0) .set_index(['id', 'dates']) ) print(result)
运行这段代码后,id=2的分组结果就会和你单独处理时的预期一致了。
内容的提问来源于stack exchange,提问作者user4505419
相关产品推荐
相关产品推荐

