2017-08-24 26 views
0

我正在將我的一個Spark項目遷移到Pandas,我遇到的其中一個問題是在每個組內的熊貓中實現滾動求和函數。滾動填充分組數據幀中間值

假設我有:

key time value 
A 1 10 
A 2 20 
A 4 30 
A 8 10 
B 1 15 
B 2 30 
B 3 15 

欲第一組由key,然後計算的滾動總和像上value填充中間時隙相對於time功能。例如,如果窗口大小爲2,我所期望的輸出將是:

key time output 
A 1 10  
A 2 30 (10+20)  
A 3 30 (10+20+0) 
A 4 50 (20+0+30) 
A 5 30 (0+30+0) 
A 6 30 (the same as above) 
A 8 10 (7 is 0 so it is omitted) 
A 9 10 
A 10 10 
B 1 15 
B 2 45 
B 3 60 
B 4 45 
B 5 15 

我一直在努力的group byapply了整整一個下午。有沒有一個聰明的方法來做到這一點?在火花我可以collect_list然後select一個udf到timevalue做到這一點,但熊貓似乎認爲不同於火花。

謝謝!

+0

你似乎是 「創造」 的數據。目前還不清楚A的輸出時間從1到5的時間以及B的輸出只有1到4的時間。 –

+0

@COLDSPEED由於窗口大小爲1,所以記錄的最後一個值持續1個時隙,抱歉不清楚。 – DarkZero

+0

是窗口大小2或3的結果? –

回答

0

IIUIC,這裏有一種方法。

首先創建dff新的時間窗口

In [1458]: dff = (df.groupby('key') 
        .apply(lambda x: pd.Series(range(x.time.min(), x.time.max()+2))) 
        .reset_index(name='time').drop('level_1', 1)) 
In [1459]: dff 
Out[1459]: 
    key time 
0 A  1 
1 A  2 
2 A  3 
3 A  4 
4 A  5 
5 B  1 
6 B  2 
7 B  3 
8 B  4 

然後,合併較早df,GROUPBY上key,增加電流,利用shift

In [1460]: dff.assign(ouput=dff.merge(df, how='left') 
           .fillna(0).groupby('key').value 
           .apply(lambda x: x+x.shift().fillna(0))) 
Out[1460]: 
    key time ouput 
0 A  1 10.0 
1 A  2 30.0 
2 A  3 20.0 
3 A  4 30.0 
4 A  5 30.0 
5 B  1 15.0 
6 B  2 45.0 
7 B  3 45.0 
8 B  4 15.0 
+0

謝謝,但我不知道這種方法是否有兩個問題:首先,它會從time.min到time.max產生連續的時隙,如果時間是'1,2,8,16',則會有很多浪費的插槽生成。其次,'shift'只適用於窗口大小爲1的情況,但情況並非總是如此...... – DarkZero

+0

我現在更改了問題描述中的示例數據。 – DarkZero

0

一種方式來處理,這是以前value在某個組中生成time的整個範圍,然後再做dropna

def make_rolling_sum(key, group, window): 
    time_range = range(group['time'].min(), group['time'].max() + 1 + window,) 
    df = group.set_index('time').reindex(time_range) 
    result = df.rolling(window, min_periods=1).sum() 
    result['key'] = key # the reindex drops a lot of NaN's in this column 
    return result.dropna().reset_index().reindex(columns=group.columns) 

window = 3 
pd.concat((make_rolling_sum(*group, window)for group in df.groupby('key')), ignore_index=True) 

產生

key  time value 
0 A 1 10.0 
1 A 2 30.0 
2 A 3 30.0 
3 A 4 50.0 
4 A 5 30.0 
5 A 6 30.0 
6 A 8 10.0 
7 A 9 10.0 
8 A 10 10.0 
9 B 1 15.0 
10 B 2 45.0 
11 B 3 60.0 
12 B 4 45.0 
13 B 5 15.0