Понимание того, когда использовать ensym, sym vs enquo в функции

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

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


person Jmac    schedule 27.01.2020    source источник
comment
пробовали ли вы обозначение {{}} - например, ошибка stackoverflow.com/questions/56926211/   -  person Richard Telford    schedule 27.01.2020
comment
@RichardTelford Я думаю (?) {{}} Заменяет !! enquo (), чтобы он работал в каналах dplyr, если аргумент был введен как пустой (без кавычек). Не уверен, как это будет работать для функций, которые не используют NSE.   -  person Jmac    schedule 31.01.2020


Ответы (1)


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

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

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

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

median(dat[[rlang::as_string(ensym(xvar))]])
person Artem Sokolov    schedule 30.01.2020