功能中的enquo()错误:已经评估了参数

时间:2017-10-04 17:50:44

标签: r dplyr purrr

我正在尝试编写几个嵌入式函数,这些函数最终会过滤id_type中的一列(filter_data()),该列由id_types中的load_data()定义})。基于新的dplyr programming vignette,我正在尝试使用enquo来运行我的代码,但我收到的错误是我不知道如何处理。

实际代码更复杂(实际上需要不同的函数),但这是我可以用来复制错误的最简单的代码:

library(dplyr)
library(purrr)

data <- tibble(id_a = c(1,1,2,2,3),
             id_b = 991,
             id_c = c(45,45,45,1,80),
             units_sold = c(21,20,24,4,5))
id_types <- c("id_a", "id_b", "id_c")

load_data <- function(){

  bind_rows(pmap(list(list(data),
                  id_types),
             filter_data))
}

filter_data <- function(df, id_type) {
  quo_id_type <- enquo(id_type)

  filter(df, !!quo_id_type == 1)
}

load_data()

引发以下错误:

Error in (function (x, strict = TRUE)  : 
  the argument has already been evaluated
Called from: (function (x, strict = TRUE) 
    {
    caller_env <- parent.frame()
    if (identical(caller_env, globalenv())) {
        stop("must be called in a function")
    }
    if (missing(x)) {
        stop("argument \"x\" is missing")
    }
    .Call(rlang_capturearg, NULL, NULL, pairlist(caller_env, 
        strict), get_env())
})(id_type)

我想要的输出:我希望代码遍历所有id_types,过滤df id_a == 1id_b == 1id_c == 1(行)原始df上的1,2和4,并将它们绑定在一个新的数据框中。

如何在不删除嵌套函数的情况下使此代码正常工作?

谢谢。

2 个答案:

答案 0 :(得分:0)

我仍然不明白为什么原始代码不起作用,但我确实找到了另一种解决方案。

替换它:

quo_id_type <- enquo(id_type)

filter(df, !!quo_id_type == 1)

有了这个:

filter_at(df, vars(id_type), all_vars(. == 1))

答案 1 :(得分:0)

快速修复:

如果您需要.data功能,可以切换到此功能,这样更容易也更明显(df是指您filter传入[[ id_type ,当id_type是字符串时,filter_data <- function(df, id_type) { filter(df, .data[[id_type]] == 1) } 选择filter_data列:

filter_at(data, vars(id_types), any_vars(. == 1))

如果您完全放弃bind_rows功能,可以使用:

pmap

(同时放弃all_varsany_vars来电。请注意,您需要将id_types更改为filter,因为您正在同时评估> filter(data, "id_a" == 1) # A tibble: 0 x 4 # ... with 4 variables: id_a <dbl>, id_b <dbl>, id_c <dbl>, # units_sold <dbl> 中的所有变量。

为什么原作不起作用:

在此示例中,您传递给FALSE的参数是一个字符串(即&#34; id_a&#34;),但即使这样也不会起作用:

"id_a"

过滤条件的计算结果为1,因为字符串tibble不等于整数id_types[[1]],因此没有行满足条件,因此返回空{{1} }。

您传递给该函数的参数实际上是enquo(),而不是&#34; id_a&#34;,因此您需要f <- function(id_type) enquo(id_type) f(id_types[[1]]) f("id_a") 。您可以通过尝试来看到:

<quosure: global>
~id_types[[1]]
<quosure: empty>
~"id_a"

返回:

filter_data

您可以通过将filter_data <- function(df, id_type) { id_type <- id_type quo_id_type <- enquo(id_type) print(quo(filter(df, !!quo_id_type == 1))) filter(df, !!quo_id_type == 1) } 更改为此来修复此问题(并打印其他问题)(但我不建议实际执行此操作):

textField.isUserInteractionEnabled = false