Как интерпретировать сообщение dplyr `summarize ()`, перегруппировывающее вывод по 'x' (переопределить с помощью аргумента `.groups`)?

94

Я начал получать новое сообщение (см. Заголовок сообщения) при запуске group_by и summarize () после обновления до версии разработки dplyr 0.8.99.9003.

Вот пример воссоздания вывода:

library(tidyverse)
library(hablar)
df <- read_csv("year, week, rat_house_females, rat_house_males, mouse_wild_females, mouse_wild_males 
               2018,10,1,1,1,1
               2018,10,1,1,1,1
               2018,11,2,2,2,2
               2018,11,2,2,2,2
               2019,10,3,3,3,3
               2019,10,3,3,3,3
               2019,11,4,4,4,4
               2019,11,4,4,4,4") %>% 
  convert(chr(year,week)) %>% 
  mutate(total_rodents = rowSums(select_if(., is.numeric))) %>% 
  convert(num(year,week)) %>% 
  group_by(year,week) %>% summarise(average = mean(total_rodents))

Выходной тиббл правильный, но появляется это сообщение:

summarise()перегруппировка вывода по 'году' (переопределить с .groupsаргументом)

Как это следует интерпретировать? Почему он сообщает о перегруппировке только по «годам», когда я сгруппировал по году и по неделям? Кроме того, что означает переопределение и зачем мне это делать?

Я не думаю, что сообщение указывает на проблему, потому что оно появляется во всей виньетке dplyr: https://cran.r-project.org/web/packages/dplyr/vignettes/programming.html

Я считаю, что это новое сообщение, потому что оно появилось только в самых недавних вопросах SO, таких как Как расплавить вывод pairwise.wilcox.test с помощью dplyr? и R Агрегировать по нескольким столбцам (ни один из которых не обращается к сообщению о перегруппировке / переопределении).

Спасибо!

Сьюзи Деркинс
источник
Пожалуйста, сделайте воспроизводимые примеры. Из какого пакета convert()?
Даг Хьерманн,
Это от хаблара. Добавляя это
Сьюзи Деркинс,

Ответы:

114

Это просто дружеское предупреждение. По умолчанию, если есть какая-либо группировка перед summarise, она удаляет одну групповую переменную, то есть последнюю, указанную в group_by. Если есть только одна группирующая переменная, не будет никакого атрибута группировки после, summariseи если их больше одного, то есть здесь два, поэтому атрибут для группировки уменьшается до 1, то есть данные будут иметь 'год' как атрибут группировки. В качестве воспроизводимого примера

library(dplyr)
mtcars %>%
     group_by(am) %>% 
     summarise(mpg = sum(mpg))
#`summarise()` ungrouping output (override with `.groups` argument)
# A tibble: 2 x 2
#     am   mpg
#* <dbl> <dbl>
#1     0  326.
#2     1  317.

Сообщение состоит в том, что это происходит, ungroupт.е. когда есть сингл group_by, он удаляет эту группу послеsummarise

mtcars %>% 
   group_by(am, vs) %>% 
   summarise(mpg = sum(mpg))
#`summarise()` regrouping output by 'am' (override with `.groups` argument)
# A tibble: 4 x 3
# Groups:   am [2]
#     am    vs   mpg
#  <dbl> <dbl> <dbl>
#1     0     0  181.
#2     0     1  145.
#3     1     0  118.
#4     1     1  199.

Здесь он отбрасывает последнюю группировку и перегруппировывается с «я»

Если проверить ?summarise, есть .groupsаргумент , который по умолчанию является "drop_last"и другими вариантами "drop", "keep","rowwise"

.groups - Группирующая структура результата.

"drop_last": отбрасывает последний уровень группировки. Это была единственная поддерживаемая опция до версии 1.0.0.

"drop": отбрасываются все уровни группировки.

"keep": та же структура группировки, что и .data.

«rowwise»: каждая строка представляет собой отдельную группу.

Если .groups не указан, вы либо получите "drop_last", если все результаты имеют размер 1, либо "keep", если размер меняется. Кроме того, сообщение проинформирует вас об этом выборе, если для параметра «dplyr.summarise.inform» не установлено значение FALSE.

то есть, если мы изменим .groupsin summarise, мы не получим сообщение, потому что атрибуты группы удалены

mtcars %>% 
    group_by(am) %>%
    summarise(mpg = sum(mpg), .groups = 'drop')
# A tibble: 2 x 2
#     am   mpg
#* <dbl> <dbl>
#1     0  326.
#2     1  317.


mtcars %>%
   group_by(am, vs) %>%
   summarise(mpg = sum(mpg), .groups = 'drop')
# A tibble: 4 x 3
#     am    vs   mpg
#* <dbl> <dbl> <dbl>
#1     0     0  181.
#2     0     1  145.
#3     1     0  118.
#4     1     1  199.


mtcars %>% 
   group_by(am, vs) %>% 
   summarise(mpg = sum(mpg), .groups = 'drop') %>%
   str
#tibble [4 × 3] (S3: tbl_df/tbl/data.frame)
# $ am : num [1:4] 0 0 1 1
# $ vs : num [1:4] 0 1 0 1
# $ mpg: num [1:4] 181 145 118 199

Раньше это предупреждение не выдавалось, и это могло привести к ситуациям, когда OP выполняет mutateили что-то еще, предполагая, что группировка отсутствует, и приводит к неожиданному результату. Теперь предупреждение дает пользователю указание на то, что мы должны быть осторожны, поскольку есть атрибут группировки

ПРИМЕЧАНИЕ. .groupsПрямо сейчас находится experimentalв своем жизненном цикле. Таким образом, в будущих выпусках поведение может быть изменено.

В зависимости от того, нужно ли нам какое-либо преобразование данных на основе одной и той же группирующей переменной (или нет необходимости), мы могли бы выбрать разные параметры в .groups.

Акрун
источник
11
Также было бы полезно объяснить, почему этот атрибут группировки вообще имеет значение, потому что он неочевиден.
jangorecki
6
Означает ли это, что если вы используете .groups = 'drop', вам не нужно использовать ungroup () перед запуском некоторых других функций, таких как case_when или rowSums?
Сьюзи Деркинс,
7
@SusieDerkins Если вы используете summarise, и with groups = 'drop', то атрибуты группы отсутствуют, поэтому вам не нужно ungroup(по крайней мере, в текущем сценарии, пока это поведение не будет изменено в tidyverse)
Акрун
1
Есть какие-нибудь советы о том, как настроить поведение группировки глобально, чтобы мне не приходилось вводить его вручную во всех моих сценариях, чтобы избежать лишних сообщений?
Майк Лоуренс,
37
Ой! чтобы заглушить сообщение (сохраняя старое значение по умолчанию "drop_last"), выполните options (dplyr.summarise.inform = F)
Майк Лоуренс,