pandas之滑动窗口学习笔记(shift, diff, pct_change)

窗口对象

pandas 中有3类窗口,分别是滑动窗口 rolling 、扩张窗口 expanding 以及指数加权窗口 ewm

滑窗对象

要使用滑窗函数,就必须先要对一个序列使用 .rolling 得到滑窗对象,其最重要的参数为窗口大小 window

In [95]: s = pd.Series([1,2,3,4,5])

In [96]: roller = s.rolling(window = 3)

In [97]: roller
Out[97]: Rolling [window=3,center=False,axis=0]

在得到了滑窗对象后,能够使用相应的聚合函数进行计算,需要注意的是窗口包含当前行所在的元素,例如在第四个位置进行均值运算时,应当计算(2+3+4)/3,而不是(1+2+3)/3

In [98]: roller.mean()
Out[98]: 
0    NaN
1    NaN
2    2.0
3    3.0
4    4.0
dtype: float64

In [99]: roller.sum()
Out[99]: 
0     NaN
1     NaN
2     6.0
3     9.0
4    12.0
dtype: float64

对于滑动相关系数或滑动协方差的计算,可以如下写出:

In [100]: s2 = pd.Series([1,2,6,16,30])

In [101]: roller.cov(s2)
Out[101]: 
0     NaN
1     NaN
2     2.5
3     7.0
4    12.0
dtype: float64

In [102]: roller.corr(s2)
Out[102]: 
0         NaN
1         NaN
2    0.944911
3    0.970725
4    0.995402
dtype: float64

此外,还支持使用 apply 传入自定义函数,其传入值是对应窗口的 Series ,例如上述的均值函数可以等效表示:

In [103]: roller.apply(lambda x:x.mean())
Out[103]: 
0    NaN
1    NaN
2    2.0
3    3.0
4    4.0
dtype: float64

shift, diff, pct_change 是一组类滑窗函数,它们的公共参数为 periods=n ,默认为1,这里的 n 可以为负,表示反方向的类似操作。

函数说明
shift取向前第 n 个元素的值
diff与向前第 n 个元素做差(与 Numpy 中不同,后者表示 n 阶差分)
pct_change与向前第 n 个元素相比计算增长率
In [104]: s = pd.Series([1,3,6,10,15])

In [105]: s.shift(2)
Out[105]: 
0    NaN
1    NaN
2    1.0
3    3.0
4    6.0
dtype: float64

In [106]: s.diff(3)
Out[106]: 
0     NaN
1     NaN
2     NaN
3     9.0
4    12.0
dtype: float64

In [107]: s.pct_change()
Out[107]: 
0         NaN
1    2.000000
2    1.000000
3    0.666667
4    0.500000
dtype: float64

In [108]: s.shift(-1)
Out[108]: 
0     3.0
1     6.0
2    10.0
3    15.0
4     NaN
dtype: float64

In [109]: s.diff(-2)
Out[109]: 
0   -5.0
1   -7.0
2   -9.0
3    NaN
4    NaN
dtype: float64

将其视作类滑窗函数的原因是,它们的功能可以用窗口大小为 n+1 的 rolling 方法等价代替

In [110]: s.rolling(3).apply(lambda x:list(x)[0]) # s.shift(2)
Out[110]: 
0    NaN
1    NaN
2    1.0
3    3.0
4    6.0
dtype: float64

In [111]: s.rolling(4).apply(lambda x:list(x)[-1]-list(x)[0]) # s.diff(3)
Out[111]: 
0     NaN
1     NaN
2     NaN
3     9.0
4    12.0
dtype: float64

In [112]: def my_pct(x):
   .....:     L = list(x)
   .....:     return L[-1]/L[0]-1
   .....: 

In [113]: s.rolling(2).apply(my_pct) # s.pct_change()
Out[113]: 
0         NaN
1    2.000000
2    1.000000
3    0.666667
4    0.500000
dtype: float64

扩张窗口

扩张窗口又称累计窗口,可以理解为一个动态长度的窗口,其窗口的大小就是从序列开始处到具体操作的对应位置,其使用的聚合函数会作用于这些逐步扩张的窗口上。具体地说,设序列为a1, a2, a3, a4,则其每个位置对应的窗口即[a1]、[a1, a2]、[a1, a2, a3]、[a1, a2, a3, a4]。

In [114]: s = pd.Series([1, 3, 6, 10])

In [115]: s.expanding().mean()
Out[115]: 
0    1.000000
1    2.000000
2    3.333333
3    5.000000
dtype: float64

cummax, cumsum 函数是典型的类扩张窗口函数,请使用 expanding 对象依次实现它们。

s = pd.Series([1, 3, 6, 10])

#cumsum
s.expanding().sum()

0    1.000000
1    2.000000
2    3.333333
3    5.000000
dtype: float64

#cummax
s.expanding().max()

0     1.0
1     3.0
2     6.0
3    10.0
dtype: float64

指数加权窗口

作为扩张窗口的 ewm 窗口
在扩张窗口中,用户可以使用各类函数进行历史的累计指标统计,但这些内置的统计函数往往把窗口中的所有元素赋予了同样的权重。事实上,可以给出不同的权重来赋给窗口中的元素,指数加权窗口就是这样一种特殊的扩张窗口。
其中,最重要的参数是 alpha,它决定了默认情况下的窗口权重为
w i = ( 1 − α ) i , i ∈ { 0 , 1 , 2 , . . . , t } w_{i}=(1-\alpha)^{i},i\in \{0,1,2,...,t\} wi=(1α)i,i{0,1,2,...,t},其中 i = t i=t i=t 表示当前元素, i = 0 i=0 i=0 表示序列的第一个元素。

从权重公式可以看出,离开当前值越远则权重越小,若记原序列为 x ,更新后的当前元素为 yt ,此时通过加权公式归一化后可知:
y t = ∑ i = 0 t w i x t − i ∑ i = 0 t w i = x t + ( 1 − α ) x t − 1 + ( 1 − α ) 2 x t − 2 + . . .   ( 1 − α ) t x 0 1 + ( 1 − α ) + ( 1 − α ) 2 + . . .   ( 1 − α ) t y_{t}=\frac{\sum_{i=0}^{t} w_i x_{t-i}}{\sum_{i=0}^{t} w_i}=\frac{x_t + (1 - \alpha)x_{t-1} + (1 - \alpha)^2 x_{t-2} + ... \ (1 - \alpha)^{t} x_{0}}{1 + (1 - \alpha) + (1 - \alpha)^2 + ... \ (1 - \alpha)^{t}} yt=i=0twii=0twixti=1+(1α)+(1α)2+... (1α)txt+(1α)xt1+(1α)2xt2+... (1α)tx0
对于 Series 而言,可以用 ewm 对象如下计算指数平滑后的序列:

In [118]: np.random.seed(0)

In [119]: s = pd.Series(np.random.randint(-1,2,30).cumsum())

In [120]: s.head()
Out[120]: 
0   -1
1   -1
2   -2
3   -2
4   -2
dtype: int32

In [121]: s.ewm(alpha=0.2).mean().head()
Out[121]: 
0   -1.000000
1   -1.000000
2   -1.409836
3   -1.609756
4   -1.725845
dtype: float64
  • 2
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值