如何解释 dplyr 消息“summarise()”通过“x”重新分组输出(用“.groups”参数覆盖)?

Sus*_*ins 161 r dplyr summarize

在更新到 dplyr 开发版本 0.8.99.9003 后运行 group_by 和 summarise() 时,我开始收到一条新消息(见帖子标题)。

以下是重新创建输出的示例:

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))
Run Code Online (Sandbox Code Playgroud)

输出 tibble 是正确的,但出现此消息:

summarise()按“年份”重新分组输出(用.groups参数覆盖)

这应该如何解释?当我按年和周分组时,为什么它只报告按“年”重新分组?另外,覆盖是什么意思,我为什么要这样做?

我不认为该消息表明存在问题,因为它出现在整个 dplyr 小插图中:https ://cran.r-project.org/web/packages/dplyr/vignettes/programming.html

我相信这是一条新消息,因为它只出现在最近的 SO 问题上,例如如何使用 dplyr 融化pairwise.wilcox.test 输出?R 聚合多列(都没有解决重组/覆盖消息)。

谢谢!

akr*_*run 197

这只是一个友好的警告信息。默认情况下,如果在 之前有任何分组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.
Run Code Online (Sandbox Code Playgroud)

消息是它正在ungrouping ,即当有一个时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.
Run Code Online (Sandbox Code Playgroud)

在这里,它删除最后一个分组并使用“am”重新分组

如果我们检查?summarise,则.groups默认情况下有一个参数,"drop_last"其他选项是"drop", "keep","rowwise"

.groups - 结果的分组结构。

“drop_last”:删除分组的最后一级。这是 1.0.0 版之前唯一支持的选项。

“drop”:所有级别的分组都被删除。

“keep”:与.data 相同的分组结构。

“rowwise”:每一行都是它自己的组。

如果未指定 .groups,则当所有结果的大小为 1 时,您会得到“drop_last”,或者如果大小不同,则得到“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
Run Code Online (Sandbox Code Playgroud)

以前,未发出此警告,它可能导致 OP 执行 amutate或其他操作(假设没有分组)并导致意外输出的情况。现在,警告向用户表明我们应该注意存在分组属性

注意:.groups现在experimental处于其生命周期中。因此,该行为可以在未来的版本中进行修改

根据我们是否需要基于相同分组变量(或不需要)对数据进行任何转换,我们可以在.groups.

  • 哦!要使消息静音(保留旧的“drop_last”默认值),请执行 options(dplyr.summarise.inform=F) (64认同)
  • 同样有用的是解释为什么这个分组属性很重要,因为它并不明显。 (28认同)
  • @MikeLawrence 谢谢!这就是我所需要的。以前工作的代码突然抛出警告(不应该有“友好”警告之类的东西),这有点令人反感。 (13认同)
  • 这是否意味着如果您使用 .groups = 'drop' 在运行某些其他函数(例如 case_when 或 rowSums)之前不必使用 ungroup() ? (9认同)
  • @SusieDerkins如果您使用`summarise`,并且使用`groups = 'drop'`,那么组属性不存在,所以您不需要`ungroup`(至少在当前场景中,直到此行为改变)在整洁宇宙中) (9认同)
  • 即使在努力理解之后,我仍然发现这个新消息令人困惑。“默认情况下,如果在汇总之前有任何分组,它会删除一个组变量,即 group_by 中指定的最后一个变量。” 你所说的“掉落”是什么意思?我仍然在结果中看到所有分组变量。看起来并没有掉落任何东西。 (4认同)
  • 有关如何全局设置分组行为的任何建议,这样我就不必在整个脚本中手动输入它以避免额外的消息? (2认同)
  • @Arthur分组变量是数据帧的一个特殊属性,它们可以改变变异的行为,例如,如果您计算平均值,它将计算每个组的平均值,而不是整个数据帧的平均值。一般来说,`summarise` 最好在默认情况下删除分组 `.groups = "drop"`。如果您需要分组计算,您可以稍后再次使用“group_by”。 (2认同)

Mar*_*ber 16

解释已接受的答案,这只是一个友好的令人困惑的警告。

summarise()已按“xxx”对输出进行分组

应阅读:输出正常并且包含所有分组列作为属性,只有分组键可能受到限制。

mtcars通过cyl, am计算分组的示例mean(mpg)

mtcars %>% group_by(cyl, am) %>% summarise(avg_mpg = mean(mpg))
`summarise()` has grouped output by 'cyl'. You can override using the `.groups` argument.
# A tibble: 6 x 3
# Groups:   cyl [3]
    cyl    am avg_mpg
  <dbl> <dbl>   <dbl>
1     4     0    22.9
2     4     1    28.1
3     6     0    19.1
4     6     1    20.6
5     8     0    15.0
6     8     1    15.4
Run Code Online (Sandbox Code Playgroud)

该警告表示,在输出中,仅使用默认值保留了第一个原始分组键.groups = "drop_last"。看线# Groups: cyl [3]

尽管如此,属性还是完整的,并且cyl都已am定义。

这里是可用选项的快速概述,显示了该函数的结果group_keys()

mtcars %>% group_by(cyl, am) %>% summarise(avg_mpg = mean(mpg)) %>% group_keys() 
`summarise()` has grouped output by 'cyl'. You can override using the `.groups` argument.
# A tibble: 3 x 1
    cyl
  <dbl>
1     4
2     6
3     8

mtcars %>% group_by(cyl, am) %>% summarise(avg_mpg = mean(mpg), .groups = "keep") %>% group_keys() 
# A tibble: 6 x 2
    cyl    am
  <dbl> <dbl>
1     4     0
2     4     1
3     6     0
4     6     1
5     8     0
6     8     1

mtcars %>% group_by(cyl, am) %>% summarise(avg_mpg = mean(mpg), .groups = "drop") %>% group_keys() 
# A tibble: 1 x 0
Run Code Online (Sandbox Code Playgroud)

唯一可见的后果是使用级联汇总时 - 下面的示例在删除组键时仅生成一个汇总行。

mtcars %>% group_by(cyl, am) %>% summarise(avg_mpg = mean(mpg), .groups = "drop") %>% summarise(min_avg_mpg = min(avg_mpg))
# A tibble: 1 x 1
  min_avg_mpg
        <dbl>
1   15.0
Run Code Online (Sandbox Code Playgroud)

但由于分组属性都是可用的,因此在后续汇总之前根据需要重新设置分组应该不成问题。group_by(cyl, am)