天天看點

Pandas進階教程之:window操作

文章目錄

  • 簡介
  • 滾動視窗
    • Center window
  • Weighted window 權重視窗
  • 擴充視窗
  • 指數權重視窗

在資料統計中,經常需要進行一些範圍操作,這些範圍我們可以稱之為一個window 。Pandas提供了一個rolling方法,通過滾動window來進行統計計算。

本文将會探讨一下rolling中的window用法。

我們有5個數,我們希望滾動統計兩個數的和,那麼可以這樣:

In [1]: s = pd.Series(range(5))

In [2]: s.rolling(window=2).sum()
Out[2]: 
0    NaN
1    1.0
2    3.0
3    5.0
4    7.0
dtype: float64
           

rolling 對象可以通過for來周遊:

In [3]: for window in s.rolling(window=2):
   ...:     print(window)
   ...: 
0    0
dtype: int64
0    0
1    1
dtype: int64
1    1
2    2
dtype: int64
2    2
3    3
dtype: int64
3    3
4    4
dtype: int64
           

pandas中有四種window操作,我們看下他們的定義:

名稱 方法 傳回對象 是否支援時間序列 是否支援鍊式groupby操作
固定或者可滑動的視窗

rolling

Rolling

Yes
scipy.signal庫提供的權重非矩形視窗

rolling

Window

No
累積值的視窗

expanding

Expanding

值上的累積和指數權重視窗

ewm

ExponentialMovingWindow

Yes (as of version 1.2)

​ 看一個基于時間rolling的例子:

In [4]: s = pd.Series(range(5), index=pd.date_range('2020-01-01', periods=5, freq='1D'))

In [5]: s.rolling(window='2D').sum()
Out[5]: 
2020-01-01    0.0
2020-01-02    1.0
2020-01-03    3.0
2020-01-04    5.0
2020-01-05    7.0
Freq: D, dtype: float64
           

設定min_periods可以指定window中的最小的NaN的個數:

In [8]: s = pd.Series([np.nan, 1, 2, np.nan, np.nan, 3])

In [9]: s.rolling(window=3, min_periods=1).sum()
Out[9]: 
0    NaN
1    1.0
2    3.0
3    3.0
4    2.0
5    3.0
dtype: float64

In [10]: s.rolling(window=3, min_periods=2).sum()
Out[10]: 
0    NaN
1    NaN
2    3.0
3    3.0
4    NaN
5    NaN
dtype: float64

# Equivalent to min_periods=3
In [11]: s.rolling(window=3, min_periods=None).sum()
Out[11]: 
0   NaN
1   NaN
2   NaN
3   NaN
4   NaN
5   NaN
dtype: float64
           

預設情況下window的統計是以最右為準,比如window=5,那麼前面的0,1,2,3 因為沒有達到5,是以為NaN。

In [19]: s = pd.Series(range(10))

In [20]: s.rolling(window=5).mean()
Out[20]: 
0    NaN
1    NaN
2    NaN
3    NaN
4    2.0
5    3.0
6    4.0
7    5.0
8    6.0
9    7.0
dtype: float64
           

可以對這種方式進行修改,設定 center=True 可以從中間統計:

In [21]: s.rolling(window=5, center=True).mean()
Out[21]: 
0    NaN
1    NaN
2    2.0
3    3.0
4    4.0
5    5.0
6    6.0
7    7.0
8    NaN
9    NaN
dtype: float64
           

使用 win_type 可以指定權重視窗的類型。其中win_type 必須是scipy.signal 中的window類型。

舉幾個例子:

In [47]: s = pd.Series(range(10))

In [48]: s.rolling(window=5).mean()
Out[48]: 
0    NaN
1    NaN
2    NaN
3    NaN
4    2.0
5    3.0
6    4.0
7    5.0
8    6.0
9    7.0
dtype: float64

In [49]: s.rolling(window=5, win_type="triang").mean()
Out[49]: 
0    NaN
1    NaN
2    NaN
3    NaN
4    2.0
5    3.0
6    4.0
7    5.0
8    6.0
9    7.0
dtype: float64

# Supplementary Scipy arguments passed in the aggregation function
In [50]: s.rolling(window=5, win_type="gaussian").mean(std=0.1)
Out[50]: 
0    NaN
1    NaN
2    NaN
3    NaN
4    2.0
5    3.0
6    4.0
7    5.0
8    6.0
9    7.0
dtype: float64
           

擴充視窗會産生聚合統計資訊的值,其中包含該時間點之前的所有可用資料。

In [51]: df = pd.DataFrame(range(5))

In [52]: df.rolling(window=len(df), min_periods=1).mean()
Out[52]: 
     0
0  0.0
1  0.5
2  1.0
3  1.5
4  2.0

In [53]: df.expanding(min_periods=1).mean()
Out[53]: 
     0
0  0.0
1  0.5
2  1.0
3  1.5
4  2.0
           

指數權重視窗與擴充視窗相似,但每個先驗點相對于目前點均按指數權重。

權重計算的公式是這樣的:

y t = Σ i = 0 t w i x t − i Σ i = 0 t w i y_t=Σ^t_{i=0}{w_ix_{t-i}\over{Σ^t_{i=0}w_i}} yt​=Σi=0t​Σi=0t​wi​wi​xt−i​​

其中 x t x_t xt​是輸入, y t y_t yt​是輸出, w i w_i wi​是權重。

EW有兩種模式,一種模式是

adjust=True

,這種情況下 Font metrics not found for font: .

一種模式是

adjust=False

,這種情況下:

$$

y_0=x_0\n

y_t=(1-a)y_{t-1}+ax_t

其中 0<????≤1, 根據EM方式的不同a可以有不同的取值:

a = { 2 s + 1 s p a n 模 式 其 中 s > = 1 1 1 + c c e n t e r o f m a s s c > = 0 1 − e x p l o g 0.5 h h a l f − l i f e h > 0 a=\{ {{2\over {s+1}} \qquad span模式 其中s >= 1\\ {1\over{1+c}}\qquad center of mass c>=0 \\ 1-exp^{log0.5\over h} \qquad half-life h > 0 } a={s+12​span模式其中s>=11+c1​centerofmassc>=01−exphlog0.5​half−lifeh>0

In [54]: df = pd.DataFrame({"B": [0, 1, 2, np.nan, 4]})

In [55]: df
Out[55]: 
     B
0  0.0
1  1.0
2  2.0
3  NaN
4  4.0

In [56]: times = ["2020-01-01", "2020-01-03", "2020-01-10", "2020-01-15", "2020-01-17"]

In [57]: df.ewm(halflife="4 days", times=pd.DatetimeIndex(times)).mean()
Out[57]: 
          B
0  0.000000
1  0.585786
2  1.523889
3  1.523889
4  3.233686
           

繼續閱讀