Это не зависит от предложений.Вот та же проблема в отсутствии нестандартной оценки в 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
Как объяснено в других вопросах здесь и здесь , do
это соединитель, который позволяет применять произвольные функции к каждой группе.Причина, по которой глаголы dplyr
, такие как mutate
и filter
, не требуют do
, заключается в том, что они обрабатывают сгруппированные кадры данных внутри как особые случаи (см., Например, реализацию mutate ).Если вы хотите, чтобы ваша собственная функция эмулировала это поведение, вам необходимо различать сгруппированные и разгруппированные фреймы данных:
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