将带引号的列表转换为dplyr :: filter的带引号的表达式列表

时间:2019-06-20 22:58:49

标签: r dplyr non-standard-evaluation quosure

我正在编写一个结合了dplyr::filter步骤(我想对其进行参数化)的函数,然后再执行其他操作。我想为可以覆盖的过滤条件提供一个默认参数。这就排除了通过...传递过滤参数的尝试。尝试如下:

library(rlang)
library(dplyr)
filter_and_stuff1 = function(tbl, filter_args = list(mpg > 33, gear == 4), arg3, arg4){
    as_expr = enexpr(filter_args)
    sub_tbl = filter(tbl, !!!as_expr)
    # do some other things with sub_tbl, arg3 and arg4
    sub_tbl
}

但是

filter_and_stuff1(mtcars)
Error: Argument 2 filter condition does not evaluate to a logical vector

似乎逗号分隔会产生问题。在dplyr的代码内部,通过调用内部函数quo_reduce处理该函数,该内部函数似乎用&将逗号分隔的值拼接在一起。如果不使用...

,我不知道该怎么做

TLDR:如何以编程方式将包含默认表达式的一组参数传递给dplyr :: filter?

2 个答案:

答案 0 :(得分:1)

如果我放弃了必须用逗号分隔filter的多个参数的要求,那么可以这样做:

filter_and_stuff2 = function(tbl, filter_args = mpg > 33 & gear == 4, arg3, arg4){
    filter(tbl, !!enexpr(filter_args))
}

> filter_and_stuff2(mtcars)
   mpg cyl disp hp drat    wt qsec vs am gear carb gear4
1 33.9   4 71.1 65 4.22 1.835 19.9  1  1    4    1  TRUE

答案 1 :(得分:1)

问题在于,enexpr在使用方式上也捕获了对list的呼叫, 而使用省略号已将每个表达式分成列表的不同元素:

library(rlang)

foo <- function(x) {
    enexpr(x)
}

foo(list(a, b, c))
# list(a, b, c)

bar <- function(...) {
    enexprs(...)
}

bar(a, b, c)
# [[1]]
# a
# 
# [[2]]
# b
# 
# [[3]]
# c

要执行所需的操作,可以使用call_args提取给list的内容中的每个表达式:

baz <- function(x) {
    as_expr <- enexpr(x)
    # expr just to show
    expr(filter(!!!call_args(as_expr)))
}

baz(list(a == 1, b < 2))
# filter(a == 1, b < 2)