如何计算Datetime索引DataFrame列排除末月的12个月滚动平均值
工作日Datetime索引DataFrame排除末尾1月数据的12月滚动均值高效实现
不要用enumerate逐行遍历,直接用pandas原生向量化接口实现,性能比循环高两个数量级,全程不需要写自定义循环函数。
核心实现逻辑
- 先定位数据集最后一个时间点,计算出最后1个月的时间分界阈值
- 把阈值之后(即最后1个月)的目标列值置为
NaN,pandas滚动计算默认自动跳过空值,这部分数据不会参与运算 - 传入时间类窗口参数调用
rolling方法,适配工作日索引自动跳过非交易日,直接计算滚动均值即可
可直接运行的代码示例
import pandas as pd import numpy as np # ---------------------- # 这里替换成你自己的DataFrame即可,要求索引是已转成DatetimeIndex的工作日序列 # 测试用构造数据:2022-2024年的工作日序列 dates = pd.bdate_range(start='2022-01-01', end='2024-05-31') df = pd.DataFrame({'target_col': np.random.randn(len(dates))}, index=dates) # ---------------------- # 计算最后1个月的分界点 last_ts = df.index.max() exclude_threshold = last_ts - pd.DateOffset(months=1) # 标记最后1个月数据为空,不参与计算 calc_series = df['target_col'].where(df.index <= exclude_threshold) # 计算12个月滚动平均 df['rolling_12m_avg'] = calc_series.rolling( window='365D', # 12个月自然时间窗口,自动识别索引里的工作日、跳过非交易日 min_periods=198, # 可选:要求至少9个月有效交易日(按每月22个交易日估算)才输出结果,避免前期数据过少产生无意义值 closed='left' # 窗口仅包含当前时间点之前的数据,避免引入未来数据 ).mean()
常见踩坑说明
之前用mask/where/自定义函数运行失败基本都是这两个原因:
- 调用
rolling时传了固定整数作为窗口大小(比如rolling(252)),固定窗口按行数滚动,无法适配时间规则,遇到节假日、交易日数量波动就会对齐错误 - 自定义滚动函数走Python逐行调用逻辑,性能差还容易出现索引对齐问题,完全没必要用
场景拓展
如果你的需求不是排除整个数据集最后1个月的数据,而是每个时间点的滚动窗口都跳过最近1个月的数据(即窗口范围为当前点往前13个月到往前1个月),直接用时间偏移shift实现即可,不需要做全量mask:
# 按时间偏移把序列往前挪1个月,自动适配工作日索引、不会按行错位 shifted_series = df['target_col'].shift(freq=pd.DateOffset(months=1)) df['rolling_12m_skip_1m'] = shifted_series.rolling('365D', min_periods=198).mean()
内容的提问来源于stack exchange,提问作者Fidel Castro
相关产品推荐
相关产品推荐

