rolling()方法需作用于Series或DataFrame列,支持固定长度、时间偏移、加权三种窗口;默认右对齐、跳过NaN,min_periods=1可提前输出结果;多列滚动应直接作用于DataFrame,分组滚动须先groupby再rolling。

rolling() 方法的基本用法和窗口类型选择
滚动计算的核心是 rolling(),它必须作用于 Series 或 DataFrame 的列上,不能直接对整个 DataFrame 调用后不指定轴就运算。常见错误是写成 df.rolling(3).sum() 却没意识到:若 df 多列,默认按行方向(axis=0)滚动,但结果仍是按列逐个计算——这点容易误以为“自动跨列聚合”,其实不是。
窗口类型分固定长度(rolling(3))、时间偏移(rolling('7D'),要求索引为 DatetimeIndex)、加权(rolling(window=5, win_type='gaussian'))三种。时间窗口最易出错:索引非时间类型时会抛 ValueError: window must be an integer,而不是提示索引问题。
- 固定窗口数用整数,如
df['x'].rolling(5).mean() - 时间窗口需先确保索引可排序且为 datetime:
df.index = pd.to_datetime(df.index) -
min_periods默认为窗口大小,设为 1 可让前几行也输出值(但含 NaN 的参与计算可能影响业务逻辑)
如何处理 NaN 和边界对齐问题
默认情况下,rolling() 计算结果与原始索引对齐,首 n-1 行(n 为窗口大小)返回 NaN。这不是 bug,而是设计行为:表示“无足够历史数据”。但很多人误以为要手动填充或截断。
真正要注意的是隐式 NaN 传播:如果原始数据已有 NaN,rolling().sum() 默认跳过它们(类似 skipna=True),但 rolling().count() 会统计非 NaN 个数,而 rolling().size() 返回窗口总长度(含 NaN)。这导致 sum / size ≠ mean,尤其在稀疏数据中。
- 显式控制 NaN 处理:所有聚合方法都支持
skipna=False参数,如s.rolling(3).sum(skipna=False) - 想让结果从第 1 行开始有值?改用
min_periods=1,但注意:第一个值就是原值,第二个是前两个均值,逻辑是否符合业务? - 右对齐是默认行为;左对齐需
df.rolling(3, closed='left'),适用于“不含当前点”的场景(如预警系统排除当前时刻)
自定义函数与 apply() 的性能陷阱
rolling().apply() 看似灵活,但底层是 Python 循环调用,比内置方法(mean、std)慢 10–100 倍。更隐蔽的问题是:apply 传入的子数组是视图还是副本?取决于 Pandas 版本和数据类型,修改它可能意外改变原数据,也可能报 SettingWithCopyWarning。
让 macOS 自动化像说话一样简单 —— 用代码控制你的 Mac,无需学习 AppleScript 系统要求 macOS 14+ (Sonoma) Python 3.9+ 需要开启:辅助功能 + 屏幕录制权限
如果你只是想做分位数、中位数等内置未覆盖的计算,优先查 rolling().quantile(0.5) 或 .median() —— 它们已高度优化。只有真正需要逐窗口定制逻辑时才用 apply。
- 避免在
apply里写 pandas 操作(如再调.mean()),这会触发二次开销 - 用
raw=True让apply接收 numpy 数组而非 Series,提速明显,但失去 index 信息 - 无法向量化时,考虑用
numba.jit加速你的函数,再传给apply
多列同时滚动与 groupby + rolling 组合
对多列统一滚动,别用循环列名。正确方式是直接作用于 DataFrame:df[['a', 'b']].rolling(5).mean(),返回同结构 DataFrame。但注意:各列独立计算,不跨列聚合。
真正复杂的是分组后滚动——比如“每个用户 ID 的最近 3 笔订单金额均值”。这时必须先 groupby('user_id'),再链式调用 rolling()。关键点在于:groupby 后的 rolling() 默认在每组内单独滚动,但索引仍保留原顺序,容易混淆。
- groupby + rolling 后务必重置索引或检查结果形状,否则合并回原表时可能错位
- 滚动窗口不跨组,这是安全设计;但若需“组内按时间排序后再滚动”,必须显式
sort_values并设dropna=False - 避免
df.groupby('id').rolling(3).x.mean()这种写法:它等价于先 groupby 再对每组 Series 滚动,但返回的是 MultiIndex,不易对齐
滚动计算真正的复杂点不在语法,而在语义对齐:窗口大小是日历日还是交易日?NaN 是缺失还是零值?分组滚动时排序是否稳定?这些不写进代码,只靠文档说明,后期维护极易出错。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










