You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何简洁地在R数据集中提取最早诊断记录及对应编码?

问题

我有一个R数据集,需要确定每个ID对应的最早疾病诊断及关联编码。当前数据集的首个疾病编码并不总是对应最早诊断(如ID 1005所示)。数据集示例如下:

df = data.frame(ID = c(1001, 1002, 1003, 1004, 1005),
                Disease_code_1 = c('I802', 'G200','I802',NA, 'H356'),
                Disease_code_2 = c('A071',NA,'G20',NA,'I802'),
                Disease_code_3 = c('H250', NA,NA,NA,NA),
                Date_of_diagnosis_1 = c('12/06/1997','13/06/1997','14/02/2003',NA,'18/03/2005'),
                Date_of_diagnosis_2 = c('12/06/1998',NA,'18/09/2001',NA,'12/07/1993'),
                Date_of_diagnosis_3 = c('17/09/2010',NA,NA,NA,NA))

我目前通过创建多个子集、行绑定后筛选最早诊断的方式实现需求,代码如下:

Disease_1 <- as.data.frame((cbind(df$ID, df$Disease_code_1, df$Date_of_diagnosis_1)))
Disease_2 <- as.data.frame((cbind(df$ID, df$Disease_code_2, df$Date_of_diagnosis_2)))
Disease_3 <- as.data.frame((cbind(df$ID, df$Disease_code_3, df$Date_of_diagnosis_3)))

Disease_data <- rbind(Disease_1, Disease_2, Disease_3)
colnames(Disease_data) = c("id","Disease_code","Date_of_diagnosis")

#筛选每个参与者的最早诊断记录
Disease_data <- Disease_data [order(Disease_data [,'id'],Disease_data [,'Date_of_diagnosis']),]
Disease_data <- Disease_data [!duplicated(Disease_data $id),]

但实际数据中有25组类似的疾病编码与诊断日期变量对,当前方法代码冗余。我想知道是否可以使用startsWith命令来简化代码,此前尝试未成功。

解决方案

方法一:基础R结合startsWith实现

完全用基础R的startsWith批量识别目标列,避免手动重复创建子集,步骤如下:

  1. 用startsWith筛选所有疾病编码和诊断日期列,搭配ID列构建长格式数据
  2. 清理缺失值并转换日期格式
  3. 按ID排序后筛选最早诊断记录

代码示例:

# 提取ID列、所有疾病编码列、所有诊断日期列
id_col <- df$ID
disease_cols <- df[, startsWith(colnames(df), "Disease_code_")]
date_cols <- df[, startsWith(colnames(df), "Date_of_diagnosis_")]

# 转换为长格式:每个ID的每组诊断对应一行
long_data <- data.frame(
  ID = rep(id_col, ncol(disease_cols)),
  Disease_code = as.vector(as.matrix(disease_cols)),
  Date_of_diagnosis = as.vector(as.matrix(date_cols))
)

# 清理缺失值,转换日期格式(注意是日/月/年的格式)
long_data <- long_data[!is.na(long_data$Disease_code) & !is.na(long_data$Date_of_diagnosis), ]
long_data$Date_of_diagnosis <- as.Date(long_data$Date_of_diagnosis, format = "%d/%m/%Y")

# 按ID和诊断日期排序,保留每个ID的第一条记录(即最早诊断)
long_data <- long_data[order(long_data$ID, long_data$Date_of_diagnosis), ]
result <- long_data[!duplicated(long_data$ID), ]

print(result)

方法二:tidyverse工具简化(更直观)

如果习惯使用tidyverse生态,pivot_longer可以更高效地完成数据重塑,代码更简洁:

library(tidyverse)

result <- df %>%
  # 将多组疾病编码/日期列转为长格式
  pivot_longer(
    cols = -ID,
    names_to = c(".value", "group"),
    names_pattern = "(Disease_code|Date_of_diagnosis)_(\\d+)"
  ) %>%
  # 去除含缺失值的记录
  drop_na(Disease_code, Date_of_diagnosis) %>%
  # 转换日期格式
  mutate(Date_of_diagnosis = as.Date(Date_of_diagnosis, format = "%d/%m/%Y")) %>%
  # 按ID和日期排序
  arrange(ID, Date_of_diagnosis) %>%
  # 保留每个ID的第一条记录
  distinct(ID, .keep_all = TRUE)

print(result)

两种方法都能适配25组变量的场景,无需手动重复编写子集代码。

内容的提问来源于stack exchange,提问作者Nic

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 00:07:12