gpt4 book ai didi

r - 基于命名列表对 data.table 进行子集化

转载 作者:行者123 更新时间:2023-12-01 16:23:14 26 4
gpt4 key购买 nike

我正在尝试对给定的 data.table 进行子集化

DT <- data.table(
a = c(1:20),
b = (3:4),
c = (5:14),
d = c(1:4)
)

在函数内通过一个命名列表的参数

param <- list(a = 1:10,
b = 2:3,
c = c(5, 7, 10))

我可能有点卡在这里,但我当然不想实现这样丑陋的东西。特别是因为它不是很动态。

DT[(if (!is.null(param$a))
a %in% param$a
else
TRUE)
&
(if (!is.null(param$b))
b %in% param$b
else
TRUE)
&
(if (!is.null(param$c))
c %in% param$c
else
TRUE)
&
(if (!is.null(param$d))
d %in% param$d
else
TRUE)]
   a b c d
1: 1 3 5 1
2: 3 3 7 3

有什么想法如何在 data.table 或基本 R 中使用命名列表的名称以优雅的方式实现此目的,以将 data.table 中的相应列与关联值进行子集化?谢谢!

编辑

我使用一些答案进行了微基准测试:

func_4 <- function(myp, DT) {
myp = Filter(Negate(is.null), param)

exs = Map(function(var, val)
call("%in%", var, val),
var = sapply(names(myp), as.name),
val = myp)
exi = Reduce(function(x, y)
call("&", x, y), exs)
ex = call("[", x = as.name("DT"), i = exi)
# eval(as.call(c(as.list(ex))))
eval(ex)
}

microbenchmark(
(DT[do.call(pmin, Map(`%in%`, DT[, names(param), with = FALSE], param)) == 1L]),
(DT[rowSums(mapply(`%in%`, DT[, names(param), with = FALSE], param)) == length(param)]),
(DT[do.call(CJ, param), on = names(param), nomatch = NULL]),
(DT[expand.grid(param), on = names(param), nomatch = NULL]),
(DT[DT[, all(mapply(`%in%`, .SD, param)), by = 1:nrow(DT), .SDcols = names(param)]$V1]),
(func_4(myp = param, DT = DT)),
times = 200)

min lq mean median uq max neval
446.656 488.5365 565.5597 511.403 533.7785 7167.847 200
454.120 516.3000 566.8617 538.146 561.8965 1840.982 200
2433.450 2538.6075 2732.4749 2606.986 2704.5285 10302.085 200
2478.595 2588.7240 2939.8625 2642.311 2743.9375 10722.578 200
2648.707 2761.2475 3040.4926 2814.177 2903.8845 10334.822 200
3243.040 3384.6220 3764.5087 3484.423 3596.9140 14873.898 200

最佳答案

您可以使用CJ (Cross Join) 函数来自 data.table从列表中创建过滤表。

lookup <- do.call(CJ, param)
head(lookup)
# a b c
# 1: 1 2 5
# 2: 1 2 7
# 3: 1 2 10
# 4: 1 3 5
# 5: 1 3 7
# 6: 1 3 10

DT[
lookup,
on = names(lookup),
nomatch = NULL
]
# a b c d
# 1: 1 3 5 1
# 2: 3 3 7 3

请注意nomatch = 0表示 lookup 中的任何组合DT 中不存在不会返回一行。

关于r - 基于命名列表对 data.table 进行子集化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55728200/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com