Программирование задач с помощью dplyr - столбца, который определенно является вектором, взятым в виде формулы

Я пишу функцию для воспроизведения нескольких диаграмм, которые будут иметь одинаковое форматирование (и другие вещи) с использованием highcharter. Я хочу иметь возможность выбирать разные столбцы набора данных, если имена меняются или если я хочу сделать что-то другое, и я принимаю эти аргументы с помощью {{ }}. Но затем я получаю эту странную ошибку:

Error: Problem with `mutate()` input `x`.
x Input `x` must be a vector, not a `formula` object.
i Input `x` is `~Year`.

Вот мой (минимально воспроизводимый) код:

library(dplyr)
library(highcharter)

plot_high_chart <- function(.data,
                            chart_type = "column",
                            x_value = Year,
                            y_value = total,
                            group_value = service) {
  .data %>% 
  hchart(chart_type, hcaes(x = {{x_value}}, y = {{y_value}}, group = {{group_value}}))
}

data %>% plot_high_chart()

и вот результат dput для данных:

structure(list(Year = c(2016, 2017, 2017, 2018, 2018, 2018), 
    service = structure(c(10L, 3L, 9L, 5L, 7L, 9L), .Label = c("Defense Logistics Agency", 
    "Chemical and Biological Defense Program", "Defense Information Systems Agency", 
    "United States Special Operations Command", "Office of the Secretary Of Defense", 
    "Missile Defense Agency", "Defense Advanced Research Projects Agency", 
    "Navy", "Army", "Air Force"), class = "factor"), total = c(9.435, 
    0, 10.442, 9.969, 73.759, 8.855)), row.names = c(NA, -6L), groups = structure(list(
    Year = c(2016, 2017, 2018), .rows = structure(list(1L, 2:3, 
        4:6), ptype = integer(0), class = c("vctrs_list_of", 
    "vctrs_vctr", "list"))), row.names = c(NA, 3L), class = c("tbl_df", 
"tbl", "data.frame"), .drop = TRUE), class = c("grouped_df", 
"tbl_df", "tbl", "data.frame"))

person Ben G    schedule 16.10.2020    source источник


Ответы (1)


{{a}} - это сокращение для !!enquo(a), которое фиксирует выражение, предоставленное для a, а также контекст, в котором это выражение должно быть вычислено. В вашем случае контекст - это фрейм данных, который уже предоставляется функции. Итак, лучший rlang глагол для использования здесь - ensym(a), который вместо этого захватывает имя символа, предоставленное a:

plot_high_chart <- function(.data,
                            chart_type = "column",
                            x_value = "Year",             # <-- Note: strings
                            y_value = "total",            
                            group_value = "service") {
  .data %>%
      hchart(chart_type, hcaes(x = !!rlang::ensym(x_value),    # <- ensym instead of {{
                               y = !!rlang::ensym(y_value),
                               group = !!rlang::ensym(group_value)))
}

В качестве бонуса функция теперь будет работать с символами И со строками:

data %>%
   plot_high_chart(x_value= "Year", y_value= "total", group_value= "service")    # Works
data %>% 
   plot_high_chart(x_value= Year, y_value= total, group_value= service)     # Also Works
person Artem Sokolov    schedule 16.10.2020
comment
Отлично, спасибо. Как вы можете видеть здесь (stackoverflow.com/questions/57960245/) В прошлом меня сбивали с толку различия enquo / ensym. До сих пор не совсем понимаю, почему enquo здесь не работает. - person Ben G; 16.10.2020
comment
@BenG Отчасти это зависит от того, как hcaes обрабатывает свои аргументы. quo() и enquo() возвращают объекты, которые можно интерпретировать как формулы (например, попробуйте class(rlang::quo(x)) убедить себя). Возможно, hcaes зацикливается на классе formula? - person Artem Sokolov; 16.10.2020
comment
НО ... почему это следует интерпретировать как формулу? - person Ben G; 16.10.2020
comment
@BenG: Потому что здесь отображение, созданное hcaes, преобразуется в символ. Попробуйте сделать as.character(hcaes( !!quo(x), !!quo(y) )), а затем as.character(hcaes( !!sym("x"), !!sym("y") )), чтобы увидеть разницу. Я думаю, что quosures внутренне хранят выражения в виде формул, поэтому преобразование их к символу приводит к ~x вместо x. - person Artem Sokolov; 17.10.2020
comment
В этом есть смысл. Спасибо - person Ben G; 18.10.2020
comment
Я считаю, что {{ в идеале должен работать. Возможно, стоит отправить отчет об ошибке с помощью hchart? - person Lionel Henry; 19.10.2020
comment
@LionelHenry github.com/jbkunst/highcharter/issues/681 - person Artem Sokolov; 19.10.2020
comment
@ArtemSokolov Большое спасибо за это. Охват работает с highchartr data_to_boxplot, поэтому я подумал, что было бы разумно работать и с hcaes. Кажется, что спустя полгода hchart все еще не обратился к этому вопросу. - person bcarothers; 29.04.2021