кудрявый кудрявый Tidy оценки и изменения входных данных или их имена - PullRequest
3 голосов
/ 08 июля 2019

В этой статье описывается новый метод фигурных фигурных вычислений . Приведено несколько примеров, демонстрирующих использование этого стиля нестандартной оценки (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)

Я создал некоторые из своих собственных функций, и это действительно намного проще для разработки, вместо того, чтобы беспокоиться о всех предложениях, ударах и всем этом.

Однако, эта же статья объясняет, что мы еще не совсем вне леса:

Вам нужны только кавычки и кавычки (с множественными вариантами enquos () и !!!) когда вам нужно каким-либо образом изменить входные данные или их имена.

... и пример не приводится. Не жалуюсь, просто спрашиваю, может ли кто-нибудь заполнить пробел и привести пример. Не очень хорошо разбираясь в оценке Tidy, я действительно не понимаю, к чему автор обращается с этой цитатой (простите за каламбур) .

1 Ответ

4 голосов
/ 09 июля 2019

Допустим, вам нужна версия следующей функции, которая принимает несколько входов вместо одного 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

...