【发布时间】:2023-07-08 05:16:01
【问题描述】:
我想按组过滤一个大的data.table。我可以使用.SD 或.I,虽然我个人认为前者更容易阅读,但后者更快/使用更少的内存(尽管使用.SDcols)。
在某种程度上,我很清楚为什么。对于.I,我们只需要每组一个向量,而对于.SD,我们需要一个完整的data.table。但我认为通过提供有意义的.SDcol 参数,我可以加快/节省一些内存。
但是,基准测试表明.SD 方法慢了大约 60 倍,并且占用了 300 倍的内存。当然,一个 4 列的 .SD data.table 将需要超过向量大小的 4 倍。但是速度慢了 60 倍,内存增加了 300 倍?有人可以启发我,为什么.SD 方法会占用这么多内存,因此速度要慢得多?有没有一种方法可以加快.SD 方法的速度,或者是回退到.I 方法的唯一选择?
数据设置
library(data.table)
## data set up
nr <- 1e6
nc <- 100
grp_perc <- .8
DT <- data.table(ids = sample(paste0("id",
seq(1, round(grp_perc * nr, 0))),
nr, TRUE))
cols <- paste("col", seq(1, nc), sep = "_")
DT[, (cols) := replicate(nc, sample(nr), simplify = FALSE)]
基准测试
results <- bench::mark(.I = DT[DT[, .(row_id = .I[which.min(col_1)]),
by = ids]$row_id, c("ids", cols[1:3]), with = FALSE],
.SD = DT[, .SD[which.min(col_1)],
by = ids, .SDcols = cols[1:3]],
iterations = 1, filter_gc = FALSE)
summary(results)
# A tibble: 2 x 13 expression min median `itr/sec` mem_alloc `gc/sec` n_itr n_gc total_time result memory time gc <bch:expr> <bch:t> <bch:t> <dbl> <bch:byt> <dbl> <int> <dbl> <bch:tm> <list> <list> <list> <list> 1 .I 2.64s 2.64s 0.378 34.4MB 0 1 0 2.64s <df[,4] [571,~ <df[,3] [1,41~ <bch:~ <tibble ~ 2 .SD 2.73m 2.73m 0.00612 9.1GB 0.342 1 56 2.73m <df[,4] [571,~ <df[,3] [2,40~ <bch:~ <tibble ~
【问题讨论】:
-
我的理解是 .SD 方法较慢,因为它会导致
[.data.table的多个方法分派。请参阅此Github issue 和此SO answer。 -
非常有见地。谢谢,这很好地解释了这个问题,我认为对于类似的问题,我会在详细模式下查看更多关于
data.table内部的信息。
标签: r data.table microbenchmark