我想在某些条件下扩展数据框。它有点类似于这个问题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的数据框,给定min和max week.number,并在此扩展的amount列中包含0。最小周数。数字为1,最大周数。数字为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)。
有一种简单,快捷的方法吗?
谢谢!
答案 0 :(得分: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.grid
和merge
:
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
答案 1 :(得分:5)
使用data.table
(tx到Frank以更正结果的长度):
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
# ......
修改强>
我刚注意到你的amount
和weeek.number
实际上定义了一个sparseVector
,即一个主要由零组成的向量,其中只保留非零元素的索引。因此,您可以尝试使用Matrix
包:
require(Matrix)
dt[,list(as.vector(sparseVector(amount,weeek.number,10))),by=ID]
获得与上面相同的结果。