如何在GroupBy操作中按日期条件计算动态窗口的滚动均值?
问题描述
需求:编写代码实现,若当前日期与id分组的最小日期差值超过3个月(按90天计),使用21天窗口计算rev字段的滚动均值;否则使用7天窗口。
示例数据:
import pandas as pd import numpy as np np.random.seed(0) dt = pd.DataFrame({'id' : [1,1,2,2,1], 'date' : ['2023-09-01', '2023-09-10', '2023-01-01', '2023-01-13', '2023-09-11'], 'rev' : np.random.randint(100, 150, 5)}) dt # 输出: # id date rev # 0 1 2023-09-01 144 # 1 1 2023-09-10 147 # 2 2 2023-01-01 100 # 3 2 2023-01-13 103 # 4 1 2023-09-11 103
尝试的代码:
dt.groupby('id').transform(lambda x : x['rev'].rolling(window = '21D', min_periods = 1).mean() if pd.to_datetime('today') - x['date'].min() >= 90 else x['rev'].rolling(window = '7D', min_periods = 1).mean())
运行后出现KeyError: 'date'错误,请求实现正确的滚动均值计算。
错误原因
使用groupby('id').transform()时,lambda函数的参数x是单个列的Series(而非整个分组的DataFrame),因此无法通过x['date']或x['rev']访问其他列,这就是报错的根源。
解决方案
- 先将
date列转换为datetime类型,确保日期运算和滚动窗口生效。 - 使用
groupby('id').apply()处理每个分组的完整DataFrame,这样可以同时访问date和rev列。 - 计算当前日期与分组最小日期的差值时,用天数数值进行比较,避免类型错误。
完整代码:
import pandas as pd import numpy as np np.random.seed(0) dt = pd.DataFrame({'id' : [1,1,2,2,1], 'date' : ['2023-09-01', '2023-09-10', '2023-01-01', '2023-01-13', '2023-09-11'], 'rev' : np.random.randint(100, 150, 5)}) # 转换日期列为datetime类型 dt['date'] = pd.to_datetime(dt['date']) def calculate_rolling_mean(group): # 计算当前日期与分组最小日期的天数差值 days_diff = (pd.to_datetime('today') - group['date'].min()).days # 根据差值选择滚动窗口 window = '21D' if days_diff >= 90 else '7D' # 计算滚动均值,需将date设为索引以支持时间窗口 group['rolling_rev_mean'] = group.set_index('date')['rev'].rolling(window=window, min_periods=1).mean().values return group # 应用函数并重置索引 result = dt.groupby('id').apply(calculate_rolling_mean).reset_index(drop=True) print(result)
输出示例(假设当前日期为2023-10-01):
id date rev rolling_rev_mean 0 1 2023-09-01 144 144.000000 1 1 2023-09-10 147 145.500000 2 1 2023-09-11 103 131.333333 3 2 2023-01-01 100 100.000000 4 2 2023-01-13 103 103.000000
内容的提问来源于stack exchange,提问作者Karthik S
相关产品推荐
相关产品推荐

