这个问题是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)
我们可以lapply
在上面使用来list
创建对象,使用运算符强制评估调用,并将其传递给:list
call
!!!
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)
该解决方案使用call
s,它们是未计算的表达式。(请参阅 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)