如何基于日期和姓名转换Pandas DataFrame实现周期值统计
Pandas分组统计固定时间窗口数值和解决方案
你当前的实现逻辑是按月度重采样后做累计值计算,和需求中「以全局最新日期为基准,回溯固定自然日窗口求和」的逻辑不匹配,按以下步骤实现即可得到预期输出:
预处理日期字段,确定统计基准
首先将date列转换为pandas的datetime类型,取全表最大日期作为时间窗口的统计基准。注意:不要按分组单独取每个用户的最新日期,否则会出现统计口径不一致的问题:import pandas as pd # 转换日期列为标准datetime格式 df['date'] = pd.to_datetime(df['date']) # 取全表最新日期作为统一统计基准 base_date = df['date'].max()分组计算两个时间窗口的value总和
按name字段分组,分别筛选出落在近30天、近365天窗口内的记录,对value字段求和:result = df.groupby('name', as_index=False).agg( Last_30_days=('value', lambda s: s[df.loc[s.index, 'date'] >= base_date - pd.Timedelta(days=30)].sum()), Last_365_days=('value', lambda s: s[df.loc[s.index, 'date'] >= base_date - pd.Timedelta(days=365)].sum()) ).rename(columns={'name': 'Name'})
结果验证
执行代码后输出的结果和预期完全一致:
Name Last_30_days Last_365_days 0 Anna 5 15 1 Jim 3 10
原代码问题说明
resample('MS')是按月度首日为节点做时间分箱,和需求的固定自然日滚动窗口逻辑完全不符- 后续调用的
cumsum()是按时间顺序做累计求和,不是从基准日期回溯指定范围的条件求和,因此无法得到目标结果
大数据量优化方案
如果数据集规模较大,可以提前给每行数据打窗口标记,减少分组计算时的重复判断,执行效率更高:
# 提前标记每行是否属于对应时间窗口 df['in_30d'] = df['date'] >= base_date - pd.Timedelta(days=30) df['in_365d'] = df['date'] >= base_date - pd.Timedelta(days=365) result = df.groupby('name', as_index=False).agg( Last_30_days=('value', lambda s: s[df.loc[s.index, 'in_30d']].sum()), Last_365_days=('value', lambda s: s[df.loc[s.index, 'in_365d']].sum()) ).rename(columns={'name': 'Name'})
内容的提问来源于stack exchange,提问作者user19495470
相关产品推荐
相关产品推荐

