如何用R计算正负检测结果间隔天数并新增对应列
问题:处理混合数值与字符串的Result列,按MRN分组计算日期差
我曾寻找相关解决方案,但未找到适用于同时包含数值与字符串的Result列的方法。我的数据如下:
Name <- c("Doe, John","Doe, John","Doe, John", "Doe, Jane", "Doe, Jane","Doe, Jane","Parker, Peter","Parker, Peter","Parker, Peter", "Stark, Tony","Stark, Tony","Stark, Tony") Accession <- c(123, 234, 345, 456, 567, 678, 789, 8910, 1023, 1134, 1567, 1769) MRN <-c(55555, 55555, 55555, 66666, 66666, 66666, 77777, 77777, 77777, 88888, 88888, 88888) Collected <-c("2022-01-05", "2022-01-06", "2022-01-07", "2022-01-08", "2022-01-09", "2022-01-10", "2022-01-11", "2022-01-12", "2022-01-13", "2022-01-14", "2022-01-15", "2022-01-16") Result <-c(137, "Not Detected", 356, 1025, 1405, 538, "Not Detected", "Not Detected", "Not Detected", "Not Detected", 137, "Not Detected") CV <- data.frame(Name, Accession, MRN, Collected, Result)
我有多条同一人员的观测记录(每人最多可达100条),希望按MRN分组实现以下需求:
- 新增
Days_till_Pos列:计算从首次观测日期到首次阳性结果日期的天数,若首次结果即为阳性则填NA; - 新增
Days_till_Neg列:计算从首次阳性结果日期到首次阴性(Result为"Not Detected")结果日期的天数,若无阳性结果则填NA。
注:Result列中数值视为阳性,"Not Detected"视为阴性。
期望输出如下:
Name<- c("Doe, John","Doe, Jane","Parker, Peter", "Stark, Tony") MRN<- c(55555, 66666, 77777, 88888) Days_till_Pos<- c(NA, NA, NA, 1) Days_till_Neg<- c(1,0,NA, 1) CV1<- data.frame(Name, MRN, Days_till_Pos, Days_till_Neg)
输出表格:
| Name | MRN | Days_till_Pos | Days_till_Neg |
|---|---|---|---|
| Doe, John | 55555 | NA | 1 |
| Doe, Jane | 66666 | NA | 0 |
| Parker, Peter | 77777 | NA | NA |
| Stark, Tony | 88888 | 1 | 1 |
解决方案
使用dplyr包完成分组计算,步骤如下:
- 转换日期格式,标记阳性/阴性记录;
- 按人员分组提取关键日期(首次观测、首次阳性、首次阴性);
- 根据规则计算目标列数值;
- 整理得到每人唯一记录。
完整代码:
library(dplyr) CV_processed <- CV %>% # 转换日期类型,标记阳性状态 mutate( Collected = as.Date(Collected), is_positive = !Result %in% "Not Detected" ) %>% # 按MRN和Name分组,提取关键日期 group_by(MRN, Name) %>% summarise( first_obs_date = min(Collected), first_pos_date = min(Collected[is_positive], na.rm = TRUE), first_neg_date = min(Collected[!is_positive], na.rm = TRUE), .groups = "drop" ) %>% # 计算Days_till_Pos:首次观测到首次阳性的天数,首次即阳性填NA mutate( Days_till_Pos = ifelse(first_obs_date == first_pos_date, NA, as.integer(first_pos_date - first_obs_date)), # 计算Days_till_Neg:首次阳性到首次阴性的天数,无阳性填NA,同日期填0 Days_till_Neg = ifelse(is.infinite(first_pos_date), NA, as.integer(first_neg_date - first_pos_date)) ) %>% # 处理无阳性/阴性导致的Inf值,转为NA mutate( first_pos_date = ifelse(is.infinite(first_pos_date), NA, first_pos_date), first_neg_date = ifelse(is.infinite(first_neg_date), NA, first_neg_date), Days_till_Pos = ifelse(is.infinite(Days_till_Pos), NA, Days_till_Pos) ) %>% # 保留目标列 select(Name, MRN, Days_till_Pos, Days_till_Neg) print(CV_processed)
代码说明
is_positive:通过判断Result是否为"Not Detected"标记阳性记录;first_pos_date:分组后最早的阳性日期,无阳性时返回Inf,后续转为NA;Days_till_Pos:首次观测与首次阳性日期相同时,说明首次结果就是阳性,填NA;否则计算天数差;Days_till_Neg:无阳性记录时填NA;若阳性与阴性日期相同,天数差为0,否则计算两者差值。
运行代码后输出结果与期望一致。
内容的提问来源于stack exchange,提问作者T.McMillen
相关产品推荐
相关产品推荐

