Как определить ключевой аргумент функции сбора с использованием конкатенации строк - PullRequest
0 голосов
/ 11 сентября 2018

У меня есть tibble с взаимодействием нескольких факторов в качестве имен столбцов (см. Пример с двумя факторами ниже).

ex <- structure(list(`Monday*FALSE` = 42.74, `Monday*TRUE` = 70.68, 
`Tuesday*TRUE` = 44.05, `Tuesday*FALSE` = 51.25, `Wednesday*TRUE` = 35.57, 
`Wednesday*FALSE` = 59.24, `Thursday*TRUE` = 85.3, `Thursday*FALSE` = 59.91, 
`Friday*TRUE` = 47.27, `Friday*FALSE` = 47.44, `Saturday*TRUE` = 62.28, 
`Saturday*FALSE` = 98.8, `Sunday*TRUE` = 57.11, `Sunday*FALSE` = 65.99), class = c("tbl_df", 
"tbl", "data.frame"), row.names = c(NA, -1L))

Я хочу написать функцию, которая позволила бы gather это tibble, но дополнительно создала бы имя key на основе входных имен факторов. Однако следующее не работает так, как задумано, поскольку paste0 возвращает строку.

my_gather <- function(data, ...){
  vars <- enquos(...)
  data %>% 
    gather(key = paste0(!!!vars, sep = '*'), value = value, factor_key = TRUE)
}

my_gather(ex, day, cond) %>% head()
# A tibble: 6 x 2
  `paste0(day, cond, sep = ".")` value
  <fct>                          <dbl>
1 Monday*FALSE                    42.7
2 Monday*TRUE                     70.7
3 Tuesday*TRUE                    44.0
4 Tuesday*FALSE                   51.2
5 Wednesday*TRUE                  35.6
6 Wednesday*FALSE                 59.2

Я попытался заменить * на ., чтобы создать правильное синктическое имя, а затем записать paste0 в sym с !!:

my_gather <- function(data, ...){
   vars <- enquos(...)
   data %>% 
     gather(key = !!sym(paste0(!!!vars, sep = '.')), value = value, factor_key = TRUE)
}

но это приводит к ошибке:

Ошибка в! Vars: неверный тип аргумента

gather, кажется, цитирует аргументы key и value в случае необходимости, поэтому есть ли способ оценить paste0(...) в пределах key определения?

1 Ответ

0 голосов
/ 11 сентября 2018

Это не работает, потому что вы двойные кавычки:

!!sym(paste0(!!!vars, sep = '.'))

Все внутри !! оценивается нормально, поэтому, если вы используете другой оператор кавычек, это должно быть обработано другой функцией квазицитирования. paste0() не поддерживает !!!.

Как правило, лучше выполнять действия в несколько этапов со сложным синтаксисом, таким как !!. Это более читабельно и меньше шансов на ошибку.

Во-вторых, вы цитируете вводы с помощью enquos(). Это означает, что они могут быть любыми сложными выражениями вместо имен столбцов. Если вы ожидаете пустые столбцы, лучше вместо этого использовать ensyms(...) (или просто syms(c(...)), если вы предпочитаете брать строки без кавычек).

my_gather <- function(data, ...){
  # ensyms() guarantees there can't be complex expressions in `...`
  vars <- ensyms(...)

  # Let's convert all symbols to strings and return a character vector
  keys <- purrr::map_chr(vars, as.character)

  # Now we can use paste() the normal way. It doesn't support `!!!`
  # but the standard way of dealing with vector inputs is the
  # `collapse` argument:
  key <- paste0(keys, collapse = '*')

  # Equivalently, but weird:
  key <- eval(expr(paste(!!!keys, sep = "*")))

  # Now the key can be unquoted:
  data %>%
    gather(key = !!key, value = value, factor_key = TRUE)
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...