Pandas的窗口函数rolling和expanding用法说明

  • Post author:
  • Post category:其他




Pandas的窗口函数rolling和expanding



1、rolling 移动窗口

rolling() 移动窗口函数,它可以与 mean、count、sum、median、std 等聚合函数一起使用。为了使用方便,Pandas 为移动函数定义了专门的方法聚合方法,比如 rolling_mean()、rolling_count()、rolling_sum() 等。

其的语法格式如下:

rolling(window, min_periods=None, center=False, win_type=None, on=None, axis=0, closed=None)



(1)参数:

  • window:表示时间窗的大小,有两种形式:

    1)使用数值int,则表示观测值的数量,即向前几个数据;

    2)也可以使用offset类型,这种类型较复杂,使用场景较少,此处暂不做介绍;
  • min_periods:每个窗口最少包含的观测值数量,小于这个值的窗口结果为NA。值可以是int,默认None。offset情况下,默认为1;
  • center: 把窗口的标签设置为居中,布尔型,默认False,居右
  • win_type: 窗口的类型。截取窗的各种函数。字符串类型,默认为None;
  • on: 可选参数。对于dataframe而言,指定要计算滚动窗口的列。值为列名。
  • axis: 默认为0,即对列进行计算
  • closed:定义区间的开闭,支持int类型的window。对于offset类型默认是左开右闭的即默认为right。可以根据情况指定为left、both等。



(2)用例:

# -*- coding: utf-8 -*-
import pandas as pd
import numpy as np

seed = 8
s = pd.Series(range(seed), index=pd.date_range('2023-01-01', periods=seed, freq='1D'))
print(s)

print(s.rolling(window=3).sum())
print(s.rolling(window=3, min_periods=1).sum())
print(s.rolling(window='3D').sum())

结果如下:

2023-01-01    0
2023-01-02    1
2023-01-03    2
2023-01-04    3
2023-01-05    4
2023-01-06    5
2023-01-07    6
2023-01-08    7
Freq: D, dtype: int64
2023-01-01     NaN
2023-01-02     NaN
2023-01-03     3.0
2023-01-04     6.0
2023-01-05     9.0
2023-01-06    12.0
2023-01-07    15.0
2023-01-08    18.0
Freq: D, dtype: float64
2023-01-01     0.0
2023-01-02     1.0
2023-01-03     3.0
2023-01-04     6.0
2023-01-05     9.0
2023-01-06    12.0
2023-01-07    15.0
2023-01-08    18.0
Freq: D, dtype: float64
2023-01-01     0.0
2023-01-02     1.0
2023-01-03     3.0
2023-01-04     6.0
2023-01-05     9.0
2023-01-06    12.0
2023-01-07    15.0
2023-01-08    18.0
Freq: D, dtype: float64

print(s.rolling(window=3).sum())

窗口宽度是3,1月1日前两天无数据,是空值,因此1日和2日的结果都是NaN

2023-01-01     NaN
2023-01-02     NaN
2023-01-03     3.0

print(s.rolling(window=3, min_periods=1).sum())

为了解决上述问题,使用min_periods,如果没有数据,最小窗口就是1 ,所以1日和2日有数据。

2023-01-01     0.0
2023-01-02     1.0
2023-01-03     3.0

print(s.rolling(window=‘3D’).sum())

索引是日期,按索引的日期3天作为窗口宽度,则同使用min_periods=1参数一样的效果。



(3)用法拓展

rolling()函数除了sum(),还支持很多函数,比如:

count() 非空观测值数量

mean() 值的平均值

median() 值的算术中值

min() 最小值

max() 最大

std() 贝塞尔修正样本标准差

var() 无偏方差

skew() 样品偏斜度(三阶矩)

kurt() 样品峰度(四阶矩)

quantile() 样本分位数(百分位上的值)

cov() 无偏协方差(二元)

corr() 相关性(二进制)

还可以与agg聚合函数使用

df = pd.DataFrame({"A": range(5), "B": range(10, 15)})

df.rolling(window=2).agg([np.sum, np.mean, np.std])

结果如下:

在这里插入图片描述



2、expanding 扩展窗口函数

expanding() 扩展窗口函数,扩展是指由序列的第一个元素开始,逐个向后计算元素的聚合值。



(1)参数:

expanding()函数的参数,与rolling()函数的参数用法相同;

没有window参数

。不固定窗口大小,实现累计计算,即不断扩展。

rolling()函数,是固定窗口大小,进行滑动计算,expanding()函数只设置最小的观测值数量。

expanding()函数,类似cumsum()函数的累计求和,其优势在于还可以进行更多的聚类计算;



(2)用例:

seed =21
df = pd.DataFrame({'a':np.random.randint(20,500,seed),'b':np.random.randint(20,100,seed)}, index=pd.date_range('2020-01-01', periods=seed, freq='1D'))
df.index.name='testdate'

print(df)
print(df.expanding(min_periods=7).max())
print(df.expanding(min_periods=7).min())

最小窗口是7天,所以最大值和最小值,1日到6日都是NaN 。

