r语言 - 如何解释 dplyr消息"summarise()"按'x'重新分组输出(用".groups"参数覆盖)?



在更新到dplyr开发版本0.8.99.9003后,当运行group_by和summary()时,我开始收到一条新消息(请参阅文章标题)。

下面是一个重新创建输出的示例:

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

输出tibble是正确的,但显示以下消息:

summarise()按"年份"重新组合输出(用.groups参数覆盖)

应该如何解释?当我同时按年份和周分组时,为什么它只报告按"年"分组?此外,覆盖意味着什么?我为什么要这样做?

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

我相信这是一条新消息,因为它只出现在最近的SO问题上,比如如何使用dplyr融化成对的.wilcox.test输出?和R在多个列上聚合(这两个列都不处理重组/覆盖消息)。

谢谢!

这只是一条关于生成的分组结构的友好警告消息;你的输出是正确的。默认情况下,如果在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.

在这里,它放弃最后一个分组,并使用"am"重新组合

如果我们检查?summarise,则有.groups自变量,默认情况下为"drop_last",其他选项为"drop""keep""rowwise"

.groups-结果的分组结构。

"drop_last":放弃最后一级分组。这是1.0.0版本之前唯一支持的选项。

"drop":将删除所有级别的分组。

"保持":与.data.相同的分组结构

"按行":每一行都是自己的组。

如果没有指定.groups,则会得到";drop_ last";当所有结果都是大小1或"1"时;保持";如果大小变化。此外,一条消息通知您该选择,除非选项";dplyr.summary.info";设置为FALSE。

即,如果我们更改summarise中的.groups,则不会收到消息,因为组属性已删除

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中选择不同的选项。

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

summarise()已通过"xxx"对输出进行分组

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

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

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

警告是说,在输出中,使用默认.groups = "drop_last"只保留了原始分组密钥中的第一个。参见# Groups: cyl [3]行。

然而,属性是完整的,定义了cylam

这里是可用选项的快速概述,显示功能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

唯一可见的结果是在使用级联摘要时-下面的示例在删除组键时只生成一个摘要行。

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

但是,由于分组属性都可用,在随后的摘要之前,根据需要使用group_by(cyl, am)重置组密钥应该不是问题。

中解释了答案?总结:"如果未指定.groups,则会根据结果的行数进行选择:如果所有结果都有1行,则得到"1";drop_last";。如果行数不同,则得到"0";保持"&";。

基本上,当有多个选项用作.groups=参数时,就会收到这样的消息。该消息警告您,在计算上述条件下的统计数据时使用了一个选项:";drop_ last";或";保持";分别用于具有1行或多行的结果。假设在您的管道中,由于某种原因,您应用了两个或多个分组标准,但您仍然需要对所有值的数据进行汇总——无分组,这可以通过设置.group="drop"来完成。不幸的是,这只是理论上的,因为,正如你在@akrun的例子中看到的,无论在.group=中设置了哪个选项,统计值都保持不变(我将这些不同的选项应用于我的一个数据集,并获得了相同的结果和数据帧结构("分组结构由.group=参数控制…")。然而,通过指定参数.group,不打印任何消息。

底线是,当使用summary时,如果不使用分组标准,则会在所有行中计算输出统计信息,因此"结果有1行"。当使用一个或多个分组标准时,在每个组中计算输出统计信息,因此"行数变化"取决于数据帧中的组数。

要解决此问题,请使用summarise(avg_mpg = mean(mpg), .groups = "drop"),dplyr实际上将结果表解释为分组,这就是他向您显示警告的原因。

这在https://r4ds.hadley.nz/data-transform.html#grouping-通过多变量

当您汇总由多个变量分组的tibble时,每个汇总都会剥离最后一组事后看来,这不是使该函数工作的好方法,但在不破坏现有代码的情况下进行更改是很困难的为了清楚地表明发生了什么,dplyr显示了一条消息

当您有两个或多个分组列时,这可能是summarise_all()summarise(across(everything()...的结果

> tibble(gr1=c(1,1,2), gr2=c(1,1,2), val=1:3) %>% 
group_by(gr1, gr2) %>% 
summarise(across(everything(), mean))
#`summarise()` has grouped output by 'gr1'. 
# You can override using the #`.groups` argument.
# A tibble: 2 x 3
# Groups:   gr1 [2]
gr1   gr2   val
<dbl> <dbl> <dbl>
1     1     1   1.5
2     2     2   3

> tibble(gr1=c(1,1,2), gr2=c(1,1,2), val=1:3) %>% 
+     group_by(gr1, gr2) %>% 
+     summarise_all(mean)
# No warnings here
# A tibble: 2 x 3
# Groups:   gr1 [2]
gr1   gr2   val
<dbl> <dbl> <dbl>
1     1     1   1.5
2     2     2   3

因此,警告意味着:尽管有everything(),但在summary()中,一些列将被跳过(分组)

最新更新