在R语言中按Study_ID填充患者特征缺失值的技术求助
解决方案:按患者ID填充NA值
你可以通过按Study_ID分组,将每个患者的非NA特征值复制到同ID的所有记录中,以下是两种常用实现方法:
先加载示例数据
首先把你提供的数据加载到R中:
patient.info <- structure(list(Study_ID = c(104, 104, 108, 108, 114, 114), Group = c("BS", NA, "BS", NA, "BS", NA), Group2 = c("MO", NA, "MO", NA, "MO", NA), Age = c(50.5, NA, 33.5, NA, 51.7, NA), Sex = c("F", NA, "F", NA, "F", NA), Sex2 = c(2L, NA, 2L, NA, 2L, NA), Ethnicity = c("A", NA, "D", NA, "C", NA), Eth2 = c("EW", NA, "AF M", NA, "EW", NA )), row.names = c(35L, 36L, 40L, 41L, 49L, 50L), class = "data.frame")
方法1:使用tidyverse(dplyr)
这是生物信息学中常用的tidy风格方法,代码简洁易读:
library(dplyr) # 按Study_ID分组,双向填充所有列的NA值 filled_data <- patient.info %>% group_by(Study_ID) %>% fill(everything(), .direction = "downup") %>% ungroup()
group_by(Study_ID):将数据按患者ID分组fill(everything(), .direction = "downup"):对所有列进行双向填充(不管NA在非NA值的上方还是下方,都会被替换为该分组的非NA值)ungroup():取消分组,恢复普通数据框结构
你也可以用更明确的取值方式,效果完全一致:
filled_data <- patient.info %>% group_by(Study_ID) %>% mutate(across(everything(), ~ ifelse(is.na(.), first(na.omit(.)), .))) %>% ungroup()
方法2:使用data.table
如果你的数据集很大(生物信息学常遇到这种情况),data.table的速度会更快:
library(data.table) # 将数据框转为data.table格式 setDT(patient.info) # 按Study_ID分组,替换NA为对应列的非NA值 filled_data <- patient.info[, lapply(.SD, function(x) { # 取当前列的第一个非NA值,替换所有NA x[is.na(x)] <- x[!is.na(x)][1] x }), by = Study_ID]
验证结果
运行后查看填充后的数据:
head(filled_data)
可以看到每个Study_ID的所有记录都已经填充了对应的特征值,NA被完全替换。
注意:如果某个患者的某列全为NA,填充后仍会保留NA(因为没有可用的特征值)
内容的提问来源于stack exchange,提问作者Elizabeth Mist
相关产品推荐
相关产品推荐

