Можно ли использовать ensyms для вектора символов?

В следующем примере, почему я получаю ошибку или неожиданные результаты от использования ensyms для принятия аргумента вектора символов? Я понимаю, что этот конкретный пример глупый: facet_grid() может фактически принимать вектор символов в качестве аргумента. Однако я хочу понять, как уверенно использовать sym, ensym, syms и ensyms в более общем смысле.

Я написал небольшой фрагмент кода, который гранит график, созданный в ggplot, с помощью вектора символов.

library(rlang)
library(ggplot2)
n <- 100
x1 <- rnorm(n)
x2 <- rnorm(n)
c1 <- rbinom(n, 1, .5)
c2 <- rbinom(n, 1, .5)

df_ex <- data.frame(x1=x1, x2=x2, c1=c1, c2=c2)
    plot_test <- function(dat, facet_vars){
    facet_vars <- ensyms(facet_vars)
    p <- ggplot(dat, aes(x1,x2)) + facet_grid(vars(!!!facet_vars))
}
facet_vars <- c("c1", "c2")
#throws error
p <- plot_test(df_ex, c("c1", "c2"))
#seems to look for variable `facet_var`
p <- plot_test(df_ex, facet_vars)

Если вектор символов напрямую вводится в функцию, я получаю сообщение об ошибке «Ошибка: в качестве аргумента должны быть указаны символы или строки». Если я ввожу facet_vars, ensyms буквально возвращает «facet_vars», и огранка не выполняется. Есть ли способ использовать ensyms без использования аргументов из многоточия, с которым я больше всего знаком?


person Daniel Conn    schedule 01.02.2019    source источник


Ответы (1)


Вы используете ensym, если хотите передать символ или строку в свою функцию через нестандартную оценку. Это не то, что вы делаете с c("c1", "c2"). Это не векторный литерал в R. Здесь вы вызываете функцию c() с двумя параметрами, чтобы вернуть вектор. Это не простая строка; это вызов функции. Вместо этого, если вы хотите превратить вектор строк в символы, просто используйте syms(). Это будет работать:

plot_test <- function(dat, facet_vars){
  facet_vars <- syms(facet_vars)
  p <- ggplot(dat, aes(x1,x2)) + facet_grid(vars(!!!facet_vars))
}
facet_vars <- c("c1", "c2")
plot_test(df_ex, c("c1", "c2"))
plot_test(df_ex, facet_vars)

или, альтернативно, зафиксируйте его как выражение

plot_test <- function(dat, facet_vars){
  facet_vars <- enexprs(facet_vars)
  p <- ggplot(dat, aes(x1,x2)) + facet_grid(vars(!!!facet_vars))
}

ensyms() работает лучше, если вы передаете строки как отдельные параметры

plot_test <- function(dat, ...){
  facet_vars <- ensyms(...)
  p <- ggplot(dat, aes(x1,x2)) + facet_grid(vars(!!!facet_vars))
}
plot_test(df_ex, "c1", "c2")
person MrFlick    schedule 01.02.2019
comment
Ваш первый комментарий о правильном использовании ensym полезен, но его захват с помощью syms или enexprs не работает, когда я пытаюсь это сделать. Использование syms избавляет от ошибки, но создает фасеты без точек в них. То же самое касается enexprs. Графики у вас правильно отображались? - person Daniel Conn; 02.02.2019
comment
В вашем коде вообще нет geom_point(), поэтому нечего рисовать точки. Я просто сосредоточился на огранки. - person MrFlick; 02.02.2019
comment
О, конечно, я случайно удалил его при переносе своего кода на SO. Благодарю вас. - person Daniel Conn; 02.02.2019