在R中跨多列匹配ICD编码前缀并生成年度二值指标
R实现ICD编码前缀匹配并生成年度疾病二值列
步骤1:加载所需工具包
我们用tidyverse套件来处理数据,它包含了数据清洗、转换的核心工具:
library(tidyverse)
步骤2:整理疾病编码映射表
先把分散的疾病ICD前缀列表整合到一个统一的数据框里,方便后续批量匹配:
# 定义各类疾病的ICD前缀 cancer <- c("C34", "C50", "C61", "C91") cvd <- c("I21", "I50", "I63", "I74") diabetes <- c("E10", "E11", "E13", "E14") respiratory <- c("J40", "J45", "J47", "J98") # 整合成映射表 disease_mapping <- tibble( disease_type = c(rep("cancer", length(cancer)), rep("cvd", length(cvd)), rep("diabetes", length(diabetes)), rep("respiratory", length(respiratory))), icd_prefix = c(cancer, cvd, diabetes, respiratory) )
步骤3:标记每行住院事件的疾病类型
把宽格式的诊断列转成长格式,用前缀匹配找到对应的疾病类型,再转回宽格式标记每行是否患有该类疾病:
# 示例数据集(实际替换成你的数据即可) dat <- data.frame( id = c(1, 1, 1, 2, 3, 3, 4, 5, 5), year = c(2014, 2015, 2020, 2015, 2016, 2014, 2015, 2014, 2017), diagnosis1 = c("I21", "C50", "E10", "J40", "E119", "I210", "I50", "I63", "J45"), diagnosis2 = c("I50", "C34", "E11", "J45", NA, NA, NA, NA, NA), diagnosis3 = c("I63", "C61", "E14", "J98", NA, NA, NA, NA, NA) ) # 转长格式处理诊断列 diagnosis_long <- dat %>% select(id, year, starts_with("diagnosis")) %>% pivot_longer(cols = starts_with("diagnosis"), names_to = "diagnosis_col", values_to = "icd_code", values_drop_na = TRUE) %>% # 前缀匹配:检查ICD编码是否以目标前缀开头 left_join(disease_mapping, by = character()) %>% filter(str_starts(icd_code, icd_prefix)) %>% select(id, year, disease_type) %>% distinct() %>% # 同一住院事件同一疾病只保留一条记录 mutate(has_disease = 1) %>% # 转回宽格式,标记每行是否有对应疾病 pivot_wider(names_from = disease_type, values_from = has_disease, values_fill = 0) # 合并回原数据集,补全未匹配到疾病的行(标记为0) dat_with_disease <- dat %>% left_join(diagnosis_long, by = c("id", "year")) %>% replace_na(list(cancer = 0, cvd = 0, diabetes = 0, respiratory = 0))
步骤4:生成所有年份的二值列
定义目标年份范围(1968-2020),为每个疾病类型和年份生成专属列,判断当前行的住院年份是否匹配且患有对应疾病:
# 定义目标年份范围 target_years <- 1968:2020 # 生成所有疾病-年份组合的列名 disease_year_combinations <- expand_grid( disease_type = c("cancer", "cvd", "diabetes", "respiratory"), year = target_years ) %>% mutate(col_name = str_c(disease_type, "_", year)) # 批量生成二值列 final_dat <- dat_with_disease %>% mutate(!!!map(set_names(disease_year_combinations$col_name, disease_year_combinations$col_name), ~ifelse(year == disease_year_combinations$year[disease_year_combinations$col_name == .x] & get(disease_year_combinations$disease_type[disease_year_combinations$col_name == .x]) == 1, 1, 0))) %>% # 调整列顺序,把原始列放在前面 select(id, year, starts_with("diagnosis"), everything())
验证结果
可以查看处理后的示例数据,确认格式和预期一致:
# 仅显示2014-2020的列(示例年份范围) final_dat %>% select(id, year, diagnosis1:diagnosis3, ends_with(as.character(2014:2020)))
注意事项
- 实际数据中的31个诊断列,
starts_with("diagnosis")会自动匹配所有以diagnosis开头的列,无需修改代码。 - 如果ICD编码存在大小写不一致的情况,可以用
str_to_upper(icd_code)统一格式后再匹配。 - 若需要调整年份范围,直接修改
target_years即可。
内容的提问来源于stack exchange,提问作者user25809482
相关产品推荐
相关产品推荐

