这个问题是 6 年前发布的。 dplyr 现在升级到 1.0.2 版。然而,这仍然是一个很好的讨论,并极大地帮助了我解决我的问题。我希望能够从所有由内存中的变量指定的列、运算符和值构造过滤器。哦,还有不定数量的过滤器!
考虑以下列表,我在其中指定列、运算符和两个过滤器的值:
myFilters =
list(
list(var = "color", op = "%in%", val = "blue"),
list(var = "value", op = "<=", val = 3)
)
从这个列表中,我想运行:
dplyr::filter(color %in% "blue", value <= 3)
我们可以在上面的list 上使用lapply 来创建call 对象的list,使用!!! 运算符强制评估调用,并将其传递给filter:
library(dplyr)
df <- data.frame(
color = c("blue", "black", "blue", "blue", "black"),
value = 1:5)
result =
lapply(myFilters, function(x) call(x$op, as.name(x$var), x$val)) %>%
{filter(df, !!!.)}
...还有沙赞!
> result
color value
1 blue 1
2 blue 3
要吸收的内容很多,所以如果不能立即看出发生了什么,让我稍微解开一下。考虑:
var = "color"
op = "%in%"
val = "blue"
我希望能够跑步:
filter(df, color %in% "blue")
如果我也有:
var2 = "value"
op2 = "<="
val2 = 3
我可能希望能够得到:
filter(df, color %in% "blue", value <= 3)
解决方案使用calls,它们是未计算的表达式。 (参见 Hadley 的 Advanced R book)基本上,从变量中列出 call 对象,然后在调用 dplyr::filter 时使用 !!! 运算符强制评估调用。
call1 = call(op, as.name(var), val)
这是call1的值:
> call1
color %in% "blue"
让我们创建另一个call:
call2 = call(op2, as.name(var2), val2)
将它们放在列表中:
calls = list(call1, call2)
并使用!!! 评估调用列表,然后再将它们发送到filter:
result = filter(df, !!!calls)