Я пытаюсь установить подмножество данных. Таблица
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 или base R, используя имена именованного списка для подстановки соответствующих столбцов в data.table со связанными значениями?
Спасибо!
EDIT
Я выполнил микробенчмарк с некоторыми ответами:
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