如何在R中按分组取众数替换NA值,保留无有效值的NA
问题描述
原始数据框:
| x | y | Owner | H |
|---|---|---|---|
| 1 | 2 | A | 1 |
| 2 | 5 | A | NA |
| 2 | 2 | A | 5 |
| 2 | 5 | A | 4 |
| 2 | 5 | B | 4 |
| 2 | 5 | C | 3 |
| 3 | 3 | C | 6 |
| 3 | 3 | C | NA |
| 3 | 3 | D | NA |
需按(x,y,Owner)分组,将H列的NA值替换为对应组内H的众数;若分组内仅含NA值,保留NA。目标结果如下:
| x | y | Owner | H |
|---|---|---|---|
| 1 | 2 | A | 1 |
| 2 | 5 | A | 4 |
| 2 | 2 | A | 5 |
| 2 | 5 | A | 4 |
| 2 | 5 | B | 4 |
| 2 | 5 | C | 3 |
| 3 | 3 | C | 6 |
| 3 | 3 | C | 6 |
| 3 | 3 | D | NA |
尝试的代码存在问题,会替换所有H值而非仅NA值:
new_data <- my_data %>% group_by('Owner', 'x', 'y') %>% mutate(H=mean(H, na.rm=TRUE))
解决方案
步骤1:定义众数计算函数
R没有内置众数函数,自定义函数处理全NA分组的情况:
get_mode <- function(x) { x_non_na <- x[!is.na(x)] if (length(x_non_na) == 0) { return(NA) } freq <- table(x_non_na) mode_val <- names(freq)[freq == max(freq)] as.numeric(mode_val[1]) # 多众数时取第一个,可按需调整 }
步骤2:用dplyr处理数据
library(dplyr) new_data <- my_data %>% group_by(Owner, x, y) %>% # 正确分组,列名无需加引号 mutate(H = ifelse(is.na(H), get_mode(H), H)) %>% # 仅替换NA值 ungroup()
说明
- 分组时不要给列名加引号,否则会把字符串当作分组变量而非列名
ifelse(is.na(H), get_mode(H), H)确保仅替换NA值,非NA值保留原样- 自定义的
get_mode函数会在分组全为NA时返回NA,符合需求
内容的提问来源于stack exchange,提问作者M S
相关产品推荐
相关产品推荐

