能否将多个变量传递给同一个双花括号?

8
我正在构建一个函数,使用 {{ }}(花括号内再加一个花括号)。
我希望用户能够将多个变量传递到同一个 {{ }}, 但我不确定是否可以使用 {{ }}来实现这一点。我找不到任何示例来展示如何做到这一点。
您能告诉我它是否可行,如果是的话,请帮我使下面的最小重现示例工作?
library(tidyverse)

group_mean <- function(.data, group){
  .data %>% 
    group_by({{group}}) %>% 
    summarise_all(mean)

}

# Works
mtcars %>% 
  group_mean(group = cyl)

# Fails
mtcars %>% 
  group_mean(group = c(cyl, am)) 

Error: Column `c(cyl, am)` must be length 32 (the number of rows) or one, not 64 

以前从未见过这种情况。你需要的是 group_by_at()... 当然还要使用 NSE。 - Sotos
我不确定你之前从未见过什么。是错误还是使用group_by()函数? - Steen Harsted
1
在R中从未见过使用双花括号定义多个变量。 - Sotos
有趣的是,它有时候能够正常工作。例如,select_vars <- function(.data, selected){ .data %>% select({{selected}}) %>% summarise_all(mean)} mtcars %>% select_vars(selected = c(cyl, mpg, hp)) - Steen Harsted
根据rlang 0.4.0的这个公告,应该使用 ... 传递多个参数:如果您想将多个参数传递给数据屏蔽动词,请直接传递... - thothal
2个回答

9

2022年更新:如今,我们往往使用tidyselect的c()语法来接收多组变量。

library(dplyr)

my_mean <- function(data, group_vars, summary_vars) {
  data |>
    group_by(across({{ group_vars }})) |>
    summarise(across({{ summary_vars }}, \(x) mean(x, na.rm = TRUE)))
}

mtcars |> my_mean(c(cyl, am), c(mpg, disp))
#> `summarise()` has grouped output by 'cyl'. You can override using the
#> `.groups` argument.
#> # A tibble: 6 × 4
#> # Groups:   cyl [3]
#>     cyl    am   mpg  disp
#>   <dbl> <dbl> <dbl> <dbl>
#> 1     4     0  22.9 136.
#> 2     4     1  28.1  93.6
#> 3     6     0  19.1 205.
#> 4     6     1  20.6 155
#> 5     8     0  15.0 358.
#> 6     8     1  15.4 326

请参考https://rlang.r-lib.org/reference/topic-data-mask-programming.html桥接模式部分。
如果您的函数需要处理多组变量,请使用vars()进行外部引用。该函数将其输入简单地捕获为表达式列表:
vars(foo, bar)
#> [[1]]
#> <quosure>
#> expr: ^foo
#> env:  global
#>
#> [[2]]
#> <quosure>
#> expr: ^bar
#> env:  global

将一个与!!!拼接的参数传入函数:

group_mean <- function(.data, .vars, ...) {
  .data <- doingsomethingelse(.data, ...)

  .data %>% 
     group_by(!!!.vars) %>% 
     summarise_all(mean)
}

使用方式如下:

data %>% group_mean(vars(foo, bar), baz, quux)

6

对于多个分组变量,你不需要使用花括号,而是用三个点代替。

group_mean <- function(.data, ...){
  .data %>% 
     group_by(...) %>% 
     summarise_all(mean)
}


mtcars %>%  group_mean(cyl)

# A tibble: 3 x 11
#    cyl   mpg  disp    hp  drat    wt  qsec    vs    am  gear  carb
#  <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#1     4  26.7  105.  82.6  4.07  2.29  19.1 0.909 0.727  4.09  1.55
#2     6  19.7  183. 122.   3.59  3.12  18.0 0.571 0.429  3.86  3.43
#3     8  15.1  353. 209.   3.23  4.00  16.8 0     0.143  3.29  3.5 

mtcars %>%  group_mean(cyl, am)

#    cyl    am   mpg  disp    hp  drat    wt  qsec    vs  gear  carb
#  <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#1     4     0  22.9 136.   84.7  3.77  2.94  21.0 1      3.67  1.67
#2     4     1  28.1  93.6  81.9  4.18  2.04  18.4 0.875  4.25  1.5 
#3     6     0  19.1 205.  115.   3.42  3.39  19.2 1      3.5   2.5 
#4     6     1  20.6 155   132.   3.81  2.76  16.3 0      4.33  4.67
#5     8     0  15.0 358.  194.   3.12  4.10  17.1 0      3     3.08
#6     8     1  15.4 326   300.   3.88  3.37  14.6 0      5     6   

谢谢。我正在构建的真实函数已经在其他地方使用....,因此不幸的是,使用...不是一个选项。 - Steen Harsted
1
@SteenHarsted,你能把你的函数分解成不同的函数吗,这样你就可以以不同的方式使用“…”了吗? - Ronak Shah
谢谢。是的,我想我要尝试类似这样的东西。 - Steen Harsted

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接