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

R语言:日期区间分类并补全enrollment/non-enrollment时段行

生成指定时间范围内的 Enrollment 状态区间解决方案

针对你需要处理的5万条id的enrollment数据集,我用R来给你一套可落地的实现方案,既能应对大规模数据(只要内存足够),又能精准生成指定时间范围内的状态区间和分类标签:

步骤1:加载依赖包

我们需要用到dplyr做数据分组和操作,lubridate处理日期类型:

library(dplyr)
library(lubridate)

步骤2:准备数据

先把你的示例数据转换成标准的日期格式数据框,实际使用时替换成你的真实数据集即可:

# 示例数据(替换为你的真实数据集)
df <- tibble(
  id = c(1,3,3,3,5,5),
  entry_date = c(NA, '1996-05-09', '2005-12-12', '2013-12-19', '2011-11-05','2012-12-10'),
  exit_date = c(NA, '2005-12-10', '2008-12-10', '2016-01-01', '2016-09-01', '2013-02-20')
) %>%
  # 将字符型日期转换为lubridate日期类型,NA值保留
  mutate(
    entry_date = ymd(entry_date),
    exit_date = ymd(exit_date)
  )

步骤3:定义时间范围

按照你的需求设置目标时间范围,这里可以根据实际情况调整:

# 指定目标时间范围
start_range <- ymd('2001-06-01')
end_range <- ymd('2015-01-01') # 若要匹配你示例中的2016结束日期,改为ymd('2016-01-01')即可

步骤4:生成状态区间和分类

核心逻辑是对每个id整理关键时间点,生成连续区间后判断每个区间的状态:

# 处理每个id,生成最终的状态区间结果
result <- df %>%
  group_by(id) %>%
  # 调整enrollment的起止日期,确保落在目标时间范围内
  mutate(
    # 若entry_date早于起始范围,调整为起始范围;NA值保留
    entry_adj = ifelse(is.na(entry_date), NA, pmax(entry_date, start_range)),
    # 若exit_date晚于结束范围,调整为结束范围;NA值保留
    exit_adj = ifelse(is.na(exit_date), NA, pmin(exit_date, end_range))
  ) %>%
  # 过滤掉完全在目标范围之外的无效enrollment记录
  filter(!(entry_adj > end_range | exit_adj < start_range)) %>%
  # 收集当前id的所有关键时间点:范围起止、调整后的entry/exit日期,去重排序
  summarise(
    time_points = c(start_range, entry_adj, exit_adj, end_range) %>%
      na.omit() %>%
      unique() %>%
      sort()
  ) %>%
  # 从排序后的时间点生成连续的日期区间
  mutate(
    entry_date = lag(time_points),
    exit_date = time_points
  ) %>%
  # 移除第一个无效的区间(entry_date为NA的行)
  filter(!is.na(entry_date)) %>%
  # 为每个区间判断对应的分类标签
  mutate(
    category = case_when(
      # 从未注册:该id没有有效enrollment记录,区间覆盖整个目标范围
      n_distinct(time_points) == 2 & !id %in% df$id[!is.na(df$entry_date)] ~ 'Never enrolled',
      # 注册前:区间在该id第一次注册的起始日期之前
      exit_date <= df$entry_adj[df$id == id][1] ~ 'Prior to enrollment',
      # 注册中:区间完全被某段enrollment时间段覆盖
      map2_lgl(entry_date, exit_date, function(e, x) {
        any(df$entry_adj[df$id == id] <= e & df$exit_adj[df$id == id] >= x)
      }) ~ 'Enrolled',
      # 注册间隔:其他非注册状态的区间(两次注册之间、最后一次注册结束到范围结束)
      TRUE ~ 'Between enrollment'
    )
  ) %>%
  # 确保日期格式正确
  mutate(
    entry_date = ymd(entry_date),
    exit_date = ymd(exit_date)
  ) %>%
  ungroup()

# 查看结果
print(result)

逻辑说明

  • 日期调整:把超出目标范围的enrollment起止日期截断到范围边界,避免无效区间。
  • 关键时间点收集:把目标范围的起止、所有调整后的注册起止日期放在一起,排序后生成连续的无重叠区间。
  • 分类判断:通过case_when依次判断每个区间的状态,确保每个标签的逻辑精准对应你的需求。

内容的提问来源于stack exchange,提问作者Jules.Sanchez

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 08:14:44