7

本文解释了整洁评估的新 curly curl 方法。给出了几个例子来展示这种非标准评估(NSE)风格的使用。

library(tidyverse)

# Example 1 --------------------------
max_by <- function(data, var, by) {
  data %>%
    group_by({{ by }}) %>%
    summarise(maximum = max({{ var }}, na.rm = TRUE))
}
starwars %>% max_by(height)
starwars %>% max_by(height, by = gender)

# Example 2 --------------------------
summarise_by <- function(data, ..., by) {
  data %>%
    group_by({{ by }}) %>%
    summarise(...)
}

starwars %>%
  summarise_by(average = mean(height, na.rm = TRUE),
               maximum = max(height, na.rm = TRUE),
               by = gender)

我创建了一些自己的函数,这确实是一个更容易开发的框架,而不是担心所有的 quosures 和 bangs 以及所有这些。

然而,同一篇文章解释说我们还没有完全走出困境:

当您需要以某种方式修改输入或其名称时,您只需要引用和取消引用(使用复数变体 enquos() 和 !!!)。

...并且没有提供示例。不抱怨,只是询问是否有人可以填补空白并提供示例。不熟悉 Tidy 评估,我真的不明白作者对这句话的看法(请原谅双关语)

4

1 回答 1

6

假设您想要以下函数的一个版本,该版本需要多个输入,而不仅仅是一个var

mean_by <- function(data, var, by) {
  data %>%
    group_by({{ by }}) %>%
    summarise(average = mean({{ var }}, na.rm = TRUE))
}

您不能只传递...摘要,因为那样用户需要调用mean()自己。

mean_by <- function(data, var, ..., by) {
  data %>%
    group_by({{ by }}) %>%
    summarise(...)
}

mtcars %>% mean_by(foo = disp)
#> Error: Column `foo` must be length 1 (a summary value), not 32

mtcars %>% mean_by(foo = mean(disp))
#> # A tibble: 1 x 1
#>     foo
#>   <dbl>
#> 1  231.

解决方案是引用这些点,修改每个输入,以便将它们包装在对 的新调用中mean(),然后将它们拼接回去:

mean_by <- function(data, ..., by) {
  # `.named` makes sure the dots have default names, if not supplied
  dots <- enquos(..., .named = TRUE)

  # Go over all inputs, and wrap them in a call
  dots <- lapply(dots, function(dot) call("mean", dot, na.rm = TRUE))

  # Finally, splice the expressions back into `summarise()`:
  data %>%
    group_by({{ by }}) %>%
    summarise(!!!dots)
}

我们正在考虑如何改进这种情况的语法。http://rpubs.com/lionel-/superstache的早期想法

于 2019-07-09T07:43:42.770 回答