为Pandas滚动均值自定义对称加权窗口类型的实现方法
这个需求很常见!Pandas自带的窗口类型确实没法直接实现这种自定义的对称加权逻辑,但我们可以用rolling.apply()方法来轻松搞定,下面是具体的实现方案:
直接实现自定义加权函数
首先,我们可以针对你需要的权重[1/6, 2/6, 2/6, 1/6],写一个专门的加权计算函数,然后通过rolling.apply()把它应用到滚动窗口上:
import pandas as pd # 生成测试数据 rs = pd.Series(range(10)) # 定义自定义加权均值函数 def symmetric_weighted_mean(window): # 对应公式:(a + 2*b + 2*c + d)/6 return (window[0] + 2 * window[1] + 2 * window[2] + window[3]) / 6 # 应用滚动窗口计算,raw=True提升处理效率(传递numpy数组而非Series) custom_result = rs.rolling(window=4).apply(symmetric_weighted_mean, raw=True) print(custom_result)
运行这段代码后,输出结果为:
0 NaN 1 NaN 2 NaN 3 1.500000 4 2.500000 5 3.500000 6 4.500000 7 5.500000 8 6.500000 9 7.500000 dtype: float64
你会发现用range(10)测试时,结果和boxcar窗口的均值一致——这是因为连续整数的对称加权和均等加权刚好巧合相等。如果换一组非连续的数据,比如pd.Series([1,2,4,8,16,32]),就能看到明显差异:
- 自定义加权结果:
NaN, NaN, NaN, 3.5, 8.166667, 18.333333 - Boxcar窗口结果:
NaN, NaN, NaN, 3.75, 7.5, 15.0
更通用的实现方式
如果以后需要调整权重,我们可以写一个更通用的函数,通过functools.partial来传入权重参数,这样扩展性更强:
import pandas as pd from functools import partial def weighted_mean(window, weights): # 通用加权均值计算:(窗口元素 * 权重)的和 / 权重总和 return (window * weights).sum() / sum(weights) # 定义你的对称权重 target_weights = [1, 2, 2, 1] # 包装成带固定权重的函数 custom_weighted_func = partial(weighted_mean, weights=target_weights) rs = pd.Series([1,2,4,8,16,32]) result = rs.rolling(window=4).apply(custom_weighted_func, raw=True) print(result)
为什么不用自定义win_type?
Pandas的win_type参数依赖Scipy的窗口函数API,要自定义窗口类型需要注册新的窗口类,步骤相对繁琐。而rolling.apply()的方式更直观灵活,能快速实现任何自定义的滚动计算逻辑,适合这类小众的加权需求。
内容的提问来源于stack exchange,提问作者Tanmay
相关产品推荐
相关产品推荐

