移动平均是数据分析中用于平滑时序数据、过滤随机波动的常用方法,Python的pandas库提供的rolling窗口函数可以快速实现各类移动平均计算,结合matplotlib还能生成直观的平滑曲线。本文将从基础用法到实际场景逐一讲解。

rolling函数的基本语法
rolling函数是pandas Series和DataFrame对象的方法,核心作用是创建一个滑动窗口对象,再结合聚合函数完成计算。基本语法如下:
import pandas as pd # 基本语法结构 Series.rolling(window, min_periods=None, center=False, win_type=None)
参数说明:
- window:窗口大小,即参与计算的连续数据个数,可以是整数或者时间偏移量
- min_periods:窗口中最少需要的数据个数,默认等于window值,若数据不足则不计算结果
- center:是否将窗口中心对齐当前数据,默认False表示窗口左对齐
- win_type:窗口类型,默认None为等权重窗口,可指定三角、高斯等加权窗口
简单移动平均实现
简单移动平均是每个窗口内的数据取算术平均值,是最基础的移动平均类型。以下示例生成随机时序数据并计算3期简单移动平均:
import pandas as pd
import numpy as np
# 生成示例数据,模拟30天的销量数据
np.random.seed(42)
data = np.random.randint(50, 150, size=30)
dates = pd.date_range(start="2024-01-01", periods=30)
sales_series = pd.Series(data, index=dates)
# 计算3期简单移动平均,min_periods=1表示窗口至少1个数据就计算
ma_3 = sales_series.rolling(window=3, min_periods=1).mean()
print("原始数据前5条:")
print(sales_series.head())
print("n3期移动平均前5条:")
print(ma_3.head())
加权移动平均实现
加权移动平均会给窗口内不同位置的数据赋予不同权重,比如越靠近当前时间的数据权重越高。可以通过指定win_type参数实现,以下示例计算三角加权的3期移动平均:
# 计算三角加权的3期移动平均
weighted_ma = sales_series.rolling(window=3, win_type="triang").mean()
print("三角加权3期移动平均前5条:")
print(weighted_ma.head())
绘制平滑曲线
计算完成移动平均后,可以结合matplotlib将原始数据和平滑后的曲线绘制出来,直观对比平滑效果:
import matplotlib.pyplot as plt
# 设置中文字体,避免中文显示乱码
plt.rcParams["font.sans-serif"] = ["SimHei"]
plt.rcParams["axes.unicode_minus"] = False
# 绘制原始数据和移动平均曲线
plt.figure(figsize=(10, 6))
plt.plot(sales_series.index, sales_series.values, label="原始销量", alpha=0.5)
plt.plot(ma_3.index, ma_3.values, label="3期简单移动平均", linewidth=2)
plt.plot(weighted_ma.index, weighted_ma.values, label="3期三角加权移动平均", linewidth=2, linestyle="--")
plt.xlabel("日期")
plt.ylabel("销量")
plt.title("销量数据移动平均平滑效果对比")
plt.legend()
plt.grid(True, linestyle="--", alpha=0.7)
plt.show()
实际场景注意事项
在使用rolling函数计算移动平均时,需要注意几个常见问题:
- 如果处理的是时序数据,需要确保数据已经按照时间升序排列,否则窗口计算逻辑会出现偏差
- 窗口大小的选择需要根据数据特性调整,窗口越大平滑效果越强,但会丢失更多细节;窗口越小越贴近原始数据,平滑效果越弱
- 当数据存在缺失值时,rolling函数会默认跳过NaN值,若需要保留缺失值的影响,可以提前对数据进行填充处理
扩展:多列数据同时计算移动平均
如果是DataFrame结构的数据,需要对多列同时计算移动平均,可以直接对DataFrame调用rolling方法:
# 生成多列示例数据
df = pd.DataFrame({
"销量": np.random.randint(50, 150, size=30),
"客单价": np.random.uniform(20, 80, size=30).round(2)
}, index=pd.date_range(start="2024-01-01", periods=30))
# 对两列同时计算3期移动平均
df_ma = df.rolling(window=3, min_periods=1).mean()
print("多列移动平均结果前5条:")
print(df_ma.head())