R语言数据整理:按gene合并行并保留所有值(含NA)
按基因合并行并保留非NA值的dplyr解决方案
问题背景
现有如下结构的数据集:
| gene | sample1 | sample2 | sample3 | |
|---|---|---|---|---|
| 1 | A | 0.2 | NA | NA |
| 2 | B | 0.1 | NA | NA |
| 3 | C | -0.3 | NA | NA |
| 4 | A | NA | -0.3 | NA |
| 5 | B | NA | 0.5 | NA |
| 6 | C | NA | NA | NA |
| 7 | A | NA | NA | NA |
| 8 | B | NA | NA | 0.2 |
| 9 | C | NA | NA | -0.5 |
需求是按gene字段合并行,保留每个样本列对应基因的唯一非NA值(每个基因-样本组合最多一个非NA值),最终得到目标数据集。原数据规模为400个样本列、500万行,使用以下dplyr代码时出现数据丢失问题:
df %>% group_by(gene) %>% summarize(across(everything(), ~ ifelse(all(is.na(.x)), NA, max(.x, na.rm = FALSE))))
原代码问题分析
原代码中max(.x, na.rm = FALSE)的逻辑错误:只要向量中存在NA,max在na.rm=FALSE时会直接返回NA,导致原本存在的非NA值被覆盖,最终出现数据丢失。
正确的dplyr解决方案
方案1:使用coalesce(推荐,高效)
利用dplyr::coalesce合并组内的列值,它会自动返回第一个非NA值,完美匹配需求(全NA时返回NA,有非NA时返回该值):
library(dplyr) df %>% group_by(gene) %>% summarize(across(everything(), ~ coalesce(!!!.x)))
解释:!!!.x将组内当前列的所有值展开为coalesce的参数,coalesce会逐个检查并返回第一个非NA值,完全符合每个基因-样本组合仅一个非NA值的场景。
方案2:使用first结合na.omit
如果确认每个基因-样本组合最多一个非NA值,也可以用以下方式提取非NA值:
df %>% group_by(gene) %>% summarize(across(everything(), ~ first(na.omit(c(.x, NA)))))
解释:na.omit(c(.x, NA))提取组内当前列的非NA值,额外添加NA是为了避免全NA时na.omit返回空向量,first取第一个值(即唯一的非NA值或NA)。
大数据量优化建议
针对500万行的超大数据量,除了dplyr方案,还可以用data.table实现更高效的处理(内存占用更低、速度更快):
library(data.table) setDT(df)[, lapply(.SD, fcoalesce), by = gene]
验证结果
运行上述代码后,将得到预期的合并结果:
| gene | sample1 | sample2 | sample3 | |
|---|---|---|---|---|
| 1 | A | 0.2 | -0.3 | NA |
| 2 | B | 0.1 | 0.5 | 0.2 |
| 3 | C | -0.3 | NA | -0.5 |
内容的提问来源于stack exchange,提问作者eb0906
相关产品推荐
相关产品推荐