窗口从7天,不断扩展到全部dataframe记录 。

a列:

2020-01-01 492 ,

一直到最后一天 ,超过了第一天的最大值,max值变化

2020-01-21 499.0

同理b列最大值。

结果如下:

              a   b
testdate           
2020-01-01  492  80
2020-01-02  399  73
2020-01-03  309  58
2020-01-04   66  38
2020-01-05  318  20
2020-01-06  488  29
2020-01-07  328  33
2020-01-08  347  25
2020-01-09  240  47
2020-01-10   80  71
2020-01-11  265  54
2020-01-12   33  65
2020-01-13  396  61
2020-01-14   71  54
2020-01-15   39  49
2020-01-16  189  48
2020-01-17   79  67
2020-01-18  303  62
2020-01-19  482  98
2020-01-20  208  27
2020-01-21  499  43
                a     b
testdate               
2020-01-01    NaN   NaN
2020-01-02    NaN   NaN
2020-01-03    NaN   NaN
2020-01-04    NaN   NaN
2020-01-05    NaN   NaN
2020-01-06    NaN   NaN
2020-01-07  492.0  80.0
2020-01-08  492.0  80.0
2020-01-09  492.0  80.0
2020-01-10  492.0  80.0
2020-01-11  492.0  80.0
2020-01-12  492.0  80.0
2020-01-13  492.0  80.0
2020-01-14  492.0  80.0
2020-01-15  492.0  80.0
2020-01-16  492.0  80.0
2020-01-17  492.0  80.0
2020-01-18  492.0  80.0
2020-01-19  492.0  98.0
2020-01-20  492.0  98.0
2020-01-21  499.0  98.0
               a     b
testdate              
2020-01-01   NaN   NaN
2020-01-02   NaN   NaN
2020-01-03   NaN   NaN
2020-01-04   NaN   NaN
2020-01-05   NaN   NaN
2020-01-06   NaN   NaN
2020-01-07  66.0  20.0
2020-01-08  66.0  20.0
2020-01-09  66.0  20.0
2020-01-10  66.0  20.0
2020-01-11  66.0  20.0
2020-01-12  33.0  20.0
2020-01-13  33.0  20.0
2020-01-14  33.0  20.0
2020-01-15  33.0  20.0
2020-01-16  33.0  20.0
2020-01-17  33.0  20.0
2020-01-18  33.0  20.0
2020-01-19  33.0  20.0
2020-01-20  33.0  20.0
2020-01-21  33.0  20.0



(3)用法拓展:

df = pd.DataFrame(
    np.random.rand(6, 4),
    index=pd.date_range("2022-01-01", periods=6),
    columns=["A", "B", "C", "D"],
)
print(df)
print (df.expanding(min_periods=3).mean())

print('mini window 3 mean result:')
print(df.iloc[0:3].mean())

print('last mean result')
print(df['A'].mean(),df['B'].mean(),df['C'].mean(),df['D'].mean())

3日的平均值,与df.iloc[0:3].mean() 等价。

6日的平均值,与df[‘A’].mean(),df[‘B’].mean(),df[‘C’].mean(),df[‘D’].mean()等价,或者是df.mean()等价 。

结果如下:

                   A         B         C         D
2022-01-01  0.697834  0.100287  0.652869  0.207896
2022-01-02  0.495769  0.010228  0.033768  0.311194
2022-01-03  0.404906  0.814433  0.447700  0.369165
2022-01-04  0.148014  0.980413  0.869525  0.760739
2022-01-05  0.925820  0.322119  0.363028  0.927978
2022-01-06  0.988882  0.997867  0.419070  0.276822
                   A         B         C         D
2022-01-01       NaN       NaN       NaN       NaN
2022-01-02       NaN       NaN       NaN       NaN
2022-01-03  0.532836  0.308316  0.378112  0.296085
2022-01-04  0.436631  0.476340  0.500966  0.412248
2022-01-05  0.534469  0.445496  0.473378  0.515394
2022-01-06  0.610204  0.537558  0.464327  0.475632
mini window 3 mean result:
A    0.532836
B    0.308316
C    0.378112
D    0.296085
dtype: float64
last mean result
0.6102041426142952 0.5375578633503776 0.4643265893696882 0.47563227350705956


再次理解一下扩展窗口的含义:


表示至少 3 个数求一次均值,计算方式为

A2=(A0+A1+A2)/3,

A3=(A0+A1+A2+A3)/4

A4=(A0+A1+A2+A3+A4)/5

A5 A6 依次类推。

df = pd.DataFrame({'a':range(5)})
print(df)
print(df.rolling(window=len(df), min_periods=1).mean())
print(df.expanding(min_periods=1).mean())

当rolling()函数的参数window=len(df)时,实现的效果与expanding()函数是一样的。结果如下:

     a
0  0
1  1
2  2
3  3
4  4
     a
0  0.0
1  0.5
2  1.0
3  1.5
4  2.0
     a
0  0.0
1  0.5
2  1.0
3  1.5
4  2.0



版权声明:本文为qq_39065491原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。