首页 > 编程笔记 > Python笔记 阅读:33

Python rolling():移动窗口计算(附带实例)

Python 中,通过重采样我们可以得到想要的任何频率的数据,但是这些数据也是某个时间点的数据,因此存在这样一个问题,基于时间点的数据波动较大时,某一点的数据就不能很好地表现该事物的本身的特性。于是就有了“移动窗口”的概念,简单地说,为了提升数据的可靠性,将某个取值点扩大到包含这个点的一段区间,这个区间就是窗口。

举例说明,如下图所示,其中时间序列代表某月 1 号到 15 号每天的销量数据,接下来以 3 天为一个窗口,将该窗口从左至右依次移动,统计出 3 天的均值作为某个时间点的值,比如 3 号的销量是 1 号、2 号和 3 号销量的均值。


图 1 移动窗口示意图

通过图 1,相信你已经理解了移动窗口。在 Pandas 中可以通过 rolling() 函数实现移动窗口数据计算,语法格式如下:
DataFrame.rolling(window, min_periods=None, center=False, win_type=None, on=None, closed=None, step=None, method='single')
参数说明见下表:

参数 说明
window 整型、日期时间间隔对象、字符串、偏移量、BaseIndexer 子类,表示窗口移动的大小。如果是整型,则表示每个窗口的固定观测数;如果是日期时间间隔对象、字符串或偏移量,则表示每个窗口的时间段。每个窗口的大小将随着时间段内的观测值变化而变化,只对类似日期时间的索引有效;如果是 BaseIndexer 子类,则窗口边界的定义将基于 get_window_bounds() 方法
min_periods 整型,默认值为 None,表示每个窗口最少包含的观测值数量,小于这个值的窗口结果为 NA。由偏移量指定的窗口,默认值为 1;由整数指定的窗口,默认值为窗口的大小
center 布尔值,默认值为 False。如果参数值为 False,则将窗口标签设置为窗口索引的右侧边缘;如果参数值为 True,则将窗口标签设置为窗口索引的中心
win_type 字符串,默认值为 None。如果参数值为 None,则所有点都是均匀加权的;如果参数值为字符串,则必须是一个有效的变量,即窗口函数(scipy.signal.windows)
on 字符串,可选参数。对于 DataFrame 对象,要在其上计算移动窗口的列标签或索引级别。如果提供的是整数索引,其将被忽略并从结果中排除,因为整数索引不能用于计算移动窗口数据
closed 字符串,默认值为 None(right),参数值介绍如下:
  • right:窗口中的第一个点将被排除在计算之外;
  • left:窗口中的最后一个点将被排除在计算之外;
  • both:窗口中没有点被排除在计算之外;
  • neither:窗口中的第一个点和最后一个点将被排除在计算之外。
step 计算每个移动步骤产生的窗口数据
method 字符串,参数值为 single 或 table,默认值为 single,表示对单行/列执行移动操作;参数值为 table 表示对整个对象执行移动操作
返回值 为特定操作而生成的窗口或移动窗口子类

值得一提的是,Series 对象中也有 rolling() 方法,用法与 DataFrame 对象中的一样。


【实例】创建淘宝每日销量数据。
1) 首先模拟一组淘宝每日销量数据,程序代码如下:
# 导入pandas模块
import pandas as pd

# 创建日期数据
index=pd.date_range(start='20240201',end='20240215')

data=[300,600,700,400,209,1187,335,88,999,1100,112,515,613,222,114]

# 创建Series对象
sl_data=pd.Series(data,index=index)
print(sl_data)

2) 使用 rolling() 方法计算 2024-02-01 到 2024-02-15 期间每 3 天的均值,即窗口长度为 3,主要代码如下:
print(sl_data.rolling(3).mean())
运行程序,看一下 rolling() 方法是如何计算的。如下图所示:


图 2 2024-02-01 到 2024-02-15 的移动窗口均值1

当窗口开始移动时,第 1 个时间点 2024-02-01 和第 2 个时间点 2024-02-02 的数值为空值,这是因为窗口长度为 3,前面有空数据;而到第 3 个时间点 2024-02-03,它前面的数据是 2024-02-01 到 2024-02-03,所以 3 天的均值是 533.333333,以此类推。

3) 在计算第 1 个时间点 2024-02-01 的窗口数据时,虽然数据个数不够窗口长度 3,但至少有当天的数据,那么能否用当天的数据代表窗口数据呢?答案是肯定的,通过设置 min_periods 参数即可,它表示窗口中最少包含的观测值,小于这个值的窗口长度显示为空值,大于或等于时都有值,主要代码如下:
print(sl_data.rolling(window=3, min_periods=1).mean())
运行程序,结果如下图所示:


图 3 2024-02-01 到 2024-02-15 的移动窗口均值2

扩展上述示例,通过图表观察原始数据与移动窗口数据的平稳性,如下图所示:


图 4 移动窗口数据的平稳性

虚线代表原始数据,实线代表移动窗口数据。

其中实线代表移动窗口数据,其走向更平稳,这也是我们学习移动窗口 rolling() 方法的原因。

相关文章