简体   繁体   English

enquo()函数错误:参数已被求值

[英]enquo() error in function: the argument has already been evaluated

I'm trying to write several embedded functions that end up filtering a set of columns ( id_type in filter_data() ) that is defined by a vector ( id_types in load_data() ). 我试图写结束滤波的一组列的多个嵌入式功能( id_typefilter_data()其由一个矢量定义( id_typesload_data() Based on the new dplyr programming vignette , I'm trying to use enquo to make my code run, but am getting an error that I don't know how to deal with. 基于新的dplyr编程小插图 ,我试图使用enquo来使我的代码运行,但是遇到了一个我不知道如何处理的错误。

The actual code is more complicated (and actually requires the different functions), but this is the simplest code I can use to replicate the error: 实际的代码更加复杂(实际上需要不同的功能),但这是我可以用来复制错误的最简单的代码:

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()

throws the following error: 引发以下错误:

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)

My desired output: I want the code to iterate through all the id_types , filtering df where either id_a == 1 , id_b == 1 , or id_c == 1 (rows 1, 2, and 4 on the original df), and bind those together in a new data frame. 我想要的输出:我希望代码遍历所有id_types ,过滤df ,其中id_a == 1id_b == 1id_c == 1 (原始df上的行1、2和4)并绑定它们一起放在一个新的数据框中。

How can I get this code to work without removing the nested functions? 如何在不删除嵌套函数的情况下使此代码正常工作?

Thank you. 谢谢。

I still don't understand why the original code didn't work, but I did find another solution. 我仍然不明白为什么原始代码不起作用,但是我确实找到了另一个解决方案。

Replace this: 替换为:

quo_id_type <- enquo(id_type)

filter(df, !!quo_id_type == 1)

With this: 有了这个:

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

Quick fix: 快速解决:

If you need the filter_data function, you can switch to this, which is a bit easier and more obvious ( .data refers to your df you pass into filter , and [[ selects the id_type column when id_type is a string): 如果需要filter_data函数,则可以切换filter_data函数,这会更简单,更明显( .data指向传递给filter df ,而[[id_type为字符串时选择id_type列):

filter_data <- function(df, id_type) {
  filter(df, .data[[id_type]] == 1)
}

If you can drop the filter_data function altogether, you can go with: 如果可以完全删除filter_data函数,则可以使用:

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

(Also dropping the bind_rows and pmap calls). (也删除bind_rowspmap调用)。 Note that you'll need to change all_vars to any_vars , since you're evaluating all of the vars in id_types at once. 请注意,由于您要一次评估id_types中的所有var, id_types需要将all_vars更改为any_vars

Why the original won't work: 为什么原版不起作用:

In this example, the argument you pass to filter is a string (ie, "id_a"), but even this by itself won't work: 在此示例中,您传递给filter的参数是一个字符串(即“ id_a”),但即使是这样,它本身也不起作用:

> 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>

The filter condition evaluates to FALSE , since the string "id_a" is not equal to the integer 1 , so no rows satisfy the condition, so it returns an empty tibble . 过滤条件的计算结果为FALSE ,因为字符串"id_a"不等于整数1 ,所以没有行满足条件,因此它返回空的tibble


The argument you pass to the function is really id_types[[1]] , not "id_a", so that's what you're enquo() ing. 您传递给函数的参数实际上是id_types[[1]] ,而不是“ id_a”,所以这就是您enquo() You can see that by trying: 您可以尝试以下方法来查看:

f <- function(id_type) enquo(id_type)  
f(id_types[[1]])  
f("id_a")

Which returns: 哪个返回:

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

You can fix that (and print the other problem) by changing filter_data to this (but I wouldn't recommend actually doing this): 您可以通过将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)
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM