簡體   English   中英

在熊貓的非連續值上應用滾動窗口

[英]Applying rolling window over non-consecutive values in pandas

我需要通過將滾動窗口應用於在數據幀中彼此不相鄰的值,為具有給定結構的數據幀計算新列。

我的數據框是由這樣的東西定義的:

df = pd.DataFrame([    
    {'date': date(2019,1,1), 'id': 1, 'value': 1},
    {'date': date(2019,1,1), 'id': 2, 'value': 10},
    {'date': date(2019,1,1), 'id': 3, 'value': 100},
    {'date': date(2019,1,2), 'id': 1, 'value': 2},
    {'date': date(2019,1,2), 'id': 2, 'value': 20},
    {'date': date(2019,1,2), 'id': 3, 'value': 200},
    {'date': date(2019,1,3), 'id': 1, 'value': 3},
    {'date': date(2019,1,3), 'id': 2, 'value': 30},
    {'date': date(2019,1,3), 'id': 3, 'value': 300},  
    {'date': date(2019,1,6), 'id': 1, 'value': 4},
    {'date': date(2019,1,6), 'id': 2, 'value': 40},
    {'date': date(2019,1,6), 'id': 3, 'value': 400},
                  ])
df=df.set_index(['date', 'id'], drop=False).sort_index()

給出的df如下所示:

                   date     id  value
date        id      
--------------+--------------------------   
2019-01-01  1 | 2019-01-01  1   1
            2 | 2019-01-01  2   10
            3 | 2019-01-01  3   100
2019-01-02  1 | 2019-01-02  1   2
            2 | 2019-01-02  2   20
            3 | 2019-01-02  3   200
2019-01-03  1 | 2019-01-03  1   3
            2 | 2019-01-03  2   30
            3 | 2019-01-03  3   300
2019-01-06  1 | 2019-01-06  1   4
            2 | 2019-01-06  2   40
            3 | 2019-01-06  3   400

我想測量每個id從一天(給定)到第二天的列的變化。 因此對於id==1 ,從2019-01-012019-01-02的更改是(2-1) / 1 = 2 ,從2019-01-032019-01-06(4-3) / 3 = 0.333

如果我像這樣重構df,以便所有值彼此相鄰,則可以計算所需的列:

restructured = df.reset_index(drop=True).set_index(['date']).sort_index()
df1 = restructured.groupby('id').rolling(2).apply(lambda x: (x.max()-x.min())/x.min(), raw=False)

在列值中產生所需的

                 id     value
id  date 
---------------+--------------------        
1   2019-01-01 | NaN    NaN
    2019-01-02 | 0.0    1.000000
    2019-01-03 | 0.0    0.500000
    2019-01-06 | 0.0    0.333333
2   2019-01-01 | NaN    NaN
    2019-01-02 | 0.0    1.000000
    2019-01-03 | 0.0    0.500000
    2019-01-06 | 0.0    0.333333
3   2019-01-01 | NaN    NaN
    2019-01-02 | 0.0    1.000000
    2019-01-03 | 0.0    0.500000
    2019-01-06 | 0.0    0.333333

我如何在原始結構中將此列連接/合並到df或以另一種方式計算值,以使結果數據幀如下所示(第一個添加列change_pct的 df):

                   date     id  value   change_pct
date        id      
--------------+---------------------------------    
2019-01-01  1 | 2019-01-01  1   1       NaN
            2 | 2019-01-01  2   10      NaN
            3 | 2019-01-01  3   100     NaN
2019-01-02  1 | 2019-01-02  1   2       1.000000
            2 | 2019-01-02  2   20      1.000000
            3 | 2019-01-02  3   200     1.000000
2019-01-03  1 | 2019-01-03  1   3       0.500000
            2 | 2019-01-03  2   30      0.500000
            3 | 2019-01-03  3   300     0.500000
2019-01-06  1 | 2019-01-06  1   4       0.333333
            2 | 2019-01-06  2   40      0.333333
            3 | 2019-01-06  3   400     0.333333

IIUC,這可能更簡單。

df['change_pct']=df.groupby('id')['value'].pct_change()

為此,請不要運行df=df.set_index(['date', 'id'], drop=False).sort_index() 只需直接在df上運行以上行即可。

輸出量

        date    id  value   change_pct
0   2019-01-01  1   1       NaN
1   2019-01-01  2   10      NaN
2   2019-01-01  3   100     NaN
3   2019-01-02  1   2       1.000000
4   2019-01-02  2   20      1.000000
5   2019-01-02  3   200     1.000000
6   2019-01-03  1   3       0.500000
7   2019-01-03  2   30      0.500000
8   2019-01-03  3   300     0.500000
9   2019-01-06  1   4       0.333333
10  2019-01-06  2   40      0.333333
11  2019-01-06  3   400     0.333333

您可以groupby與該指數的一部分level kwarg:

df.value.groupby(id, level=1).rolling(2).apply(lambda x: (x.max()-x.min())/x.min(), raw=False)

SH-SF的回答指導我解決了這個問題:

如果我只處理非索引df,問題就變得容易了:

df = pd.DataFrame([    
    {'date': date(2019,1,1), 'id': 1, 'value': 1},
    {'date': date(2019,1,1), 'id': 2, 'value': 10},
    {'date': date(2019,1,1), 'id': 3, 'value': 100},
    {'date': date(2019,1,2), 'id': 1, 'value': 2},
    {'date': date(2019,1,2), 'id': 2, 'value': 20},
    {'date': date(2019,1,2), 'id': 3, 'value': 200},
    {'date': date(2019,1,3), 'id': 1, 'value': 3},
    {'date': date(2019,1,3), 'id': 2, 'value': 30},
    {'date': date(2019,1,3), 'id': 3, 'value': 300},  
    {'date': date(2019,1,6), 'id': 1, 'value': 4},
    {'date': date(2019,1,6), 'id': 2, 'value': 40},
    {'date': date(2019,1,6), 'id': 3, 'value': 400},
])

df=df.sort_values(['id', 'date']) # make sure everything is in correct order

window_size=2 # the window size is adjustable

#calculate values
c= df.groupby('id')['value'].rolling(window_size).apply(lambda x: (x.max()-x.min())/x.min(), raw=False)

df[change_pct] = c.values # create new column in df

#now I can create the structure I need
df=df.set_index(['date', 'id'], drop=False).sort_index()

暫無
暫無

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

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