2016-02-29 41 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