如何使用列名向量作为 dplyr::group_by() 的输入?
How to use vector of column names as input into dplyr::group_by()?
我想创建一个基于 dplyr
的函数,对数据子集执行某些操作。子集由数据集中一个或多个键列的值定义。当仅使用一列来标识子集时,我的代码工作正常:
set.seed(1)
df <- tibble(
g1 = c(1, 1, 2, 2, 2),
g2 = c(1, 2, 1, 2, 1),
a = sample(5)
)
group_key <- "g1"
aggregate <- function(df, by) {
df %>% group_by(!!sym(by)) %>% summarize(a = mean(a))
}
aggregate(df, by = group_key)
这按预期工作并且 returns 是这样的:
# A tibble: 2 x 2
g1 a
<dbl> <dbl>
1 1 1.5
2 2 4
不幸的是,如果我更改 group_key
:
,一切都会崩溃
group_key <- c("g1", "g2")
aggregate(df, by = group_key)
我收到一个错误:Only strings can be converted to symbols
,我认为它来自 rlang::sym()
。用 syms()
替换它不起作用,因为我得到一个名称列表,group_by()
窒息。
如有任何建议,我们将不胜感激!
您需要使用 unquote-splice 运算符 !!!
:
aggregate <- function(df, by) {
df %>% group_by(!!!syms(by)) %>% summarize(a = mean(a))
}
group_key <- c("g1", "g2")
aggregate(df, by = group_key)
## A tibble: 4 x 3
## Groups: g1 [2]
# g1 g2 a
# <dbl> <dbl> <dbl>
#1 1 1 1
#2 1 2 4
#3 2 1 2.5
#4 2 2 5
或者,您可以使用 dplyr::group_by_at
:
agg <- function(df, by) {
require(dplyr)
df %>% group_by_at(vars(one_of(by))) %>% summarize(a = mean(a))}
group_key <- "g1"
group_keys <- c("g1","g2")
agg(df, by = group_key)
#> # A tibble: 2 x 2
#> g1 a
#> <dbl> <dbl>
#> 1 1 2.5
#> 2 2 3.33
agg(df, by = group_keys)
#> # A tibble: 4 x 3
#> # Groups: g1 [2]
#> g1 g2 a
#> <dbl> <dbl> <dbl>
#> 1 1 1 1
#> 2 1 2 4
#> 3 2 1 2.5
#> 4 2 2 5
使用 dplyr 1.0.0 更新
新的 across()
允许像 all_of
这样的 tidyselect 功能,它取代了 NSE 的 quote-unqote 程序。代码看起来更简单一些:
aggregate <- function(df, by) {
df %>%
group_by(across(all_of(by))) %>%
summarize(a = mean(a))
}
df %>% aggregate(group_key)
我想创建一个基于 dplyr
的函数,对数据子集执行某些操作。子集由数据集中一个或多个键列的值定义。当仅使用一列来标识子集时,我的代码工作正常:
set.seed(1)
df <- tibble(
g1 = c(1, 1, 2, 2, 2),
g2 = c(1, 2, 1, 2, 1),
a = sample(5)
)
group_key <- "g1"
aggregate <- function(df, by) {
df %>% group_by(!!sym(by)) %>% summarize(a = mean(a))
}
aggregate(df, by = group_key)
这按预期工作并且 returns 是这样的:
# A tibble: 2 x 2
g1 a
<dbl> <dbl>
1 1 1.5
2 2 4
不幸的是,如果我更改 group_key
:
group_key <- c("g1", "g2")
aggregate(df, by = group_key)
我收到一个错误:Only strings can be converted to symbols
,我认为它来自 rlang::sym()
。用 syms()
替换它不起作用,因为我得到一个名称列表,group_by()
窒息。
如有任何建议,我们将不胜感激!
您需要使用 unquote-splice 运算符 !!!
:
aggregate <- function(df, by) {
df %>% group_by(!!!syms(by)) %>% summarize(a = mean(a))
}
group_key <- c("g1", "g2")
aggregate(df, by = group_key)
## A tibble: 4 x 3
## Groups: g1 [2]
# g1 g2 a
# <dbl> <dbl> <dbl>
#1 1 1 1
#2 1 2 4
#3 2 1 2.5
#4 2 2 5
或者,您可以使用 dplyr::group_by_at
:
agg <- function(df, by) {
require(dplyr)
df %>% group_by_at(vars(one_of(by))) %>% summarize(a = mean(a))}
group_key <- "g1"
group_keys <- c("g1","g2")
agg(df, by = group_key)
#> # A tibble: 2 x 2
#> g1 a
#> <dbl> <dbl>
#> 1 1 2.5
#> 2 2 3.33
agg(df, by = group_keys)
#> # A tibble: 4 x 3
#> # Groups: g1 [2]
#> g1 g2 a
#> <dbl> <dbl> <dbl>
#> 1 1 1 1
#> 2 1 2 4
#> 3 2 1 2.5
#> 4 2 2 5
使用 dplyr 1.0.0 更新
新的 across()
允许像 all_of
这样的 tidyselect 功能,它取代了 NSE 的 quote-unqote 程序。代码看起来更简单一些:
aggregate <- function(df, by) {
df %>%
group_by(across(all_of(by))) %>%
summarize(a = mean(a))
}
df %>% aggregate(group_key)