我想重塑data.table,并包含每个变量的历史(累计求和)信息.该No变量指示对对象的测量的时间顺序ID.在每次测量时,都会找到其他信息.我想在No对象的每个时间戳聚合已知信息ID.
让我举个例子来证明:
对于以下data.table:
df <- data.table(ID=c(1,1,1,2,2,2,2),
No=c(1,2,3,1,2,3,4),
Variable=c('a','b', 'a', 'c', 'a', 'a', 'b'),
Value=c(2,1,3,3,2,1,5))
df
ID No Variable Value
1: 1 1 a 2
2: 1 2 b 1
3: 1 3 a 3
4: 2 1 c 3
5: 2 2 a 2
6: 2 3 a 1
7: 2 4 b 5
Run Code Online (Sandbox Code Playgroud)
我想重塑它:
ID No a b c
1: 1 1 2 NA NA
2: 1 2 2 1 NA
3: 1 3 5 1 NA
4: 2 1 NA NA 3
5: 2 2 2 NA 3
6: 2 3 3 NA 3
7: 2 4 3 5 3
Run Code Online (Sandbox Code Playgroud)
所以的累计值Value,每次Variable通过(ID, No),累积高No.
我可以在没有累积部分的情况下得到结果
dcast(df, ID+No~Variable, value.var="Value")
Run Code Online (Sandbox Code Playgroud)
这导致非累积变体:
ID No a b c
1: 1 1 2 NA NA
2: 1 2 NA 1 NA
3: 1 3 3 NA NA
4: 2 1 NA NA 3
5: 2 2 2 NA NA
6: 2 3 1 NA NA
7: 2 4 NA 5 NA
Run Code Online (Sandbox Code Playgroud)
任何想法如何使这累积?原始data.table有超过250,000行,因此效率很重要.
编辑:我只是用a,b,c作为例子,原始文件有大约40个不同的级别.而且,NAs很重要; 还有Value0的值,这意味着除了NA
可能的解决方案
好的,所以我找到了一个有效的解决方案.它远没有效率,因为它扩大了原始表格.
想法是复制每一行TotalNo - No时间,其中TotalNo最大值No为每行ID.然后可以使用原始dcast函数来提取数据帧.所以在代码中:
df[,TotalNo := .N, by=ID]
df2 <- df[rep(seq(nrow(df)), (df$TotalNo - df$No + 1))] #create duplicates
df3 <- df2[order(ID, No)]#, No:= seq_len(.N), by=.(ID, No)]
df3[,No:= seq(from=No[1], to=TotalNo[1], by=1), by=.(ID, No)]
df4<- dcast(df3,
formula = ID + No ~ Variable,
value.var = "Value", fill=NA, fun.aggregate = sum)
Run Code Online (Sandbox Code Playgroud)
它不是很好,因为重复的创建使用更多的内存.我认为它可以进一步优化,但到目前为止它适用于我的目的.在示例代码中,它从7行到16行,在原始文件中从241,670行到高达978,331.这超过了4倍.
解决方案 Eddi在完整数据集中改进了我的计算时间解决方案(Eddi的2.08秒,而我的4.36秒).这些是我可以使用的数字!谢谢大家!
您的解决方案很好,但是您添加了太多行,如果您cumsum事先计算出来,那么这些行是不必要的:
# add useful columns
df[, TotalNo := .N, by = ID][, CumValue := cumsum(Value), by = .(ID, Variable)]
# do a rolling join to extend the missing values, and then dcast
dcast(df[df[, .(No = seq(No[1], TotalNo[1])), by = .(ID, Variable)],
on = c('ID', 'Variable', 'No'), roll = TRUE],
ID + No ~ Variable, value.var = 'CumValue')
# ID No a b c
#1: 1 1 2 NA NA
#2: 1 2 2 1 NA
#3: 1 3 5 1 NA
#4: 2 1 NA NA 3
#5: 2 2 2 NA 3
#6: 2 3 3 NA 3
#7: 2 4 3 5 3
Run Code Online (Sandbox Code Playgroud)