Я потратил часы, пытаясь заставить клей на правой стороне формулы работать и из подсказок. Вот простой репрекс.
meta <- function(x, var, suffix){
x<- x %>% mutate("{{var}}_{suffix}":= 5)
x<- x %>% mutate("{{var}}_{suffix}_new":= {{var}} - "{{var}}_{suffix}")
}
x<- meta(mtcars, mpg, suf)
#Should be equivalent to
x<- mtcars %>% mutate(mpg_suf:= 5)
x<- x%>% mutate(mpg_suf_new:= mpg - mpg_suf)
#N: Tried https://stackoverflow.com/questions/70427403/how-to-correctly-glue-together-prefix-suffix-in-a-function-call-rhs but none of the methods in it worked, unfortunately
Мета-функция дает мне «Ошибка в local_error_context (точки = точки, .index = i, маска = маска): обещание уже находится на стадии оценки: рекурсивная ссылка на аргумент по умолчанию или более ранние проблемы? "
Просмотрел все хиты для поисковых слов для него на SO, но на данный момент ничего не сработало.
Был бы очень признателен за любые идеи. Спасибо!
Я думаю, будет лучше, если мы сначала определим части, которые нам нужны, а затем мы сможем использовать их по мере необходимости в расчете слева или справа. Я добавлю, что для меня нет особого смысла передавать аргумент suffix
как голое имя. Я думаю, что было бы более ясным выбором сделать это только строкой.
library(dplyr)
meta <- function(x, var, suffix) {
var <- rlang::as_name(enquo(var))
suffix <- rlang::as_name(enquo(suffix)) # Remove this to make "suffix" string only.
new_var <- glue::glue("{var}_{suffix}")
x %>%
mutate("{new_var}" := 5,
"{new_var}_new" := !!sym(var) - !!sym(new_var))
}
mtcars %>%
head() %>%
meta(mpg, suf)
mpg cyl disp hp drat wt qsec vs am gear carb mpg_suf mpg_suf_new
Mazda RX4 21.0 6 160 110 3.90 2.620 16.46 0 1 4 4 5 16.0
Mazda RX4 Wag 21.0 6 160 110 3.90 2.875 17.02 0 1 4 4 5 16.0
Datsun 710 22.8 4 108 93 3.85 2.320 18.61 1 1 4 1 5 17.8
Hornet 4 Drive 21.4 6 258 110 3.08 3.215 19.44 1 0 3 1 5 16.4
Hornet Sportabout 18.7 8 360 175 3.15 3.440 17.02 0 0 3 2 5 13.7
Valiant 18.1 6 225 105 2.76 3.460 20.22 1 0 3 1 5 13.1
Большое спасибо! Я буду исследовать этот подход дальше.
Вот рабочая версия:
meta <- function(x, var, suffix){
new_name <- rlang::englue("{{ var }}_{{ suffix }}")
x %>%
mutate("{new_name}" := 5) %>%
mutate("{new_name}_new" := {{ var }} - .data[[new_name]])
}
names(meta(mtcars, mpg, suf))
#> [1] "mpg" "cyl" "disp" "hp"
#> [5] "drat" "wt" "qsec" "vs"
#> [9] "am" "gear" "carb" "mpg_suf"
#> [13] "mpg_suf_new"
Чтобы понять, что происходит:
Узнайте о разнице между "{{ var }}"
и "{var}"
в клеевых строках tidyval: https://rlang.r-lib.org/reference/glue-operators.html
Узнайте о том, как englue()
создавать связующие строки за пределами LHS :=
: https://rlang.r-lib.org/reference/englue.html. Эта часть необязательна, но я подумал, что лучше создать и повторно использовать переменную.
Сложная часть: вы создаете новый столбец с построенным именем, а затем хотите использовать новый столбец, на который ссылается это имя. Вам придется подмножить его с помощью .data
, см.: https://rlang.r-lib.org/reference/dot-data.html
Смотрите также общую тему: https://rlang.r-lib.org/reference/topic-data-mask-programming.html
Спасибо, Лайонел! Это очень полезно. Я также ценю вашу работу в сообществе. Просмотрел много ваших постов.
Эта версия тоже хороша, но требует более продвинутых инструментов. Я полностью согласен с советом брать простые строки в качестве аргумента
suffix
.