r - 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”,因为示例中的函数有多个参数?
解决方案
正如您编写的那样,该函数选择column
from 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
推荐阅读
- python - 为什么我会收到索引超出范围错误?
- javascript - 如何在 Vue 中使用 JSX 制作适当控制和反应式的组件
- amazon-web-services - 为什么不能 Terraform SSH 进入我的 EC2 实例?
- android - Android - 如何模糊背后的布局
- python - 如何在 Python 中让一个简单的股票价格模拟过程更高效?
- angular - NgIf 和零:为什么模板没有被渲染?
- javascript - 重定义父类后,Javascript对象实例如何保留方法?
- akka-stream - 如何将 akka.stream.javadsl.Source 转换为 java.util.concurrent.Flow.Publisher
- reactjs - 使用 Bootstrap 和 React 在 Safari 上选择菜单列表
- javascript - 如何使用 input[type="Date"] 在 javascript 中验证出生日期?