r语言 - 如何使用字符串连接定义收集函数的键参数



我有一个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))

我想编写一个函数,允许gathertibble,但另外根据因子的输入名称创建一个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似乎在必要时对keyvalue参数进行配额,那么有没有办法在key定义范围内评估paste0(...)

这不起作用,因为您正在双重取消引用:

!!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)
}

最新更新