使用变量名进行多列分组的dplyr操作

46

我正在使用R Shiny进行一些探索性数据分析。我有两个复选框输入,其中仅包含用户选择的选项。第一个复选框输入仅包含分类变量;第二个复选框仅包含数值变量。接下来,我对这两个选择应用了groupby

var1 <- input$variable1      # Checkbox with categorical variables
var2 <- input$variable2      # Checkbox with numerical variables

v$data <- dataset %>%
  group_by_(var1) %>%
  summarize_(Sum = interp(~sum(x), x = as.name(var2))) %>%
  arrange(desc(Sum))

当只选择一个分类变量时,这个groupby可以完美地工作。当选择多个分类变量时,这个groupby会返回一个带有列名的数组。我该如何将这个列名数组传递给dplyrgroupby


当用户选择了3个分类变量时,我有11个分类变量,它会给我[1] "dish_name" "dish_type" [3] "user_location_grp"var1中,我该如何将这个数组传递给groupby。 - Neil
4个回答

65

dplyr版本>1.0

在较新的dplyr版本中,您应该使用across与一个tidyselect帮助程序函数。请参阅help("language", "tidyselect")获取所有帮助程序函数的列表。在这种情况下,如果您想要将所有列放入字符向量中,请使用all_of()

cols <- c("mpg","hp","wt")
mtcars %>% 
   group_by(across(all_of(cols))) %>% 
   summarize(x=mean(gear))

原始答案(较旧版本的dplyr)

如果您有一个变量名称的向量,您应该将它们传递给group_by_.dots=参数。例如:

mtcars %>% 
   group_by_(.dots=c("mpg","hp","wt")) %>% 
   summarize(x=mean(gear))

5
需要注意的是,group_by_() 函数已经被软弃用,并将最终从 dplyr 包中移除。 - bschneidr

11

使用dplyr 1.0.0,基于“常规”group_by,我们具有以下可能性:

library(dplyr)

group_cols <- c("vs", "am")

mtcars %>% 
  group_by(across(all_of(group_cols))) %>% 
  summarize(mean_wt = mean(wt))

在 group_by(across( 中是否需要 all_of? - Arthur Yip
在这种情况下,是的。 - Michael M

10

您可以使用由与dplyr相同的团队创建的rlang包中的帮助程序。当使用dplyr和其他整洁化包时,您无需加载rlang包即可使用这些帮助程序。

具体来说,您可以这样使用syms函数和!!!函数:

library(dplyr)

group_cols <- c("vs", "am")

mtcars %>% 
  group_by(!!!syms(group_cols)) %>% 
  summarize(mean_wt = mean(wt))

这个相关的问题和答案解释了如何使用!!运算符和sym函数来处理单列名称(即长度为1的字符向量)。


5
最近版本的dplyr包中包含了group_by的变体,如group_by_ifgroup_by_at。您可以使用这些函数,以与select函数类似的语法执行列选择。
就像您可以使用select(my_data, one_of(group_cols))选择一组列一样,您可以使用group_by_at来执行以下操作:
library(dplyr)

group_cols <- c("vs", "am")

mtcars %>% 
  group_by_at(.vars = vars(one_of(group_cols))) %>% 
  summarize(mean_wt = mean(wt))

2
因为这些答案是根本不同的方法。如果用户发现其中一种方法比另一种更有帮助,投票过程将会表明这一点。对于读者来说,有两篇文章并没有什么害处,我很乐意分别接受它们的评论和编辑。请参阅meta.stackexchange上的相关帖子,建议在这种情况下使用多个答案。 - bschneidr
1
“Scoped verbs (⁠_if⁠, ⁠_at⁠, ⁠_all⁠)在现有的动词中已被pick()或across()的使用所取代。有关详细信息,请参阅vignette("colwise")。” - undefined
1
是的,说得好。pick()across()是最好的方法,直到它们最终被取代为止 ;) - undefined

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