什么是推荐的 “最佳 “过滤方式(关于性能)?data.table
根据这个表格的汇总形式计算的一些标准。
A reprex
说的比1000字还多。
library(data.table)
DT <- data.table(grp = rep(LETTERS[1:3], each = 3), x = 1:9)
setkey(DT, "grp")
DT[DT[, .(nok = any(x == 4)), by = grp][nok == FALSE]]
DT[DT[, .GRP[all(x != 4)], by = grp]]
我一下子就能想到这2种解决方案,我的直觉告诉我,第二种形式应该 “更好”(存储了较小的中间表,我不需要链式结果),但我想知道,有没有一种规范的形式来做这件事?
也许我首先不需要使用联接,可以用分组过滤的方式来对 i
争论?
这显然没有达到预期的效果 (by
显然只对 j
):
DT[all(x != 4), by = grp]
虽然这 所以回答 显示了另一种相同的方法,我主要关注的是性能。因此,我想知道,如果我想进一步在过滤后的data.table上工作(即使用另一个 j
筛选结果的表达式)
在我的实际案例中,我有大约16Mio行,大约4万个唯一键和14列。
因此,一个基准数据集可能看起来如下。
bench <- data.table(keys = rep(paste0("k", 1:40000), 400))
bench[, paste0("cols", 1:13) := replicate(13, sample(40000 * 400, TRUE),
simplify = FALSE)]
虽然我在寻找一个通用的答案(如果可能的话),不管最后选择的过滤器是什么,但实际的过滤器将是找出哪些组包含了任何一个组。NA
值。
解决方案:
我不认为有一种适用于所有情况的通用方法。这取决于数据集的特性,也取决于过滤标准。数据集可能有多个小组或整数键,而过滤可以使用更快的低级编程方法来实现。
这里有几个关于你的实际问题的选项(即过滤其中一列中带有NAs的组)。
DT_keys <- copy(DT)
system.time(setkey(DT_keys, keys))
# user system elapsed
# 1.50 0.67 1.32
DT_cols1 <- copy(DT)
system.time(setkey(DT_cols1, cols1))
# user system elapsed
# 4.21 0.21 1.30
microbenchmark::microbenchmark(times=1L,
m0 = DT_keys[, keys[is.na(cols1)], keys]$keys,
m1 = DT_keys[, if (anyNA(cols1)) keys, keys]$keys,
m2 = DT_cols1[.(NA_integer_)]$keys
)
1600万行虚数据的定时。
Unit: milliseconds
expr min lq mean median uq max neval
m0 90.675005 90.675005 90.675005 90.675005 90.675005 90.675005 1
m1 56.548620 56.548620 56.548620 56.548620 56.548620 56.548620 1
m2 4.010301 4.010301 4.010301 4.010301 4.010301 4.010301 1
对于你的实际数据集的大小来说,计时是非常快的。除非你运行过滤数百次,否则不会节省太多的时间。也许你可能想在运行时间之外保存一些其他类型的定时。
的数据。
library(data.table)
set.seed(0L)
nk <- 4e4L
nn <- 400L
DT <- data.table(keys = rep(paste0("k", 1L:nk), nn))
DT[, paste0("cols", 1L:13L) :=
replicate(13L, sample(c(NA_integer_, 1L:nk), nk * nn, TRUE), simplify = FALSE)]