我想在某些条件下扩展数据框.它有点类似于这个问题在数据框内扩展数据帧,但不完全相同.
我有一个数据框:
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))
Run Code Online (Sandbox Code Playgroud)
我想扩展每个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))
Run Code Online (Sandbox Code Playgroud)
(实际上,我有成千上万的ID和周数从1到160).
有一个简单,快速的方法来做到这一点?
谢谢!
以下是使用以下方法的方法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
#.. ... ... ...
Run Code Online (Sandbox Code Playgroud)
基数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
Run Code Online (Sandbox Code Playgroud)
使用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
# ......
Run Code Online (Sandbox Code Playgroud)
编辑
我只注意到你的amount和weeek.number实际定义sparseVector,即主要由其中的非零元素的只是指数保持零向量.所以,你可以试试这个Matrix包:
require(Matrix)
dt[,list(as.vector(sparseVector(amount,weeek.number,10))),by=ID]
Run Code Online (Sandbox Code Playgroud)
得到与上面相同的结果.