R语言for循环+sapply返回全NA:疾病匹配逻辑列生成失败
问题排查与修正:基于UKbiobank DC码生成患病标记
错误原因分析
你的代码输出全为NA,核心问题有三个:
- 向量长度不匹配引发循环补齐:
for(i in datacodes)会遍历datacodes的每一列(整列向量),x==i是将patient_illness的列与整列DC向量逐行比较。当两者长度不一致时,R会触发循环补齐机制,不匹配的位置直接生成NA。 - 循环变量被重复覆盖:每次循环都会重新赋值
equality,最终仅保留最后一次循环的结果,无法累积所有DC码的匹配情况。 - 逻辑偏离需求:代码是逐列对应比较illness和DC码,但实际需求是患者的任意illness编码匹配任意DC码即判定患病,逐列比较的逻辑完全不符合目标。
修正后的代码实现
方案1:基础向量操作(高效简洁)
library(dplyr) # 读取数据 ccc <- read.table(file.choose(), header = TRUE, sep = ",") ccc2 <- ccc # 提取目标列 patient_illness <- select(ccc2, contains("illness")) datacodes <- select(ccc2, contains("DC")) # 将所有DC码整理为去重后的向量 dc_codes <- unique(unlist(datacodes)) # 生成患病标记:任意illness匹配DC码则为1,否则为0 ccc2$disease_flag <- ifelse(rowSums(sapply(patient_illness, function(x) x %in% dc_codes)) > 0, 1, 0)
方案2:dplyr管道式实现(可读性更强)
library(dplyr) ccc2 <- read.table(file.choose(), header = TRUE, sep = ",") %>% # 提取所有DC码并去重,存储为列表列 mutate(dc_codes = list(unique(unlist(select(., contains("DC")))))) %>% # 按行判断是否有illness编码匹配DC码 rowwise() %>% mutate( disease_flag = ifelse(any(c_across(contains("illness")) %in% unlist(dc_codes)), 1, 0) ) %>% ungroup() %>% # 移除临时列(可选) select(-dc_codes)
关键逻辑说明
unlist(datacodes):将所有DC列合并为一个长向量,实现“匹配任意DC码”的判断基础。x %in% dc_codes:判断单个illness编码是否存在于DC码集合中,返回布尔值,相比==更适合多值匹配场景。rowSums(...) > 0:统计每行中匹配成功的illness列数量,只要有1个及以上匹配就标记为患病。
内容的提问来源于stack exchange,提问作者hoon99
相关产品推荐
相关产品推荐

