Есть ли пределы для аккуратной оценки? - PullRequest
0 голосов
/ 11 мая 2018

Я пытаюсь использовать аккуратную оценку, как определено в dplyr 0.7.0.

Однако во время вызова функции в mutate() я получаю ошибку.Кажется, что переменные оцениваются не так, как я ожидаю.

library(dplyr)
library(tibble)
library(tidyr)

myCor <- function(col1, col2) {
  col1 <- enquo(col1)
  col2 <- enquo(col2)

  mtcars %>%
    rownames_to_column("vehicle") %>%
    select(vehicle, !!col1, !!col2) %>%
    mutate(correlation=cor(!!col1, !!col2))
}

myCor("mpg", "disp")
# Error in mutate_impl(.data, dots) : 
#   Evaluation error: 'x' must be numeric.

Вместо этого я должен использовать этот синтаксис non-tidy eval, чтобы получить желаемый результат.

myCor <- function(col1, col2) {
  col1_tidy <- enquo(col1)
  col2_tidy <- enquo(col2)

  mtcars %>%
    rownames_to_column("vehicle") %>%
    select(vehicle, !!col1_tidy, !!col2_tidy) %>%
    mutate(correlation=cor(eval(parse(text=col1)), eval(parse(text=col2))))
}

myCor("mpg", "disp")
# vehicle  mpg  disp correlation
# 1            Mazda RX4 21.0 160.0  -0.8475514
# 2        Mazda RX4 Wag 21.0 160.0  -0.8475514
# 3           Datsun 710 22.8 108.0  -0.8475514
# 4       Hornet 4 Drive 21.4 258.0  -0.8475514
# ...

Isесть ли способ использовать аккуратную оценку в этом примере?

Ответы [ 2 ]

0 голосов
/ 12 мая 2018

Используйте ensym вместо enquo, если вы хотите передать строки в качестве аргументов ...

library(dplyr)
library(rlang)
library(tibble)

myCor <- function(col1, col2) {
  col1 <- ensym(col1)
  col2 <- ensym(col2)

  mtcars %>%
    rownames_to_column("vehicle") %>%
    select(vehicle, !!col1, !!col2) %>%
    mutate(correlation=cor(!!col1, !!col2))
}

# both of these will work now
myCor("mpg", "disp")
myCor(mpg, disp)
0 голосов
/ 12 мая 2018

Из виньетки Программирование с помощью dplyr :

Большинство аргументов dplyr не являются ссылочно прозрачными. Это означает, что вы не можете заменить значение, казалось бы, эквивалентным объектом, который вы определили в другом месте.

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

Чтобы превратить обычный mutate -звук в функцию с нестандартной оценкой, было бы более интуитивно понятно, как это начинать.
Сначала запишите вызов, как без функции:

mtcars %>%
    rownames_to_column("vehicle") %>%
    select(vehicle, mpg, disp) %>%
    mutate(correlation = cor(mpg, disp))

Это работает (и вызовет ошибку с кавычками mpg и disp!).
Теперь потяните переменные, которые вы хотите изменить перед вызовом и подставьте их:

col1 <- quo(mpg)
col2 <- quo(disp)

mtcars %>%
  rownames_to_column("vehicle") %>%
  select(vehicle, !!col1, !!col2) %>%
  mutate(correlation=cor(!!col1, !!col2))

Поскольку это за пределами функции, мы должны использовать quo здесь, но на последнем шаге, когда мы заключаем ее в функцию, мы используем enquo.

myCor <- function(var1, var2) {
  col1 <- enquo(var1)
  col2 <- enquo(var2)

  mtcars %>%
    rownames_to_column("vehicle") %>%
    select(vehicle, !!col1, !!col2) %>%
    mutate(correlation=cor(!!col1, !!col2))
}

Я использовал разные имена для аргументов функции, а затем объект «заключенный в кавычки» (с enquo), чтобы сделать различие более четким, но, конечно, оно работает и с col1 и col2.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...