2012-11-01 51 views
6

我有一個由許多堆棧時間序列組成的DataFrame。索引是(poolId,month),其中兩個都是整數,「月」是自2000年以來的月數。計算多個變量的滯後版本的最佳方法是什麼?移動MultiIndex時間序列的最有效方法

現在,我做這樣的事情:

cols_to_shift = ["bal", ...5 more columns...] 
df_shift = df[cols_to_shift].groupby(level=0).transform(lambda x: x.shift(-1)) 

對於我的數據,這花了我一個完整的60秒運行。 (我有48K不同池和共718k行。)

我來自R碼和等效data.table呼叫轉換此:

dt.shift <- dt[, list(bal=myshift(bal), ...), by=list(poolId)] 

只需要9 s到運行。 (這裏的「myshift」就像是「function(x)c(x [-1],NA)」。)

有沒有辦法讓熊貓verison回到速度明智的行列?我在0.8.1上測試了這個。

編輯:這裏是產生足夠接近的數據集的例子,這樣你就可以得到我的意思了一些想法:

ids = np.arange(48000) 
lens = np.maximum(np.round(15+9.5*np.random.randn(48000)), 1.0).astype(int) 
id_vec = np.repeat(ids, lens) 
lens_shift = np.concatenate(([0], lens[:-1])) 
mon_vec = np.arange(lens.sum()) - np.repeat(np.cumsum(lens_shift), lens) 
n = len(mon_vec) 
df = pd.DataFrame.from_items([('pool', id_vec), ('month', mon_vec)] + [(c, np.random.rand(n)) for c in 'abcde']) 
df = df.set_index(['pool', 'month']) 
%time df_shift = df.groupby(level=0).transform(lambda x: x.shift(-1)) 

這花了64號,當我嘗試過。這些數據從第0個月開始每個系列;真的,他們都應該在np.max(鏡頭)月份結束,開始日期不齊,但是足夠好。

編輯2:這是一些比較R代碼。這需要0.8秒。 80因素,不好。

library(data.table) 
ids <- 1:48000 
lens <- as.integer(pmax(1, round(rnorm(ids, mean=15, sd=9.5)))) 
id.vec <- rep(ids, times=lens) 
lens.shift <- c(0, lens[-length(lens)]) 
mon.vec <- (1:sum(lens)) - rep(cumsum(lens.shift), times=lens) 
n <- length(id.vec) 
dt <- data.table(pool=id.vec, month=mon.vec, a=rnorm(n), b=rnorm(n), c=rnorm(n), d=rnorm(n), e=rnorm(n)) 
setkey(dt, pool, month) 
myshift <- function(x) c(x[-1], NA) 
system.time(dt.shift <- dt[, list(month=month, a=myshift(a), b=myshift(b), c=myshift(c), d=myshift(d), e=myshift(e)), by=pool]) 
+0

這裏我打開一個GitHub的問題:https://github.com/pydata/pandas /問題/ 2162。我會看看 –

回答

6

我建議你重塑數據,做一個單班兌GROUPBY方法:

result = df.unstack(0).shift(1).stack() 

此切換級別的順序所以你要交換和重新排序:

result = result.swaplevel(0, 1).sortlevel(0) 

您可以驗證它已經被一個週期滯後(您想移(1)而不是shift(-1)):

In [17]: result.ix[1] 
Out[17]: 
       a   b   c   d   e 
month             
1  0.752511 0.600825 0.328796 0.852869 0.306379 
2  0.251120 0.871167 0.977606 0.509303 0.809407 
3  0.198327 0.587066 0.778885 0.565666 0.172045 
4  0.298184 0.853896 0.164485 0.169562 0.923817 
5  0.703668 0.852304 0.030534 0.415467 0.663602 
6  0.851866 0.629567 0.918303 0.205008 0.970033 
7  0.758121 0.066677 0.433014 0.005454 0.338596 
8  0.561382 0.968078 0.586736 0.817569 0.842106 
9  0.246986 0.829720 0.522371 0.854840 0.887886 
10  0.709550 0.591733 0.919168 0.568988 0.849380 
11  0.997787 0.084709 0.664845 0.808106 0.872628 
12  0.008661 0.449826 0.841896 0.307360 0.092581 
13  0.727409 0.791167 0.518371 0.691875 0.095718 
14  0.928342 0.247725 0.754204 0.468484 0.663773 
15  0.934902 0.692837 0.367644 0.061359 0.381885 
16  0.828492 0.026166 0.050765 0.524551 0.296122 
17  0.589907 0.775721 0.061765 0.033213 0.793401 
18  0.532189 0.678184 0.747391 0.199283 0.349949 

In [18]: df.ix[1] 
Out[18]: 
       a   b   c   d   e 
month             
0  0.752511 0.600825 0.328796 0.852869 0.306379 
1  0.251120 0.871167 0.977606 0.509303 0.809407 
2  0.198327 0.587066 0.778885 0.565666 0.172045 
3  0.298184 0.853896 0.164485 0.169562 0.923817 
4  0.703668 0.852304 0.030534 0.415467 0.663602 
5  0.851866 0.629567 0.918303 0.205008 0.970033 
6  0.758121 0.066677 0.433014 0.005454 0.338596 
7  0.561382 0.968078 0.586736 0.817569 0.842106 
8  0.246986 0.829720 0.522371 0.854840 0.887886 
9  0.709550 0.591733 0.919168 0.568988 0.849380 
10  0.997787 0.084709 0.664845 0.808106 0.872628 
11  0.008661 0.449826 0.841896 0.307360 0.092581 
12  0.727409 0.791167 0.518371 0.691875 0.095718 
13  0.928342 0.247725 0.754204 0.468484 0.663773 
14  0.934902 0.692837 0.367644 0.061359 0.381885 
15  0.828492 0.026166 0.050765 0.524551 0.296122 
16  0.589907 0.775721 0.061765 0.033213 0.793401 
17  0.532189 0.678184 0.747391 0.199283 0.349949 

逆足是不是用這種方法太糟糕了(可能在0.9.0是一個觸摸慢):

In [19]: %time result = df.unstack(0).shift(1).stack() 
CPU times: user 1.46 s, sys: 0.24 s, total: 1.70 s 
Wall time: 1.71 s 
+0

這是一個很大的改進!在0.8.1下花了6.6秒;希望下週我們可以安裝0.9.0,所以我可以試試。 –

+0

一個不同之處在於,由於它刪除了stack()上由shift()生成的NaN條目,所以它的行數比前一個少,但這在join()中得到了處理。 (我的意思是移位(-1);這是一個危險率計算,所以它是前瞻性的。) –

+0

我做的性能改進是在trunk中。努力盡快獲得新版本 –

相關問題