如何使用字符串连接定义 gather 函数的关键参数
How to define key argument of gather function using string concatenation
我有一个 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
returns 一个字符串。
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)
}
但会导致错误:
Error in !vars : invalid argument type
gather
似乎在必要时引用了 key
和 value
参数,那么有什么方法可以在 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)
}
我有一个 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
returns 一个字符串。
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)
}
但会导致错误:
Error in !vars : invalid argument type
gather
似乎在必要时引用了 key
和 value
参数,那么有什么方法可以在 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)
}