我有一个data.table,其中包含任意user_ids和一个测量的因变量:
library(data.table)
data <- data.table(user_id = round(runif(10,0,100),0), dv = round(runif(10, 0, 10),1))
我想构造一个新的表,它包含该表的所有顺序排列。为了澄清,我想完成
data_combined <- rbind(data[1:1, ],
data[1:2, ],
data[1:3, ],
...
data[1:n, ])
对于任意最大n行数。我做到这一点的最好方法是:
library(data.table)
data <- data.table(user_id = seq(1,10,1), dv = round(runif(10, 0, 10),1))
for(n in 1:nrow(data)){
ifelse(n > 1,
data_combined <- rbindlist(list(data_combined,
cbind(data[1:n, ], N = n))),
data_combined <- cbind(data[1:n, ], N = n)
)
}
这将创建所需的表,并附加一个新变量,该变量统计每次迭代期间添加的行数。
这是完成任务最有效的方法吗?这有点深奥,所以我不确定是否有特定的功能来实现它,但我也不确定我的解决方案是否一定是理想的(尤其是对于较大的最大组大小(
我认为你不太可能找到巨大的速度提升,至少除非你有非常大的数据。但是,如果您避免cbind
调用,您可以编写一个更短但速度不是两倍的版本。我还包括一个稍微快一点的。请注意,我将样本量增加到200,以提供更有意义的基准。
library(data.table)
N <- 200
data <- data.table(user_id = round(runif(N,0,100),0), dv = round(runif(N, 0, 10),1))
method1 <- function() {
for(n in 1:nrow(data)){
ifelse(n > 1,
data_combined <- rbindlist(list(data_combined,
cbind(data[1:n, ], N = n))),
data_combined <- cbind(data[1:n, ], N = n)
)
}
return(data_combined)
}
method2 <- function() {
data_combined <- lapply(1:nrow(data), function(i) data.table(data[1:i], N=i))
data_combined <- rbindlist(data_combined)
return(data_combined)
}
method3 <- function() {
data_combined <- list()
for (i in 1:nrow(data)) {
data_combined[[i]] <- data[1:i]
data_combined[[i]][, N := i]
}
data_combined <- rbindlist(data_combined)
return(data_combined)
}
检查结果是否相同:
all(method1() == method2())
#> [1] TRUE
all(method2() == method3())
#> [1] TRUE
基准:
library(microbenchmark)
microbenchmark(method1(), method2(), method3())
#> Unit: milliseconds
#> expr min lq mean median uq max neval cld
#> method1() 131.94106 150.40669 166.28043 157.02466 165.40358 408.1812 100 c
#> method2() 82.57354 100.94865 109.82735 106.36961 109.65404 202.5385 100 b
#> method3() 73.79046 90.20843 96.89102 96.14839 99.36719 193.2423 100 a