多分组列含NA时dplyr的group_by+summarise丢失NA行问题
问题:dplyr分组汇总时丢失含NA的行
问题重现
使用dplyr对包含NA的多列分组后汇总,示例代码如下:
df <- data.frame(ID1 = c(1,2,3,4,5), ID2 = c(11, NA, 13, NA, 14), ID3 = c(1,2,3,4,5), value = c(110, 120, 130, 140, 150)) test <- df %>% group_by(ID1, ID2, ID3) %>% summarise(value=sum(value))
期望输出与实际输出
期望输出
ID1 ID2 ID3 value 1 11 1 110 2 NA 2 120 3 13 3 130 4 NA 4 140 5 14 5 150
实际输出(9个分组ID列时)
ID1 ID2 ID3 value 1 11 1 110 3 13 3 130 5 14 5 150
注:上述示例代码可得到期望输出,但9个分组ID列的代码会排除含NA的行,此前类似场景未出现该问题。
当前临时解决方法
通过将NA替换为字符"NA",汇总后再还原的方式处理:
df <- data.frame(ID1 = c(1,2,3,4,5), ID2 = c(11, NA, 13, NA, 14), ID3 = c(1,2,3,4,5), value = c(110, 120, 130, 140, 150)) test <- df %>% mutate(ID2 = ifelse(is.na(ID2), "NA", ID2)) %>% group_by(ID1, ID2, ID3) %>% summarise(value=sum(value)) %>% mutate(ID2 = ifelse(ID2 == "NA", NA, ID2))
原因分析与最优解决方案
原因分析
- dplyr版本差异:最可能的原因是使用的dplyr版本低于1.0.0。在dplyr 1.0.0之前,多列分组场景下
group_by()默认会意外排除包含NA的分组;而1.0.0及之后的版本默认保留NA分组(.na.rm = FALSE)。 - 列类型问题:如果实际数据中NA所在的分组列为因子类型,因子的NA处理逻辑会导致分组时被排除。
最优解决方案
方案1:升级dplyr版本
将dplyr升级到1.0.0及以上版本,无需修改现有代码,group_by()会默认保留含NA的分组,直接得到期望输出。方案2:显式设置分组参数(适配旧版本)
如果无法升级版本,在group_by()中显式设置参数保留NA分组:- 对于dplyr 0.8.x及更早版本,使用
keep.na = TRUE:test <- df %>% group_by(ID1, ID2, ID3, ..., keep.na = TRUE) %>% summarise(value=sum(value)) - 对于dplyr 1.0.0及以上版本,可显式指定
.na.rm = FALSE(默认值,可省略):test <- df %>% group_by(ID1, ID2, ID3, ..., .na.rm = FALSE) %>% summarise(value=sum(value))
- 对于dplyr 0.8.x及更早版本,使用
方案3:处理因子类型分组列
如果分组列为因子类型,先将其转换为字符或数值列后再分组:test <- df %>% mutate(across(c(ID2, ...), as.character)) %>% # 或as.numeric,根据实际类型选择 group_by(ID1, ID2, ID3, ...) %>% summarise(value=sum(value))
内容的提问来源于stack exchange,提问作者Ismail Arslan
相关产品推荐
相关产品推荐

