Понимание, когда использовать ensym, sym vs enquo в функции - PullRequest
2 голосов
/ 27 января 2020

Я пытаюсь обернуть голову вокруг различных синтаксисов quo / unquo, и когда каждый из них должен использоваться.

В основном я пишу функции, которые передают фрейм данных и столбцы для использования в качестве аргумента - для построения графика. используя ggplot или суммируйте / манипулируйте данными с помощью dplyr (group_by, Summaze, Mutate ect) Однако иногда мне приходится использовать функцию, которая не использует NSE в моей общей функции.

Из того, что я прочитал, я понимаю, что:

1) если я ссылаюсь на столбец в кадре данных, тогда мне не нужно захватывать среду, и я могу использовать ensym или sym. Это правильно? Будет ли проблема с использованием enquo, или это просто не нужно?

2) если я использую ensym, чтобы пользователь мог технически ввести в аргументе как строку, так и имя голого столбца ,

Исходя из этого, моя типичная установка функции будет выглядеть примерно так:

library(tidyverse)

dataset <- mtcars

myfun <- function(dat, xvar, yvar, group){

  #either manipulate data
  x <- dat %>% group_by(!!ensym(group)) %>%
    mutate(new = !!ensym(xvar)*5) %>%
    summarize(medianx=median(!!ensym(xvar), na.rm=TRUE), 
              median_new=median(new, na.rm=TRUE))


  #or plot data
  p <- ggplot(dat, aes(x=!!ensym(xvar), y=!!ensym(yvar))) + 
    geom_point()

  #sometime require referencing the column with NSE function..
  median(dat[[xvar]])  #works if require string in argument

  #how would you reference this with bare argument column? Convert ensym to string?
  median(dat[[?????]])
}

#both work with ensym, only the later with sym
myfun(dataset, xvar=mpg, yvar=disp, group=cyl)
myfun(dataset, xvar="mpg", yvar="disp", group="cyl")

Как преобразовать пустой аргумент столбца или символ в строку для использования в последней строке из myfun выше? Я пытался rlang::as_string(!!ensym(xvar)), но это не работает.

1 Ответ

0 голосов
/ 30 января 2020

Ваше понимание верно. sym / ensym предпочтительнее при ссылке на столбец в существующем фрейме данных. enquo(), конечно, также будет работать, но оно захватывает любое произвольное выражение, позволяя пользователю указывать такие вещи, как mpg * cyl или log10(mpg + cyl)/2. Если ваш нисходящий код предполагает, что xvar и yvar являются одиночными столбцами, произвольные выражения могут привести к проблемам или неожиданному поведению. В этом смысле ensym() выполняет шаг проверки аргумента, когда вы ожидаете ссылку на один столбец.

Что касается преобразования символов в строки, один из подходов заключается в использовании deparse():

median(dat[[deparse(ensym(xvar))]])

Чтобы заставить rlang::as_string работать, вам нужно удалить !!, потому что вы хотите преобразовать само выражение в строку, а не в то, на что ссылается выражение (например, mpg, cyl, et c.):

median(dat[[rlang::as_string(ensym(xvar))]])
...