如何使用字符串串联定义gather函数的关键参数

时间:2018-09-11 11:15:27

标签: r dplyr tidyeval

我有一个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似乎在必要时对keyvalue参数进行了配额分配,那么是否有任何方法可以在paste0(...)定义内评估key

1 个答案:

答案 0 :(得分:9)

这行不通,因为您双引号不对:

["/path/to/index.php", "your" "command arguments" "here"]

$cmdline = file_get_contents('/proc/self/cmdline'); $argv = str_getcsv($cmdline, "\0"); while (true) { $arg = array_shift($argv); if ($arg === null || $arg === '--') { // Stick whatever on the start to align with normal $argv array_unshift($argv, __FILE__); if ($arg !== null) { // Remove extra empty arg at the end array_pop($argv); } break; } } $argc = count($argv); print('<pre>'); var_dump($argc, $argv); print('</pre>'); 内的所有内容都可以正常评估,因此,如果使用另一个unquote运算符,则需要使用另一个准引用函数来处理它。 !!sym(paste0(!!!vars, sep = '.')) 不支持!!

一般而言,最好使用复杂的语法(例如paste0())分几步进行操作。它更具可读性,并且出错的机会更少。

第二件事是您用!!!引用输入。这意味着它们可以是任何复杂的表达式,而不是列名。如果您希望使用裸列,则最好改用!!(如果您希望使用不带引号的字符串,则最好使用enquos())。

ensyms(...)