如何按record_id和event_name合并数据表?解决merge重复列问题
问题描述
现有数据表结构如下:
| record_id | event_name | lab_value_1 | lab_value_2 | lab_value_3 | lab_value_4 |
|---|---|---|---|---|---|
| ID 1 | t0 | 0.1 | 0.1 | 0.1 | 0.1 |
| ID 2 | t1 | 0.2 | 0.2 | 0.2 | 0.2 |
| ID 2 | t2 | 0.3 | 0.3 | 0.3 | NA |
需要合并三类外部数据集:
- A) 补充现有记录缺失值
| record_id | event_name | lab_value_1 | lab_value_2 | lab_value_3 | lab_value_4 |
|---|---|---|---|---|---|
| ID 2 | t2 | NA | NA | NA | 0.5 |
- B) 新增record_id
| record_id | event_name | lab_value_1 | lab_value_2 | lab_value_3 | lab_value_4 |
|---|---|---|---|---|---|
| ID 3 | t0 | 0.1 | 0.2 | 0.3 | 0.5 |
- C) 为现有记录新增时间点
| record_id | event_name | lab_value_1 | lab_value_2 | lab_value_3 | lab_value_4 |
|---|---|---|---|---|---|
| ID 2 | t3 | 0.1 | 0.2 | 0.3 | 0.5 |
重要提示:不同数据框的列顺序可能不同!
需求:当record_id和event_name同时匹配时,用新数据填补旧数据的缺失值;不匹配时新增行。使用merge函数后出现了重复列(如lab_ldl.x、lab_ldl.y),未实现合并到原列的效果,测试示例如下:
old_data record_id redcap_event_name lab_ldl lab_ggt lab_cpept lab_alat lab_asat lab_hba1c 1 ADI757106 t3_arm_1 0.12 0.51 NA NA NA NA 2 ADI123456 t1_arm_1 NA NA 0.133 0.155 47.3 NA new_data record_id redcap_event_name lab_ldl lab_hba1c 1 ADI123456 t1_arm_1 1 5 merge(old_data, new_data, by = c("record_id", "redcap_event_name"), all = TRUE, sort = TRUE) record_id redcap_event_name lab_ldl.x lab_ggt lab_cpept lab_alat lab_asat lab_hba1c.x lab_ldl.y lab_hba1c.y 1 ADI123456 t1_arm_1 NA NA 0.133 0.155 47.3 NA 1 5 2 ADI757106 t3_arm_1 0.12 0.51 NA NA NA NA NA NA
解决方案
方法1:Base R 实现
先合并数据,再对重复列进行合并,保留非NA值:
# 合并数据 merged_data <- merge(old_data, new_data, by = c("record_id", "redcap_event_name"), all = TRUE) # 获取所有非合并键的列名,提取原始列前缀 non_key_cols <- setdiff(colnames(merged_data), c("record_id", "redcap_event_name")) original_cols <- unique(sub("\\.(x|y)$", "", non_key_cols)) # 遍历每个原始列,合并x和y列的非NA值 for(col in original_cols) { merged_data[[col]] <- ifelse(is.na(merged_data[[paste0(col, ".x")]]), merged_data[[paste0(col, ".y")]], merged_data[[paste0(col, ".x")]]) # 删除临时的x和y列 merged_data[c(paste0(col, ".x"), paste0(col, ".y"))] <- NULL } # 查看结果 merged_data
方法2:tidyverse 工具包实现
用dplyr的bind_rows结合group_by和coalesce更简洁,自动处理列顺序问题:
library(dplyr) # 合并数据并按分组键聚合,用coalesce填补NA merged_data <- bind_rows(old_data, new_data) %>% group_by(record_id, redcap_event_name) %>% summarise(across(everything(), ~coalesce(!!!.)), .groups = "drop") # 查看结果 merged_data
方法说明
bind_rows会自动对齐列,不管列顺序如何,缺失的列会补NAgroup_by(record_id, redcap_event_name)把相同记录的行分组across(everything(), ~coalesce(!!!.))对每一列,用coalesce函数取第一个非NA值,实现缺失值填补
内容的提问来源于stack exchange,提问作者Eric G
相关产品推荐
相关产品推荐

