首页 > 解决方案 > R:为什么 group_by 仍然需要“做”,即使使用 quosures

问题描述

如何使用户定义的函数与管道和 group_by 很好地配合使用?这是一个简单的函数:

 library(tidyverse)

 fun_head <- function(df, column) {
 column <- enquo(column)
 df %>% select(!!column) %>% head(1)
 }

该函数与管道很好地配合使用,并允许按另一列过滤:

 mtcars %>% filter(cyl == 4) %>% fun_head(mpg)

 >    mpg
   1 22.8

但是,相同的管道工作因 group_by 而失败

mtcars %>% group_by(cyl) %>% fun_head(mpg)

Adding missing grouping variables: `cyl`
# A tibble: 1 x 2
# Groups:   cyl [1]
     cyl   mpg
     <dbl> <dbl>
1     6    21

在 group_by 之后使用“do”使其工作:

 > mtcars %>% group_by(cyl) %>% do(fun_head(., mpg))
 # A tibble: 3 x 2
 # Groups:   cyl [3]
    cyl   mpg
   <dbl> <dbl>
1     4  22.8
2     6  21  
3     8  18.7

应该如何更改函数,以便它与 filter 和 group_by 一致地工作而不需要“do”?
或者 quosures 与问题无关,而 group_by 只需要使用“do”,因为示例中的函数有多个参数?

标签: rdplyrtidyversequosure

解决方案


正如您编写的那样,该函数选择columnfrom df,然后采取head,这是df(head不是 tidyverse 函数,并且不知道任何分组的第一行)。dplyr::slice(1)取每组的第一行,这就是你想要的。您可以使用

 fun_head <- function(df, column) {
 column <- enquo(column)
 df %>% slice(1) %>% select(!!column)
 }

 mtcars %>% group_by(cyl) %>% fun_head(mpg)

# # A tibble: 3 x 2
# # Groups:   cyl [3]
#     cyl   mpg
#   <dbl> <dbl>
# 1     4  22.8
# 2     6  21  
# 3     8  18.7

推荐阅读