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

如何用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)

输出表格:

NameMRNDays_till_PosDays_till_Neg
Doe, John55555NA1
Doe, Jane66666NA0
Parker, Peter77777NANA
Stark, Tony8888811

解决方案

使用dplyr包完成分组计算,步骤如下:

  1. 转换日期格式,标记阳性/阴性记录;
  2. 按人员分组提取关键日期(首次观测、首次阳性、首次阴性);
  3. 根据规则计算目标列数值;
  4. 整理得到每人唯一记录。

完整代码:

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 12:15:34