Como interpretar a mensagem dplyr `sumize ()` reagrupando a saída por 'x' (sobrescrever com o argumento `.groups`)?

112

Comecei a receber uma nova mensagem (veja o título da postagem) ao executar group_by e summary () após atualizar para a versão de desenvolvimento dplyr 0.8.99.9003.

Aqui está um exemplo para recriar a saída:

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))

A tabela de saída está correta, mas esta mensagem aparece:

summarise()reagrupando a produção por 'ano' (substituir com .groupsargumento)

Como isso deve ser interpretado? Por que ele relata o reagrupamento apenas por 'ano' quando agrupei por ano e semana? Além disso, o que significa substituir e por que eu faria isso?

Não acho que a mensagem indique um problema porque aparece em toda a vinheta dplyr: https://cran.r-project.org/web/packages/dplyr/vignettes/programming.html

Acredito que seja uma mensagem nova porque só apareceu em questões muito recentes do SO, como How to melt pairwise.wilcox.test output using dplyr? e R agregado em várias colunas (nenhuma das quais endereça a mensagem de reagrupamento / substituição).

Obrigado!

Susie Derkins
fonte
Faça exemplos reproduzíveis. De qual pacote é convert()?
Dag Hjermann
É de hablar. Adicionando isso.
Susie Derkins

Respostas:

137

É apenas uma mensagem de aviso amigável. Por padrão, se houver qualquer agrupamento antes de summarise, ele elimina uma variável de grupo, ou seja, a última especificada em group_by. Se houver apenas uma variável de agrupamento, não haverá nenhum atributo de agrupamento após o summarisee se houver mais de um, ou seja, aqui são dois, então, o atributo para agrupamento é reduzido a 1, ou seja, os dados teriam o 'ano' como atributo de agrupamento. Como um exemplo reproduzível

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.

A mensagem é que é ungrouping, ou seja, quando há um único group_by, ele descarta esse agrupamento após osummarise

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.

Aqui, ele remove o último agrupamento e reagrupa com o 'sou'

Se verificar o ?summarise, não há .groupsargumento que por padrão é "drop_last"e as outras opções são "drop", "keep","rowwise"

.groups - Estrutura de agrupamento do resultado.

"drop_last": descartando o último nível de agrupamento. Esta era a única opção com suporte antes da versão 1.0.0.

"drop": todos os níveis de agrupamento são eliminados.

"keep": mesma estrutura de agrupamento que .data.

"rowwise": cada linha é seu próprio grupo.

Quando .groups não é especificado, você obtém "drop_last" quando todos os resultados têm tamanho 1 ou "manter" se o tamanho varia. Além disso, uma mensagem informa sobre essa escolha, a menos que a opção "dplyr.summarise.inform" seja definida como FALSE.

ou seja, se mudarmos .groupspara summarise, não recebemos a mensagem porque os atributos do grupo são removidos

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

Anteriormente, esse aviso não era emitido e poderia levar a situações em que o OP faz um mutate ou algo mais, presumindo que não há agrupamento e resulta em uma saída inesperada. Agora, o aviso dá ao usuário uma indicação de que devemos tomar cuidado para que haja um atributo de agrupamento

NOTA: O .groupsagora está experimentalem seu ciclo de vida. Portanto, o comportamento pode ser modificado nas versões futuras

Dependendo se precisamos de alguma transformação dos dados com base na mesma variável de agrupamento (ou não necessária), podemos selecionar as diferentes opções em .groups.

Akrun
fonte
12
O que seria útil também é explicar por que esse atributo de agrupamento é importante, porque não é óbvio.
jangorecki 01 de
7
Isso significa que se você usar .groups = 'drop', você não precisa usar ungroup () antes de executar certas outras funções, como case_when ou rowSums?
Susie Derkins
8
@SusieDerkins Se você estiver usando summarise, e com groups = 'drop', os atributos do grupo não estão lá, então você não precisa ungroup(pelo menos no cenário atual até que este comportamento seja alterado no tidyverse)
akrun
49
Oh! para silenciar a mensagem (mantendo o antigo padrão "drop_last"), faça options (dplyr.summarise.inform = F)
Mike Lawrence
6
@MikeLawrence obrigado! Isso é tudo que eu precisava. É um pouco desconcertante que o código que funcionava anteriormente esteja emitindo avisos repentinamente (não deveria haver um aviso amigável ).
Fofo de