create a filter expression (i) dynamically in data.table

不问归期 提交于 2020-01-04 02:43:07

问题


Having a data.table

library(data.table)
dd <- data.table(x=1:10,y=10:1,z=20:20)

I can filter it using

dd[x %in% c(1, 3) & z %in% c(12, 20)]
   x  y  z
1: 1 10 20
2: 3  8 20

Now I would like to create the same filter dynamically. This what I have tried so far:

cond <- list(x=c(1,3),z=c(12,20))
vars <- names(cond)
## dd[get(vars[[1]]) %in% cond[[1]] & get(vars[[2]]) %in% cond[[2]]]

EVAL = function(...){
  expr <- parse(text=paste0(...))
  print(expr)
  eval(expr)
  }

dd[ EVAL(vars, " %in% ", cond, collapse=" & ") ] 

But I still get an error:

 Error in match(x, table, nomatch = 0L) : object 'x' not found

even if the expression evalutaed looks good:

expression(x %in% c(1, 3) & z %in% c(12, 20))

Is there a way to fix this?


回答1:


Building expression instead of parsing it.

library(data.table)
dd = data.table(x=1:10,y=10:1,z=20:20)
AndIN = function(cond){
    Reduce(
        function(x, y) call("&", call("(",x), call("(",y)),
        lapply(names(cond), function(var) call("%in%", as.name(var), cond[[var]]))
    )
}
cond = list(x=c(1,3),z=c(12,20))
AndIN(cond)
#(x %in% c(1, 3)) & (z %in% c(12, 20))
dd[eval(AndIN(cond))]
#   x  y  z
#1: 1 10 20
#2: 3  8 20

Calls call("(",x) and call("(",y) may not be necessary.



来源:https://stackoverflow.com/questions/34970312/create-a-filter-expression-i-dynamically-in-data-table

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!