pandas中時間窗函式rolling的使用

weijian001發表於2017-12-20

在建模過程中,我們常常需要需要對有時間關係的資料進行整理。比如我們想要得到某一時刻過去30分鐘的銷量(產量,速度,消耗量等),傳統方法複雜消耗資源較多,pandas提供的rolling使用簡單,速度較快。

函式原型和引數說明

DataFrame.rolling(window, min_periods=None, freq=None, center=False, win_type=None, on=None, axis=0, closed=None)
  • window:表示時間窗的大小,注意有兩種形式(int or offset)。如果使用int,則數值表示計算統計量的觀測值的數量即向前幾個資料。如果是offset型別,表示時間窗的大小。pandas offset相關可以參考這裡

  • min_periods:最少需要有值的觀測點的數量,對於int型別,預設與window相等。對於offset型別,預設為1。

  • freq:從0.18版本中已經被捨棄。

  • center:是否使用window的中間值作為label,預設為false。只能在window是int時使用。

    
    # 為方便觀察,並列排列
    
    df = pd.DataFrame({'B': [0, 1, 2, np.nan, 4]})
    df.rolling(3, min_periods=1).sum()
    df.rolling(3, min_periods=1, center=True).sum()
        B    B1   B2
    0   0.0  0.0  1.0
    1   1.0  1.0  3.0
    2   2.0  3.0  3.0
    3   NaN  3.0  6.0
    4   4.0  6.0  4.0
  • win_type:視窗型別,預設為None一般不特殊指定,瞭解支援的其他視窗型別,參考這裡

  • on:對於DataFrame如果不使用index(索引)作為rolling的列,那麼用on來指定使用哪列。

  • closed:定義區間的開閉,曾經支援int型別的window,新版本已經不支援了。對於offset型別預設是左開右閉的即預設為right。可以根據情況指定為left both等。

  • axis:方向(軸),一般都是0。

舉例

一個簡單的場景,從A向B運送東西,我們想看一下以3秒作為一個時間窗運送的量。

# A地有兩個倉庫,都運往B。
df = pd.DataFrame({'1': ['A1', 'A2', 'A1', 'A2', 'A2', 'A1', 'A2'],
                  '2': ['B1', 'B1', 'B1', 'B1', 'B1', 'B1', 'B1'],
                  'num': [1,2,1,3,4,2,1]}, 
                 index = [pd.Timestamp('20130101 09:00:00'),
                          pd.Timestamp('20130101 09:00:01'),
                          pd.Timestamp('20130101 09:00:02'),
                          pd.Timestamp('20130101 09:00:03'),
                          pd.Timestamp('20130101 09:00:04'),
                          pd.Timestamp('20130101 09:00:05'),
                          pd.Timestamp('20130101 09:00:06')])
#   1   2   num
# 2013-01-01 09:00:00   A1  B1  1
# 2013-01-01 09:00:01   A2  B1  2
# 2013-01-01 09:00:02   A1  B1  1
# 2013-01-01 09:00:03   A2  B1  3
# 2013-01-01 09:00:04   A2  B1  4
# 2013-01-01 09:00:05   A1  B1  2
# 2013-01-01 09:00:06   A2  B1  1

使用rolling進行計算

# 首先我們先對groupby進行聚合(如果只有從A->B,那麼不用聚合一個rolling就可以)
# 以9:00:04秒為例,由於時間窗是3s,預設的closed是right,所以我們相加04,03,02秒的num,共有4+3+0=7
df.groupby(['1', '2'])['num'].rolling('3s').sum()
# 1   2                      
# A1  B1  2013-01-01 09:00:00    1.0
#         2013-01-01 09:00:02    2.0
#         2013-01-01 09:00:05    2.0
# A2  B1  2013-01-01 09:00:01    2.0
#         2013-01-01 09:00:03    5.0
#         2013-01-01 09:00:04    7.0
#         2013-01-01 09:00:06    5.0
# Name: num, dtype: float64

由於使用groupby,所以最後的結果是MultiIndex,想使用正常格式在DataFrame上使用reset_index()即可。

相關文章