如何按sample汇总数据行并替换NA?存在矛盾值时保留原行
问题描述
我正在处理一个每个sample对应多行数据的数据集,每行代表一次测量结果。由于并非每次测量都采集了所有数据,数据中存在大量NA值:
sample <- c("sample1", "sample1", "sample2", "sample2", "sample3", "sample3") value1<- c(1, 5, 7, NA, NA, 3) value2 <- c(1, 5, 5, NA, NA, 5) value3 <- c(13, NA, 7, NA, NA, NA) myinput <- data.frame(sample, value1, value2, value3)
查看原始数据集:
> myinput sample value1 value2 value3 1 sample1 1 1 13 2 sample1 5 5 NA 3 sample2 7 5 7 4 sample2 NA NA NA 5 sample3 NA NA NA 6 sample3 3 5 NA
需求说明:
- 按
sample对行进行汇总,用同sample下的非NA值填充对应变量的NA; - 若同一sample的行存在矛盾值(比如sample1的
value1同时有1和5两个不同非NA值),则不做汇总,保留所有非全NA的原始行; - 最终期望输出:
> myoutput sample value1 value2 value3 1 sample1 1 1 13 2 sample1 5 5 NA 3 sample2 7 5 7 4 sample3 3 5 NA
编辑:针对margusl的问题,修改了示例。若存在矛盾值(如sample1),保留原行。
解决方案
使用dplyr包可以简洁实现需求,步骤如下:
- 先加载
dplyr包:
library(dplyr)
- 编写处理代码:
myoutput <- myinput %>% # 标记每个sample是否存在变量矛盾(任意变量有多个不同非NA值) group_by(sample) %>% mutate(has_conflict = any(c_across(starts_with("value")) %>% map_lgl(~n_distinct(., na.rm = TRUE) > 1))) %>% ungroup() %>% # 分情况处理有/无矛盾的sample group_by(sample, has_conflict) %>% group_modify(function(.data, .key) { if (.key$has_conflict) { # 有矛盾:保留所有非全NA的行 .data %>% filter(rowSums(is.na(.[-1])) != ncol(.[-1])) } else { # 无矛盾:用同sample的非NA值填充NA,然后去重得到唯一行 .data %>% mutate(across(starts_with("value"), ~ifelse(is.na(.), first(na.omit(.)), .))) %>% distinct() } }) %>% ungroup() %>% select(-has_conflict) # 移除辅助标记列
- 查看结果:
> myoutput # A tibble: 4 × 4 sample value1 value2 value3 <chr> <dbl> <dbl> <dbl> 1 sample1 1 1 13 2 sample1 5 5 NA 3 sample2 7 5 7 4 sample3 3 5 NA
内容的提问来源于stack exchange,提问作者Nereus
相关产品推荐
相关产品推荐

