基本上你的问题是
enquos()
在单个参数上,您还引用
list()
呼叫(即单个呼叫)。所以基本上你是在创造
filter_args_enquos <- quo(list(Sepal.Length > 5, Petal.Length > 5))
当你打电话的时候
dplyr::filter(iris, !!!filter_args_enquos)
dplyr::filter(iris, list(Sepal.Length > 5, Petal.Length > 5))
这不是有效的dplyr语法。这个
!!!
需要处理一个适当的列表,比如对象,而不是对列表的未评估调用,请注意,这样做是可行的
filter_args_enquos <- list(quo(Sepal.Length > 5), quo(Petal.Length > 5))
dplyr::filter(iris, !!!filter_args_enquos)
因为这里我们实际上是在评估清单,只引用清单中的内容。这基本上是enquos在使用时创建的对象类型。。。
filter_wrap <- function(x, ...) {
filter_args_enquos <- rlang::enquos(...)
dplyr::filter(x, !!!filter_args_enquos)
}
filter_wrap(iris, Sepal.Length > 5, Petal.Length > 5)
函数需要多个参数,而不仅仅是一个列表。这就是为什么它要和
...
因为这会扩展到多个参数。如果您想传入一个列表,可以编写一个helper函数来查找这个特例并正确地扩展quosure。例如
expand_list_quos <- function(x) {
expr <- rlang::quo_get_expr(x)
if (expr[[1]]==as.name("list")) {
expr[[1]] <- as.name("quos")
return(rlang::eval_tidy(expr, env = rlang::quo_get_env(x)))
} else {
return(x)
}
}
然后你就可以用它了
filter_wrap <- function(x, filter_args) {
filter_args <- expand_list_quos(rlang::enquo(filter_args))
dplyr::filter(x, !!!filter_args)
}
这两个都可以
filter_wrap(iris, Petal.Length > 5)
filter_wrap(iris, list(Sepal.Length > 5, Petal.Length > 5))
但事实并非如此
enquo
东西是“注定”要用的。这个
方法更惯用。或者打电话
quos()
如果你需要更多的控制
filter_wrap <- function(x, filter_args) {
dplyr::filter(x, !!!filter_args)
}
filter_wrap(iris, quo(Petal.Length > 5))
filter_wrap(iris, quos(Sepal.Length > 5, Petal.Length > 5))