使用dplyr :: filter的tidyeval方式是什么?

时间:2017-09-07 02:01:13

标签: r dplyr tidyeval

使用foo(c("b"))调用下面的函数。输出以内联方式显示。

df %>% filter(!!x > (!!x))的正确方法是什么?

我添加了一个在tidyeval样式中使用mutate的示例,以便将其与filter进行对比。

foo <- function(variables) {

  x <- rlang::sym(variables[[1]])

  print(x)
  #> b

  print(typeof(x))
  #> [1] "symbol"

  df <- data_frame(a = 1, b = 2)

  print(df %>% mutate(!!x := 100 + !!x))

  #> # A tibble: 1 x 2
  #>         a     b
  #>       <dbl> <dbl>
  #>   1     1   102  

  print(df %>% filter(!!x  > (!!x)))

  #> Error in !x : invalid argument type

  print(df %>% filter(magrittr::is_greater_than(!!x, !!x)))

  #> # A tibble: 0 x 2
  #> # ... with 2 variables: a <dbl>, b <dbl>

}

4 个答案:

答案 0 :(得分:3)

除了小错字之外,你大部分都在那里,你的过滤器语句中的圆括号应该是变量而不是值。

print(df %>% filter((!!x) > !!x))

#> # A tibble: 0 x 2
#> # ... with 2 variables: a <dbl>, b <dbl>

答案 1 :(得分:2)

修改:所有这些都不再适用。重组优先树,以便!!x + !!y等默认执行正确的操作。因为rlang 0.2.0,所以不再需要括号。

!运算符的优先级非常低。这意味着它将适用于右侧出现的大部分表达。

!! x > 3

隐含地等同于:

(!! x > 3)

所以你必须帮助R用明确的括号找出正确的优先级:

(!! x) > 3

请注意,在大多数情况下,如果您在操作员的两边都没有引用,则从技术上讲,您不必在最后一个上应用括号:

(!! x) + (!! y) + z

然而,根据通常神秘的优先规则,这会有所不同,因此我建议在涉及运营商时将其括在括号中:

(!! x ) + (!! y) + (!! z)

答案 2 :(得分:0)

您可以使用filter_at

oof <- function(variables) {
  x <- rlang::sym(variables[[1]])
  df <- data.frame(a = 1, b = 2)
  print(df %>% filter_at(vars(!!x), any_vars(. == !!x)))
  print(df %>% filter(magrittr::equals(!!x, !!x)))
}

我使用magrittr::equals来显示magrittr样式的作品

oof(c("b"))

#   a b
# 1 1 2
#   a b
# 1 1 2

答案 3 :(得分:0)

This is a very generic way of handling any field value condition

data%>%
    filter(!!quo((!!as.name (field1)) > (!!myVal)))