R:将字符向量传递给 dplyr::all_of() 的预期输出是什么?
R: What is the expected output of passing a character vector to dplyr::all_of()?
我试图结合使用 dplyr::all_of()
来理解 dplyr::group_by()
的预期输出。我的理解是,使用 dplyr::all_of()
应该将包含变量名的字符向量转换为裸名,以便 group_by()
,但这似乎没有发生。
下面,我生成一些假数据,将不同的对象传递给 group_by()
with(out) all_of()
并计算每组中的观察数。在该示例中,传递不带 dplyr::all_of()
的单个裸列名称会产生正确的输出:每个列的唯一值一行。但是,传递字符向量或使用 dplyr::all_of()
会产生不正确的输出:无论一列中的值有多少,都会产生一行。
使用 all_of
时会发生什么情况?我如何将字符向量传递给 group_by
以作为裸名向量进行处理?
library(dplyr)
# Create a 20-row data.frame with
# 2 variables each with 2 unique values.
df <- data.frame(var = rep(c("a", "b"), 10),
bar = rep(c(1, 2), 20))
# Output 1: 2x2 tibble - GOOD
df %>% group_by(var) %>% summarize(n = n())
# Output 2: 1x2 tibble - BAD
foo <- "var"
df %>% group_by(all_of(foo)) %>% summarize(n = n())
# Output 3: 1x2 tibble
df %>% group_by("var") %>% summarize(n = n())
# Output 4: Error in_var not found - BAD
foo2 <- list("var", "bar")
lapply(foo2, function(in_var) {
df %>%
group_by(in_var) %>%
summarize(n = n())
})
# Output 5: list of length 2 where
# each element is a 1x2 tibble - BAD
foo2 <- list("var", "bar")
lapply(foo2, function(in_var) {
df %>%
group_by(all_of(in_var)) %>%
summarize(n = n())
})
我们可以使用group_by_at
lapply(foo2, function(in_var) df %>%
group_by_at(all_of(in_var)) %>%
summarise(n = n()))
-输出
#[[1]]
# A tibble: 2 x 2
# var n
#* <chr> <int>
#1 a 20
#2 b 20
#[[2]]
# A tibble: 2 x 2
# bar n
#* <dbl> <int>
#1 1 20
#2 2 20
由于 across
替换了 group_by_at
的一些功能,我们可以将其与 all_of
:
一起使用
lapply(foo2, function(in_var) df %>%
group_by(across(all_of(in_var))) %>%
summarise(n = n()))
或转换为 sym
bol 并计算 (!!
)
lapply(foo2, function(in_var) df %>%
group_by(!! rlang::sym(in_var)) %>%
summarise(n = n()))
或使用map
library(purrr)
map(foo2, ~ df %>%
group_by(!! rlang::sym(.x)) %>%
summarise(n = n()))
或者代替group_by
,可以是count
map(foo2, ~ df %>%
count(across(all_of(.x))))
添加@akrun 的多种方法来实现所需输出的答案 - 我对 all_of()
的理解是,它是选择存储为 dplyr
函数字符的变量的帮助器,并且在下面使用 vctrs
。与 any_of()
相比,后者是 all_of()
的不太严格的版本和一些方便的用例。
阅读 ?tidyselect::all_off()
很有帮助。此页面也有助于跟上 dplyr
的变化和整洁的评估 https://dplyr.tidyverse.org/articles/programming.html。
根据 RStudio 开发人员的决定,dplyr
范围内的动词将来会被 across
取代。请参阅 ?group_by_at()
或其他 *_if
、*_at
、*_all
文档。所以我想这真的取决于您在工作流程中使用的 dplyr
版本以及最适合您的版本。
此 SO post 还提供了解决方案随时间变化的上下文,将字符传递给 dplyr
函数,并且可能还有更多帖子。
我试图结合使用 dplyr::all_of()
来理解 dplyr::group_by()
的预期输出。我的理解是,使用 dplyr::all_of()
应该将包含变量名的字符向量转换为裸名,以便 group_by()
,但这似乎没有发生。
下面,我生成一些假数据,将不同的对象传递给 group_by()
with(out) all_of()
并计算每组中的观察数。在该示例中,传递不带 dplyr::all_of()
的单个裸列名称会产生正确的输出:每个列的唯一值一行。但是,传递字符向量或使用 dplyr::all_of()
会产生不正确的输出:无论一列中的值有多少,都会产生一行。
使用 all_of
时会发生什么情况?我如何将字符向量传递给 group_by
以作为裸名向量进行处理?
library(dplyr)
# Create a 20-row data.frame with
# 2 variables each with 2 unique values.
df <- data.frame(var = rep(c("a", "b"), 10),
bar = rep(c(1, 2), 20))
# Output 1: 2x2 tibble - GOOD
df %>% group_by(var) %>% summarize(n = n())
# Output 2: 1x2 tibble - BAD
foo <- "var"
df %>% group_by(all_of(foo)) %>% summarize(n = n())
# Output 3: 1x2 tibble
df %>% group_by("var") %>% summarize(n = n())
# Output 4: Error in_var not found - BAD
foo2 <- list("var", "bar")
lapply(foo2, function(in_var) {
df %>%
group_by(in_var) %>%
summarize(n = n())
})
# Output 5: list of length 2 where
# each element is a 1x2 tibble - BAD
foo2 <- list("var", "bar")
lapply(foo2, function(in_var) {
df %>%
group_by(all_of(in_var)) %>%
summarize(n = n())
})
我们可以使用group_by_at
lapply(foo2, function(in_var) df %>%
group_by_at(all_of(in_var)) %>%
summarise(n = n()))
-输出
#[[1]]
# A tibble: 2 x 2
# var n
#* <chr> <int>
#1 a 20
#2 b 20
#[[2]]
# A tibble: 2 x 2
# bar n
#* <dbl> <int>
#1 1 20
#2 2 20
由于 across
替换了 group_by_at
的一些功能,我们可以将其与 all_of
:
lapply(foo2, function(in_var) df %>%
group_by(across(all_of(in_var))) %>%
summarise(n = n()))
或转换为 sym
bol 并计算 (!!
)
lapply(foo2, function(in_var) df %>%
group_by(!! rlang::sym(in_var)) %>%
summarise(n = n()))
或使用map
library(purrr)
map(foo2, ~ df %>%
group_by(!! rlang::sym(.x)) %>%
summarise(n = n()))
或者代替group_by
,可以是count
map(foo2, ~ df %>%
count(across(all_of(.x))))
添加@akrun 的多种方法来实现所需输出的答案 - 我对 all_of()
的理解是,它是选择存储为 dplyr
函数字符的变量的帮助器,并且在下面使用 vctrs
。与 any_of()
相比,后者是 all_of()
的不太严格的版本和一些方便的用例。
阅读 ?tidyselect::all_off()
很有帮助。此页面也有助于跟上 dplyr
的变化和整洁的评估 https://dplyr.tidyverse.org/articles/programming.html。
根据 RStudio 开发人员的决定,dplyr
范围内的动词将来会被 across
取代。请参阅 ?group_by_at()
或其他 *_if
、*_at
、*_all
文档。所以我想这真的取决于您在工作流程中使用的 dplyr
版本以及最适合您的版本。
此 SO post 还提供了解决方案随时间变化的上下文,将字符传递给 dplyr
函数,并且可能还有更多帖子。