Рассмотрим тиббл, где каждый столбец является символьным вектором, который может принимать много значений - скажем, от «A» до «F».
library(tidyverse)
sample_df <- tibble(q1 = c("A", "B", "C"), q2 = c("B", "B", "A"))
Я хочу создать функцию, которая принимает имя столбца в качестве аргумента и перекодирует этот столбец, так что любой ответ «A» становится NA, а df в противном случае возвращается как есть. Причиной такого проектирования является встраивание в более широкий конвейер, который выполняет ряд операций с использованием данного столбца.
Есть много способов сделать это. Но мне интересно понять, каким будет лучший идиоматический подход tidy_eval / tidyverse. Во-первых, имя вопроса должно быть слева от глагола-мутанта, поэтому мы соответствующим образом используем операторы !!
и :=
. Но тогда, что поставить на правой стороне?
fix_question <- function(df, question) {
df %>% mutate(!!question := recode(... something goes here...))
}
fix_question(sample_df, "q1") # should produce a tibble whose first column is (NA, "B", "C")
Первоначально я думал, что это будет работать:
df %>% mutate(!!question := recode(!!question, "A" = NA_character_))
Но, конечно же, функция bang-bang внутри функции просто возвращает строку буквенных символов (например, «q1»). В итоге я выбрал то, что выглядит как хакерский маршрут для ссылки на данные справа, используя [[
оператор base R и опираясь на .
конструкцию из dplyr, и это работает, поэтому в некотором смысле я решил свою основную проблему:
df %>% mutate(!!question := recode(.[[question]], "A" = NA_character_))
Я заинтересован в том, чтобы узнать мнение людей, которые хорошо разбираются в tidyeval, о том, есть ли более идиоматический способ сделать это, в надежде, что просмотр проработанного примера улучшит мое понимание набора функций tidyeval в более общем плане. Какие-нибудь мысли?
q1
(символом), так и с"q1"
(строкой):df %>% mutate_at( vars(!!ensym(question)), recode, A = NA_character_)
Ответы:
Здесь, с правой стороны
:=
, мы можем указатьsym
преобразовать в символ и затем оценить (!!
)Лучший подход, который будет работать как для цитируемых, так и без кавычек:
ensym
источник
Вы можете использовать метод " curly curly " прямо сейчас, если у вас есть rlang> = 0.4.0 .
Объяснение благодаря @ eipi10:
Это объединяет двухэтапный процесс кавычки, а затем кавычки в один шаг, так
{{question}}
что эквивалентно!!enquo(question)
Обратите внимание, что в отличие от
ensym
подхода, это не работает с именами персонажей. Хуже того, он делает не то, что нужно, вместо того, чтобы просто дать ошибку.источник
question
сначала нужно превратить в quosure (question = enquo(question)
) перед использованием в трубе dplyr.{{question}}
эквивалентно!!enquo(question)
.Вы можете сделать функцию немного более гибкой, позволяя также вводить вектор перекодированных значений в качестве аргумента. Например:
Обратите внимание, что
recode.vec
"без кавычек" с!!!
. Вы можете увидеть, что это делает с этим примером, адаптированным из « Программирование с dplyr vignette» (ищите «сращивание», чтобы увидеть соответствующие примеры). Обратите внимание, как!!!
"склеивает" пары значений перекодировки вrecode
функцию, чтобы они использовались в качестве...
аргумента вrecode
.Если вы хотите запустить функцию записи для нескольких столбцов, вы можете превратить ее в функцию, которая берет только имя столбца и вектор записи. Такой подход кажется более подходящим для труб.
Или перекодировать один столбец:
источник