簡體   English   中英

動態窗口上的滾動總和

[英]Rolling sum on a dynamic window

我是 python 新手,上次編碼是在 80 年代中期,所以我感謝您的耐心幫助。

似乎 .rolling(window) 要求窗口是固定整數。 我需要一個滾動窗口,其中窗口或回溯期是動態的並由另一列給出。

在下表中,我尋找回溯和,它是回溯列指定的數據的滾動總和。

d={'Data':[1,1,1,2,3,2,3,2,1,2],
   'Lookback':[0,1,2,2,1,3,3,2,3,1],
   'LookbackSum':[1,2,3,4,5,8,10,7,8,3]}
df=pd.DataFrame(data=d)

例如:

   Data  Lookback  LookbackSum
0     1         0            1
1     1         1            2
2     1         2            3
3     2         2            4
4     3         1            5
5     2         3            8
6     3         3           10
7     2         2            7
8     1         3            8
9     2         1            3

您可以創建與df.apply一起使用的自定義函數,例如:

def lookback_window(row, values, lookback, method='sum', *args, **kwargs):
    loc = values.index.get_loc(row.name)
    lb = lookback.loc[row.name]
    return getattr(values.iloc[loc - lb: loc + 1], method)(*args, **kwargs)

然后將其用作:

df['new_col'] = df.apply(lookback_window, values=df['Data'], lookback=df['Lookback'], axis=1)

可能會有一些極端情況,但只要您的索引對齊並且是唯一的 - 它應該可以滿足您的要求。

這是一個帶有列表理解的列表,它存儲列df['Lookback']的索引和值,並通過反轉值並根據列值進行切片來獲取切片:

df['LookbackSum'] = [sum(df.loc[:e,'Data'][::-1].to_numpy()[:i+1]) 
                           for e,i in enumerate(df['Lookback'])]

print(df)

   Data  Lookback  LookbackSum
0     1         0            1
1     1         1            2
2     1         2            3
3     2         2            4
4     3         1            5
5     2         3            8
6     3         3           10
7     2         2            7
8     1         3            8
9     2         1            3

如果您想嘗試幾乎完全矢量化的方法,那就是痛苦的練習。 旁注:我認為這里不值得。 在所有。 靈感來自 Divakar在此處回答

鑒於:

import numpy as np
import pandas as pd
d={'Data':[1,1,1,2,3,2,3,2,1,2],
   'Lookback':[0,1,2,2,1,3,3,2,3,1],
   'LookbackSum':[1,2,3,4,5,8,10,7,8,3]}
df=pd.DataFrame(data=d)

使用 Divakar 的答案中的函數,但稍作修改

from skimage.util.shape import view_as_windows as viewW
def strided_indexing_roll(a, r, fill_value=np.nan):
    # Concatenate with sliced to cover all rolls
    p = np.full((a.shape[0],a.shape[1]-1),fill_value)
    a_ext = np.concatenate((p,a,p),axis=1)

    # Get sliding windows; use advanced-indexing to select appropriate ones
    n = a.shape[1]
    return viewW(a_ext,(1,n))[np.arange(len(r)), -r + (n-1),0]

現在,我們只需要為數據准備一個二維數組,並根據我們想要的回溯值獨立地移動行。

arr = df['Data'].to_numpy().reshape(1, -1).repeat(len(df), axis=0)
shifter = np.arange(len(df) - 1, -1, -1) #+ d['Lookback'] - 1
temp = strided_indexing_roll(arr, shifter, fill_value=0)
out = strided_indexing_roll(temp, (len(df) - 1 - df['Lookback'])*-1, 0).sum(-1)

輸出:

array([ 1,  2,  3,  4,  5,  8, 10,  7,  8,  3], dtype=int64)

然后我們可以根據需要將它分配回數據幀並檢查。

df['out'] = out
#output:
    Data    Lookback    LookbackSum out
0   1   0   1   1
1   1   1   2   2
2   1   2   3   3
3   2   2   4   4
4   3   1   5   5
5   2   3   8   8
6   3   3   10  10
7   2   2   7   7
8   1   3   8   8
9   2   1   3   3

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM