2016-02-29 51 views
4

我想在給定條件下擴展數據幀。這與expand data frames inside data frame有點類似,但不完全相同。展開數據幀

我有一個數據幀:

df = data.frame(ID = c(3,3,3,3, 17,17,17, 74, 74, 210, 210, 210, 210), amount = c(101, 135, 101, 68, 196, 65 ,135, 76, 136, 15, 15, 15 ,15), week.number = c(4, 6, 8, 10, 2, 5, 7, 2, 6, 2, 3, 5, 6)) 

我想擴大對於每個ID,給定一個最小和最大week.number數據幀,並在這種擴張的量列具有0。閔week.number爲1,最大week.number是10.預期的結果將是:

df1 <- data.frame(ID = c(rep(3,10), rep(17, 10), rep(74, 10), rep(210, 10)), 
       amount = c(0, 0, 0, 101, 0, 135, 0, 101, 0, 68, 0, 196, 
         0, 0, 65, 0, 135, 0, 0, 0, 0, 76, 0, 0, 0, 
         136, 0, 0, 0, 0, 0, 15, 15, 0, 15, 15, 0, 0, 
         0, 0)) 

(在現實中,我有成千上萬的ID和週數去從1到160)。

有沒有簡單快捷的方法來做到這一點?

謝謝!

回答

5

隨着data.table(TX弗蘭克修正長度的結果):

require(data.table) 
dt<-as.data.table(df) 
f<-function(x,y,len=max(y)) {res<-numeric(len);res[y]<-x;res} 
dt[,list(amount=f(amount,weeek.number,10)),by=ID] 
#  ID amount 
# 1: 3  0 
# 2: 3  0 
# 3: 3  0 
# 4: 3 101 
# 5: 3  0 
# 6: 3 135 
# 7: 3  0 
# 8: 3 101 
# 9: 3  0 
#10: 3  68 
# ...... 

編輯

我只注意到你的amountweeek.number實際上定義了sparseVector,即主要由其中的非零元素的只是指數保持零向量。因此,您可以試用Matrix包裝:

require(Matrix) 
dt[,list(as.vector(sparseVector(amount,weeek.number,10))),by=ID] 

獲得與上述相同的結果。

+1

你說得對,我要編輯。 Tx用於注意。 – nicola

+0

謝謝!兩種解決方案都非常優雅我認爲,對於我的情況,sparseVector更有用,因爲擴展數據框時我會有更多的列保持不變。再次感謝! – Andres

5

這裏是你如何能使用tidyr做到這一點:

library(tidyr) 
complete(df, ID, weeek.number = 1:10, fill = list(amount = 0)) 
#Source: local data frame [40 x 3] 
# 
#  ID weeek.number amount 
# (dbl)  (dbl) (dbl) 
#1  3   1  0 
#2  3   2  0 
#3  3   3  0 
#4  3   4 101 
#5  3   5  0 
#6  3   6 135 
#7  3   7  0 
#8  3   8 101 
#9  3   9  0 
#10  3   10  68 
#.. ...   ... ... 

在基礎R的一種方法是使用expand.gridmerge

newdf <- merge(expand.grid(ID = unique(df$ID), weeek.number = 1:10), df, all.x = TRUE) 
newdf$amount[is.na(newdf$amount)] <- 0 # replace NA with 0 
+0

謝謝!雖然,我使用tidyr包得到一個錯誤:錯誤:位置必須介於0和n之間。將進一步調查。 – Andres

+0

@Andres,你有最新的tidyr版本嗎? (0.4.1) –

+0

我的第一個想法。是的,那是0.3.1。再次感謝! – Andres