如何用dplyr在R中按lesion_id合并REDCap导出的多行数据?
用dplyr合并REDCap导出的多行病灶数据
我从REDCap导出了一份数据,由于包含多个表单,不同表单的结果被分到不同行,但这些行隶属于同一个lesion_id和patient_id。我希望合并这些行,使每个lesion_id对应一行完整数据(部分患者有多个病灶)。尝试使用pivot_wider但效果不佳,请问用dplyr实现该需求的最佳方法是什么?
当前数据示例
library(tibble) library(tidyverse) data <- tribble( ~lesion_id, ~patient_id, ~complete, ~ct_finding, ~guess, ~malignancy, "747-1", 747, "complete", NA, NA, 0, "747-1", 747, NA, "lesion growth", NA, 0, "747-1", 747, NA, NA, "Non-Malignant", 0, "747-2", 747, "incomplete", NA, NA, 1, "747-2", 747, NA, "remission", NA, 1, "747-2", 747, NA, NA, "Non-Malignant", 1 )
期望数据格式
desired_data <- tribble( ~lesion_id, ~patient_id, ~complete, ~ct_finding, ~guess, ~malignancy, "747-1", 747, "complete", "lesion growth", "Non-Malignant", 0, "747-2", 747, "incomplete", "remission", "Non-Malignant", 1 )
解决方案
核心思路是按lesion_id和patient_id分组,提取每组内各字段的唯一非NA值。用dplyr的分组+汇总操作即可简洁实现:
library(dplyr) merged_data <- data %>% group_by(lesion_id, patient_id) %>% summarise(across(everything(), ~ first(na.omit(.x))), .groups = "drop")
代码说明
group_by(lesion_id, patient_id):将同一病灶的所有行归为一组,确保合并逻辑的准确性summarise(across(everything(), ~ first(na.omit(.x)))):遍历所有列,先剔除该列的NA值,再取第一个(也是唯一的)有效数据.groups = "drop":完成汇总后自动取消分组,返回常规数据框结构
执行后得到的merged_data与期望的desired_data完全一致。
你也可以用purrr的reduce()结合coalesce()实现相同效果,逻辑是将每组内的行逐列合并,自动保留非NA值:
library(purrr) library(dplyr) merged_data <- data %>% group_by(lesion_id, patient_id) %>% summarise(across(everything(), ~ reduce(.x, coalesce)), .groups = "drop")
内容的提问来源于stack exchange,提问作者John Ryan
相关产品推荐
相关产品推荐

