编辑
我发现了这个SO post,其中包括将丢失的行插入 data.table 的更好方法。功能fun_DT
相应调整。代码现在更干净了;我没有看到任何速度改进。
在另一篇文章中查看我的更新。Arun 的解决方案同样有效,但您必须手动插入缺失的组合。由于这里有更多标识符列(ID、Month),我在这里只提出了一个肮脏的解决方案(首先创建一个 ID2,然后创建所有 ID2-Category 组合,然后填充 data.table,然后进行整形)。
我很确定这不是最好的解决方案,但如果这个 FR是内置的,这些步骤可能会自动完成。
解决方案的速度大致相同,尽管看看它是如何扩展的会很有趣(我的机器太慢了,所以我不想进一步增加 n ......计算机已经经常崩溃了 ;-)
library(data.table)
library(rbenchmark)
fun_reshape <- function(n) {
DT <- data.table(
ID=sample(1:100, n, replace=TRUE),
Month=sample(1:12, n, replace=TRUE),
Category=sample(1:10, n, replace=TRUE),
Qty=runif(n)*500,
key=c('ID', 'Month')
)
agg <- DT[, list(Qty = sum(Qty)), by = c("ID", "Month", "Category")]
reshape(agg, v.names = "Qty", idvar = c("ID", "Month"),
timevar = "Category", direction = "wide")
}
#UPDATED!
fun_DT <- function(n) {
DT <- data.table(
ID=sample(1:100, n, replace=TRUE),
Month=sample(1:12, n, replace=TRUE),
Category=sample(1:10, n, replace=TRUE),
Qty=runif(n)*500,
key=c('ID', 'Month')
)
agg <- DT[, list(Qty = sum(Qty)), by = c("ID", "Month", "Category")]
agg[, ID2 := paste(ID, Month, sep="_")]
setkey(agg, ID2, Category)
agg <- agg[CJ(unique(ID2), unique(Category))]
agg[, as.list(setattr(Qty, 'names', Category)), by=list(ID2)]
}
library(rbenchmark)
n <- 1e+07
benchmark(replications=10,
fun_reshape(n),
fun_DT(n))
test replications elapsed relative user.self sys.self user.child sys.child
2 fun_DT(n) 10 45.868 1 43.154 2.524 0 0
1 fun_reshape(n) 10 45.874 1 42.783 2.896 0 0