You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

循环中使用dplyr的group_by_at/summarise_at后如何保留空组?

解决dplyr分组后保留空组的问题

我来帮你搞定这个困扰!你遇到的核心问题是:使用group_by_at()分组时,dplyr默认会丢弃没有数据的空组,之后用complete()补全时又因为索引的问题找不到正确的分组变量取值范围。这里有几个实用的解决办法:

方法1:分组时直接保留空组(最推荐)

dplyr的分组函数(包括group_by_at())有一个.drop=FALSE参数,设置它就能在分组阶段直接保留所有可能的分组,不管该组有没有数据。这样后续汇总后就不会丢失空组,再用complete()补全缺失列就很顺畅了:

library(dplyr)
library(tidyr) # 推荐用tidyr的complete,功能更完善

df2 <- mtcars %>%
  # 按第10列分组,同时保留所有空组
  group_by_at(vars(10), .drop = FALSE) %>%
  # 汇总第1列的均值,同时取消分组(.groups="drop")
  summarise_at(vars(1), mean, na.rm = TRUE, .groups = "drop") %>%
  # 补全gear的所有组,给Gewicht列填充默认值1
  complete(gear, fill = list(Gewicht = 1))

df2

如果你用的是较新版本的dplyr(1.0.0+),更推荐用across()替代group_by_at()和summarise_at(),写法更直观:

df2 <- mtcars %>%
  group_by(across(10), .drop = FALSE) %>%
  summarise(Mittelwert = mean(across(1), na.rm = TRUE), .groups = "drop") %>%
  complete(gear, fill = list(Gewicht = 1))

方法2:补全时指定分组变量的所有可能值

如果不想修改分组逻辑,也可以在complete()里明确指定分组变量的所有取值范围,直接从原始数据中获取:

df2 <- mtcars %>%
  group_by_at(10) %>%
  summarise_at(1, mean, na.rm = TRUE) %>%
  # 明确gear的取值为原始mtcars中所有存在的gear值
  complete(gear = unique(mtcars$gear), fill = list(Gewicht = 1))

为什么你的原始代码不行?

你原来的complete(gear, ...)之所以没生效,是因为经过group_by_at()和summarise_at()后,空组已经被丢弃了,此时结果里的gear列只有有数据的取值,complete()不知道要补哪些空组。而上面两种方法要么从源头保留空组,要么告诉complete()所有可能的分组取值,就能解决问题啦。

内容的提问来源于stack exchange,提问作者user7353167

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 10:09:33