如何使用户定义的函数与管道和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一致地工作而无需“做”呢?
还是与问题无关,而group_by只需要使用“ do”,因为示例中的函数具有多个参数?
答案 0 :(得分:3)
编写该函数时,该函数从column
中选择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
答案 1 :(得分:3)
这与确定无关。在fun_head()
中没有非标准评估的情况下,这是同样的问题:
fun_head <- function(df) {df %>% select(mpg) %>% head(1)}
mtcars %>% group_by( cyl ) %>% fun_head()
# Adding missing grouping variables: `cyl`
# # A tibble: 1 x 2
# # Groups: cyl [1]
# cyl mpg
# <dbl> <dbl>
# 1 6 21
如其他问题here和here所述,do
是允许您将任意功能应用于每个组的连接器。 dplyr
和mutate
之类的filter
动词不需要do
的原因是因为它们在内部将分组数据帧作为特殊情况处理(例如,参见{{3} }。如果您希望自己的函数模拟此行为,则需要区分分组数据帧和非分组数据帧:
fun_head2 <- function( df )
{
if( !is.null(groups(df)) )
df %>% do( fun_head2(.) )
else
df %>% select(mpg) %>% head(1)
}
mtcars %>% group_by(cyl) %>% fun_head2()
# # A tibble: 3 x 2
# # Groups: cyl [3]
# cyl mpg
# <dbl> <dbl>
# 1 4 22.8
# 2 6 21
# 3 8 18.7
编辑:我想指出,group_by
+ do
的另一种替代方法是使用tidyr::nest
+ purrr::map
。回到带有两个参数的原始函数定义:
fhead <- function(.df, .var) { .df %>% select(!!ensym(.var)) %>% head(1) }
以下两条链是等效的(由于group_by
按分组变量排序,而nest
却不行,因此行的顺序最高)
# Option 1: group_by + do
mtcars %>% group_by(cyl) %>% do( fhead(., mpg) ) %>% ungroup
# Option 2: nest + map
mtcars %>% nest(-cyl) %>% mutate_at( "data", map, fhead, "mpg" ) %>% unnest