rolling().mean()仅支持等权均值,因底层为C实现的滑动求和且不接受权重参数;win_type仅控制窗口形状,不改变等权逻辑;apply()不透传weights,需手动构造并校验长度。

直接用 rolling() 配合 apply() 是最灵活的方式,但默认不支持内置加权窗口;想用向量化性能,得手动构造权重并配合 np.average() 或 convolve。
为什么 rolling().mean() 不能直接做加权平均
Pandas 的 rolling().mean() 是等权均值,底层调用的是 C 实现的滑动求和+计数,不接受权重参数。即使传入 win_type(比如 'gaussian'),它也只影响窗口形状,最终仍是对窗口内值做等权平均,不是你想要的「按自定义权重加权」。
-
win_type='triangular'仅控制窗口衰减形态,不改变加权逻辑 -
rolling().apply(np.average, weights=...)会报错 ——apply不把weights透传给np.average - 权重必须在
apply内部显式构造,且长度需严格匹配当前窗口
用 rolling().apply() + 手动加权(最通用)
适合权重固定、窗口大小固定、逻辑需自定义的场景,比如前 3 期按 [0.5, 0.3, 0.2] 加权。
安全 Python 代码沙箱:在隔离的沙箱中执行任意 Python 代码,预装 requests、NumPy、pandas 库。返回 stdout、stderr。
import pandas as pd import numpy as np <p>s = pd.Series([1, 2, 3, 4, 5]) weights = np.array([0.5, 0.3, 0.2])</p><p>result = s.rolling(window=3).apply( lambda x: np.average(x, weights=weights) if len(x) == 3 else np.nan, raw=False )
- 必须加
if len(x) == 3 else np.nan:滚动初期窗口不满,x长度不足,np.average会因权重长度不匹配报ValueError -
raw=False(默认)才能把x当Series处理,方便取值;设为True会传ndarray,但权重仍需对齐 - 性能一般:Python 层循环,大数据量时明显慢于向量化方法
用 np.convolve() 实现向量化加权滚动(最快)
当权重是固定数组、窗口大小恒定、且允许首尾填充 nan 时,这是最优解。本质是把加权平均转为一维卷积。
立即学习“Python免费学习笔记(深入)”;
w = np.array([0.5, 0.3, 0.2]) # 卷积后需除以权重和(此处为 1.0),若权重未归一化要显式除 conv = np.convolve(s, w[::-1], mode='valid') # 注意反转权重 result = pd.Series(conv, index=s.index[2:]) # 对齐索引
- 权重必须反转:
np.convolve是“翻转后滑动点乘”,而滚动窗口是正序对齐,所以传w[::-1] -
mode='valid'自动截掉边界不完整部分,结果比原序列短window-1个元素 - 无法处理
min_periods类逻辑(比如允许窗口从 1 开始计算),也不支持center=True - 若权重和不为 1,必须手动除:例如
w=[1,2,1]要写np.convolve(s, w[::-1]) / w.sum()
容易被忽略的边界与 dtype 问题
加权滚动最常出问题的地方不在主逻辑,而在边缘细节:
- 输入
Series若含NaN,np.average(..., weights=...)默认不忽略,会传播NaN;如需跳过,得先dropna()或改用np.nansum(x * w) / np.nansum(w) - 权重数组类型最好显式设为
float64,否则混合int权重和float数据可能导致意外截断 - 使用
convolve时,若原始数据是Int64(nullable int),卷积会强制转为float64,无法保留整数语义 -
rolling(window=n).apply(...)在axis=1(DataFrame 行方向)时行为不同,权重需按行构造,别直接复用列方向代码

















