承接上一篇《Pandas 窗口函数 rolling》,本篇专门讲解 expanding 扩展窗口、ewm 指数加权窗口,对比 rolling,包含参数、代码示例、分组用法、业务场景、坑点,是时序指标、金融回测、数据平滑的常用工具,保持系列教程统一风格。
前置导入与示例数据
import pandas as pd
import numpy as np
df = pd.DataFrame({
"date": pd.date_range(start="2025-01-01", periods=10, freq="D"),
"value": [120, 90, 150, 130, 180, 160, 200, 170, 140, 190]
})
df = df.set_index("date")
print(df)
一、三者核心区别快速回顾
rolling:固定窗口大小,向前滑动,窗口重叠(3日移动平均)expanding:扩展窗口,从第一条数据一直包含到当前行,窗口持续变大ewm:指数加权窗口,距离当前越近的数据权重越高,权重指数衰减
rolling 是“固定长度滑动”;expanding 是“不断扩大的全集”;ewm 是“带权重衰减的平滑”
二、expanding 扩展窗口
2.1 基础语法
exp = df["value"].expanding(min_periods=1)
df["exp_sum"] = exp.sum()
df["exp_mean"] = exp.mean()
df["exp_max"] = exp.max()
df["exp_min"] = exp.min()
参数说明:
min_periods:最少有效样本数量,默认 1;达到这个数量才输出结果axis:维度方向,默认0(按列)method:计算方式,single单进程,table全表(新版pandas)
支持的聚合函数和 rolling 几乎一致:sum, mean, max, min, std, var, median, skew, corr, cov
2.2 和 cumsum 的关系
# 下面两行等价
df["value"].expanding().sum()
df["value"].cumsum()
cumsum/cummax/cummin 是 expanding 部分场景的简写;但 expanding 可以做均值、标准差、偏度等复杂统计,cumsum 只能做累计求和。
2.3 分组 expanding(groupby + expanding)
业务高频场景:每个品类、每个用户独立累计统计
df2 = pd.DataFrame({
"date": pd.date_range("2025-01-01", periods=12, freq="D"),
"cate": ["A","A","A","A","B","B","B","B","A","A","B","B"],
"sales": [120,90,150,130,180,160,200,170,140,190,110,135]
})
df2["exp_mean_cate"] = df2.groupby("cate")["sales"].expanding(min_periods=1).mean().reset_index(drop=True)
print(df2)
注意:groupby + expanding 返回 MultiIndex,需要
reset_index(drop=True)才能直接赋值回原DataFrame。
2.4 expanding 适用场景
累计收益率、累计最高水位、累计平均转化率、用户累计消费、累计最大回撤。
三、ewm 指数加权窗口(Exponentially Weighted Moving)
EWM,常用来计算 EWMA 指数加权移动平均,降噪、趋势平滑,股票、传感器时序非常常用。
核心思想:历史数据权重随时间指数衰减,越新的数据权重越高。
3.1 基础语法
# span=5 代表5周期EWMA
df["ewm_span5"] = df["value"].ewm(span=5, adjust=False).mean()
3.2 四大参数(四选一,控制衰减速度)
你只需要指定其中一个:
span:跨度,等效N周期,alpha = 2/(span+1)com:质心,alpha = 1/(com+1)halflife:半衰期,权重衰减到一半的时间alpha:直接指定衰减系数,范围0 < alpha ≤ 1
# alpha=0.3,最新数据权重0.3
df["ewm_alpha03"] = df["value"].ewm(alpha=0.3, adjust=False).mean()
3.3 adjust 参数(非常关键,很多人踩坑)
adjust=True(默认):使用递归标准EWM公式,适合理论计算adjust=False:简化公式,和金融软件(同花顺、通达信EWMA)对齐,做回测优先 False
3.4 支持的聚合
ewm 原生支持:mean, var, std, corr, cov,不支持max/min/median,这点和 rolling/expanding 不一样。
3.5 分组 ewm(groupby + ewm)
Pandas 1.2.0 之后支持分组指数加权
df2["ewm_span3"] = df2.groupby("cate")["sales"].ewm(span=3, adjust=False).mean().reset_index(drop=True)
print(df2)
3.6 ewm 适用场景
时序平滑降噪、波动率EWMA、行情均线、传感器信号过滤、在线指标平滑。
四、自定义函数:expanding.apply / ewm 说明
expanding.apply(func):支持传入自定义函数,用法和 rolling.apply 一致,但是性能同样偏弱
def range_func(x):
return x.max() - x.min()
df["exp_range"] = df["value"].expanding(min_periods=2).apply(range_func)
- ewm 没有
.apply(),ewm 只能使用内置的 mean/std/cov/corr,不能自定义函数。
五、三者对比汇总表
| 窗口类型 | 窗口形态 | 权重 | 典型输出 | 能否时间窗口 | 分组支持 |
|---|---|---|---|---|---|
| rolling | 固定长度滑动,重叠窗口 | 默认等权,支持win_type加权 | MA、滚动分位数、滚动极值 | ✅ 支持 5D、1H | ✅ |
| expanding | 从首行持续扩大到当前行 | 等权 | 累计均值、累计最大、累计标准差 | ❌ 仅按行数 | ✅ |
| ewm | 全量历史,指数衰减 | 近大远小 | EWMA、指数波动率 | ❌ 仅按行数 | ✅ |
六、高频坑清单
- expanding 不支持时间窗口(”5D”),只能按行数;想要时间范围累计,只能用rolling时间窗口
- ewm 没有 max/min 聚合,不能用来求指数加权最大值
adjust=True和adjust=False结果差异很大,对接金融指标要固定为False- groupby + expanding / ewm 会返回多层索引,直接赋值会报长度不匹配,必须 reset_index(drop=True)
- expanding 前几行 min_periods 设置不当会大量出现NaN
- ewm 对缺失值敏感,NaN会中断权重链,建议先填充时序缺失
七、综合实战模板
def add_exp_ewm_feature(df, col, span=5):
"""批量增加扩展窗口、EWM指标"""
df = df.sort_index()
# expanding
exp = df[col].expanding(min_periods=1)
df[f"{col}_exp_mean"] = exp.mean()
df[f"{col}_exp_max"] = exp.max()
# ewm
df[f"{col}_ewm_{span}"] = df[col].ewm(span=span, adjust=False).mean()
return df
df = add_exp_ewm_feature(df, "value", span=5)
print(df)
八、配套速记
- 需要N天滑动指标 → rolling
- 需要从开始到现在累计统计 → expanding
- 需要平滑、近期数据权重更高 → ewm
0 条笔记