用多个符号简化 tidyeval

simplifying tidyeval with multiple symbols

以下函数按预期运行:可以将多个变量传递给 group_by 而无需将它们放入 alist()dplyr::vars:


mean_by_grp <- function(df, meanvar, grp) {
  
  grouping <- enexpr(grp) %>% 
    expr_deparse %>% 
    str_split(",",simplify = T) %>% `[`(1,) %>% 
    map(str_remove,"c\(") %>% map(str_remove,"\)") %>% map(str_trim) %>% 
    unlist %>% syms
  
  df %>% 
    group_by(!!!syms(grouping)) %>% 
    summarise("average_{{meanvar}}" := mean({{meanvar}}, na.rm = TRUE),
              .groups = 'drop')
}

starwars %>% mean_by_grp(height, species)
starwars %>% mean_by_grp(height, c(species, homeworld))

然而,这很复杂。我需要将 c(var1,....varn) 变成一个字符串,拆分它并将其变成一个符号列表,这样我就可以使用 with with syms.

没有更简单的方法吗?

当然,我可以使用省略号而不是 grp,但是这样我只能有一个参数将多个符号传递给另一个函数。

一个选项是 dplyr::across:

mean_by_grp <- function(df, meanvar, grp) {
  df %>% 
    group_by(across({{ grp }})) %>% 
    summarise("average_{{meanvar}}" := mean({{meanvar}}, na.rm = TRUE),
              .groups = 'drop')
}

library(dplyr)

starwars %>% mean_by_grp(height, species)
#> # A tibble: 38 × 2
#>    species   average_height
#>    <chr>              <dbl>
#>  1 Aleena               79 
#>  2 Besalisk            198 
#>  3 Cerean              198 
#>  4 Chagrian            196 
#>  5 Clawdite            168 
#>  6 Droid               131.
#>  7 Dug                 112 
#>  8 Ewok                 88 
#>  9 Geonosian           183 
#> 10 Gungan              209.
#> # … with 28 more rows
starwars %>% mean_by_grp(height, c(species, homeworld))
#> # A tibble: 58 × 3
#>    species  homeworld   average_height
#>    <chr>    <chr>                <dbl>
#>  1 Aleena   Aleen Minor             79
#>  2 Besalisk Ojom                   198
#>  3 Cerean   Cerea                  198
#>  4 Chagrian Champala               196
#>  5 Clawdite Zolan                  168
#>  6 Droid    Naboo                   96
#>  7 Droid    Tatooine               132
#>  8 Droid    <NA>                   148
#>  9 Dug      Malastare              112
#> 10 Ewok     Endor                   88
#> # … with 48 more rows