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

如何处理含日期的复杂变量:计算眼部影像随访年数

问题描述

我有一个tibble,每行代表一张眼部影像,包含变量:patientId、laterality(左/右)、date、imageId。需要将其处理为另一个tibble,展示每只眼睛(按patientId、laterality分组)的followUpYears,规则如下:

  • 要满足某一年的随访要求,该年度内必须有两个不同的影像日期:第1年为基线日起0-365天,第2年为366-730天,以此类推,followUpYears为整数。
  • 同一日期仅计一次影像。
  • 一旦某一年不满足“两个影像日期”的要求,随访即终止:若第1年仅1个影像日期,无论后续有多少影像,followUpYears均为0。
  • 眼睛拥有n年随访,不要求首次与末次影像日期间隔至少n年。

示例数据:

data <- tibble(patientId = c('A','A','A','A','A','A','B','B','B','B','B','B','B'),
               laterality = c('L','L','L','L','L','L','R','R','R','R','L','L','L'),
               date = as.Date(c('2000-05-05','2000-05-05','2001-05-06','2001-05-07','2002-05-06','2002-05-07','2000-09-08','2001-09-07','2001-09-09','2001-09-10','2000-09-08','2001-09-07','2001-09-10')),
               imageId = 1:13)

期望输出:

expected_output <- tibble(patientId = c('A','B','B'),
                 laterality = c('L','R','L'),
                 followUpYears = c(0, 2, 1)) 

患者A左眼followUpYears为0(符合规则2、3);患者B右眼为2(符合规则4);患者B左眼为1(第2年未满足要求)。熟悉基础dplyr动词,但不知如何构建该变量,患者可能单眼/双眼纳入,部分随访超10年,忽略闰年按每年365天计算,求解决方案。


解决方案

可以通过分组去重、计算随访年份区间、逐年份验证条件,最终确定连续满足要求的最大随访年份数。代码如下:

library(dplyr)
library(tidyr)

result <- data %>%
  # 按患者+眼别分组,去除同一日期的重复影像
  group_by(patientId, laterality) %>%
  distinct(date, .keep_all = TRUE) %>%
  # 计算每个日期与基线(本组最早日期)的间隔天数
  mutate(baseline = min(date),
         days_since_baseline = as.numeric(date - baseline)) %>%
  # 划分该日期所属的随访年份(第1年=0-365天,以此类推)
  mutate(year = floor(days_since_baseline / 365) + 1) %>%
  # 统计每个年份的不同日期数量
  count(year) %>%
  # 补全连续的年份序列,避免遗漏中间未满足要求的年份
  complete(year = seq(1, max(year, na.rm = TRUE)), fill = list(n = 0)) %>%
  # 标记年份是否满足要求,并找到第一个不满足的年份位置
  mutate(meets_requirement = n >= 2,
         first_fail = which(!meets_requirement)[1] %||% (n() + 1)) %>%
  # 根据规则计算最终随访年份
  summarise(followUpYears = ifelse(first_fail == 1, 0, first_fail - 1)) %>%
  ungroup()

# 查看结果
result

代码说明

  1. 日期去重:使用distinct(date, .keep_all = TRUE)去掉同一日期的重复影像,符合规则2。
  2. 基线与天数计算:以每组最早日期为基线,计算各日期到基线的间隔天数,为划分年份做准备。
  3. 随访年份划分:通过floor(days_since_baseline / 365) + 1将日期映射到对应的随访年份。
  4. 年份日期数统计:用count(year)统计每个年份的有效日期数,再通过complete补全连续年份,确保不会漏掉中间未满足要求的年份。
  5. 结果计算:标记每个年份是否满足“至少2个不同日期”的要求,找到第一个不满足的年份位置:
    • 若第一个不满足的是第1年,followUpYears为0;
    • 否则,followUpYears为第一个不满足年份减1,即连续满足要求的最大年份数。

运行代码后结果与期望输出一致:

# A tibble: 3 × 3
  patientId laterality followUpYears
  <chr>     <chr>              <dbl>
1 A         L                      0
2 B         L                      1
3 B         R                      2

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 01:31:18