pandas.Series.rolling().mean()可高效实现移动平均,需确保索引为排序的DatetimeIndex并设合适window与min_periods;SimpleExpSmoothing须调用.fit()才能获得拟合结果,alpha应合理设置避免过拟合或滞后。

用 pandas.Series.rolling().mean() 做移动平均,别手写循环
移动平均本质是窗口内均值,pandas 的 rolling 方法直接封装了底层优化逻辑,比用 for 循环或 numpy.convolve 更安全、更易对齐时间索引。窗口大小(window)必须是正整数,且建议为奇数(如 3、5),否则中心对齐会偏移——pandas 默认居中对齐,但若数据末尾缺失值多,得配合 min_periods 控制容忍度。
常见错误是忽略索引类型:如果时间索引不是 DatetimeIndex 或未排序,rolling 仍会按行序计算,而非时间顺序。务必先执行 df.sort_index() 或 series = series.sort_index()。
示例:
import pandas as pd # 假设 ts 是带 DatetimeIndex 的 Series smoothed = ts.rolling(window=5, min_periods=3).mean()
用 statsmodels.tsa.holtwinters.SimpleExpSmoothing 做指数平滑,别调 alpha 盲目设 0.5
指数平滑不是“调个 alpha 就完事”。SimpleExpSmoothing 默认不优化参数,必须显式调用 .fit(),否则返回的是未拟合对象,.fittedvalues 为空。alpha 范围是 (0, 1),但设太高(如 >0.8)会让结果过度跟随噪声;太低(如 ses.fit(optimized=True)。
立即学习“Python免费学习笔记(深入)”;
注意输入必须是 1D array-like,不能是 DataFrame;若传入含 NaN 的序列,fit() 会直接报错 ValueError: Input contains NaN,需提前用 ts.dropna() 或插值处理。
示例:
from statsmodels.tsa.holtwinters import SimpleExpSmoothing ses = SimpleExpSmoothing(ts.dropna()) fitted = ses.fit(optimized=True) smoothed = fitted.fittedvalues
移动平均 vs 指数平滑:延迟、边界和实时性差异
移动平均有固定延迟:窗口为 n 时,输出比输入滞后约 (n-1)/2 步,无法用于实时预警;指数平滑无固定窗口,延迟随 alpha 增大而减小,更适合流式更新——只要保存上一期的平滑值 l_{t-1},新点到来时用 l_t = alpha * x_t + (1-alpha) * l_{t-1} 即可增量计算。
边界行为也不同:移动平均在起点产生 NaN(除非设 min_periods=1),而指数平滑默认用首值初始化,起点就有输出。但这也带来风险:若首值是异常点,会影响后续所有平滑结果,必要时可用前几期均值初始化。
性能上,纯 Python 实现的指数平滑循环比 pandas.rolling 快一个数量级(尤其大数据量),但前提是避免反复构造对象——把 l_t 当作状态变量传入函数,而非每次新建 SimpleExpSmoothing 实例。
别忽略原始噪声分布,先用 ts.diff().hist() 看波动模式
选方法前,先观察一阶差分分布:如果 ts.diff().hist() 显示长尾或双峰,说明噪声非高斯、可能含突变点,此时移动平均会被拉偏,指数平滑响应又太慢。这种情况下,应先用 scipy.signal.medfilt 做中值滤波去脉冲噪声,再套平滑。
另一个易漏点是重采样干扰:原始数据若是不等间隔采集(如传感器断连后补传),直接做 rolling 或 SES 会把时间空档误当正常间隔。必须先用 ts.resample('1H').mean() 对齐频率,再平滑。
最后提醒:平滑只是预处理,不是建模替代品。若后续要预测,SES 自带 .forecast(),而移动平均输出不能直接外推——它没状态,也没误差估计。


















