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

在R中基于日期差与重置逻辑按唯一ID划分独立事件

问题描述

我在R中有一个数据框df,每个个体对应多个事件,每个事件由唯一日期定义。diff_earliest_date列是对应唯一id的最早日期与后续日期之间的天数。

原始数据

data <- data.frame(
  id = c(1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 5678, 5678, 5678, 5678, 5678, 5678),
  date = as.Date(c("1997-04-08", "1997-04-12", "1997-04-19", "1997-09-01", "1997-09-14", "1997-10-22", "1997-12-10", 
                   "1998-06-16", "1998-06-27", "1998-06-29", "1998-09-13", "1998-09-25", "1999-05-17", "1999-07-18", 
                   "1997-04-08", "1997-04-22", "1997-09-14", "1997-10-25", "1998-05-13", "1998-10-07")),
  event = c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 1, 2, 3, 4, 5, 6),
  diff_earliest_date = c("0 days", "4 days", "11 days", "146 days", "159 days", "197 days", "246 days", "434 days", 
                         "445 days", "447 days", "523 days", "535 days", "769 days", "831 days", "0 days", "10 days", 
                         "159 days", "200 days", "400 days", "547 days"))

原始数据预览:

> data
     id       date event diff_earliest_date
1  1234 1997-04-08     1             0 days
2  1234 1997-04-12     2             4 days
3  1234 1997-04-19     3            11 days
4  1234 1997-09-01     4           146 days
5  1234 1997-09-14     5           159 days
6  1234 1997-10-22     6           197 days
7  1234 1997-12-10     7           246 days
8  1234 1998-06-16     8           434 days
9  1234 1998-06-27     9           445 days
10 1234 1998-06-29    10           447 days
11 1234 1998-09-13    11           523 days
12 1234 1998-09-25    12           535 days
13 1234 1999-05-17    13           769 days
14 1234 1999-07-18    14           831 days
15 5678 1997-04-08     1             0 days
16 5678 1997-04-22     2            10 days
17 5678 1997-09-14     3           159 days
18 5678 1997-10-25     4           200 days
19 5678 1998-05-13     5           400 days
20 5678 1998-10-07     6           547 days

需求说明

为每个id定义间隔243天的唯一事件:当某个日期与对应id的最早日期间隔>243天时,重置天数差以标记新的唯一事件。最终数据需新增diff_reset和unique_event列,预期结果如下:

> data
     id       date event diff_earliest_date diff_reset unique_event
1  1234 1997-04-08     1             0 days     0 days            1
2  1234 1997-04-12     2             4 days     4 days            1
3  1234 1997-04-19     3            11 days    11 days            1
4  1234 1997-09-01     4           146 days   146 days            1
5  1234 1997-09-14     5           159 days   159 days            1
6  1234 1997-10-22     6           197 days   197 days            1
7  1234 1997-12-10     7           246 days     0 days            2
8  1234 1998-06-16     8           434 days   189 days            2
9  1234 1998-06-27     9           445 days   200 days            2
10 1234 1998-06-29    10           447 days   202 days            2
11 1234 1998-09-13    11           523 days     0 days            3
12 1234 1998-09-25    12           535 days    13 days            3
13 1234 1999-05-17    13           769 days     0 days            4
14 1234 1999-07-18    14           831 days    63 days            4
15 5678 1997-04-08     1             0 days     0 days            1
16 5678 1997-04-22     2            10 days    10 days            1
17 5678 1997-09-14     3           159 days   159 days            1
18 5678 1997-10-25     4           200 days     0 days            1
19 5678 1998-05-13     5           400 days   200 days            2
20 5678 1998-10-07     6           547 days     0 days            3

我尝试用dplyr的mutate结合日期运算和lag(date)实现,但未成功,觉得可能需要循环遍历数据,恳请提供解决方案。


解决方案

无需使用循环,用dplyr的分组累积计算即可实现需求,完整步骤如下:

1. 转换天数列为数值型

先把字符格式的diff_earliest_date转为整数天数,方便后续计算:

library(dplyr)

data <- data %>%
  group_by(id) %>%
  mutate(diff_num = as.numeric(gsub(" days", "", diff_earliest_date))) %>%
  ungroup()

2. 计算唯一事件组unique_event

通过天数与243的整除关系,划分每个事件所属的唯一组:

data <- data %>%
  group_by(id) %>%
  mutate(unique_event = floor(diff_num / 243) + 1) %>%
  ungroup()

3. 计算重置后的天数差diff_reset

以每个唯一事件组的最早日期为起点,计算当前日期与起点的天数差:

data <- data %>%
  group_by(id, unique_event) %>%
  mutate(diff_reset = paste(date - min(date), "days")) %>%
  ungroup() %>%
  # 调整列顺序并移除中间变量
  select(id, date, event, diff_earliest_date, diff_reset, unique_event)

完整可运行代码

library(dplyr)

# 原始数据
data <- data.frame(
  id = c(1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 1234, 5678, 5678, 5678, 5678, 5678, 5678),
  date = as.Date(c("1997-04-08", "1997-04-12", "1997-04-19", "1997-09-01", "1997-09-14", "1997-10-22", "1997-12-10", 
                   "1998-06-16", "1998-06-27", "1998-06-29", "1998-09-13", "1998-09-25", "1999-05-17", "1999-07-18", 
                   "1997-04-08", "1997-04-22", "1997-09-14", "1997-10-25", "1998-05-13", "1998-10-07")),
  event = c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 1, 2, 3, 4, 5, 6),
  diff_earliest_date = c("0 days", "4 days", "11 days", "146 days", "159 days", "197 days", "246 days", "434 days", 
                         "445 days", "447 days", "523 days", "535 days", "769 days", "831 days", "0 days", "10 days", 
                         "159 days", "200 days", "400 days", "547 days"))

# 转换天数列为数值型
data <- data %>%
  group_by(id) %>%
  mutate(diff_num = as.numeric(gsub(" days", "", diff_earliest_date))) %>%
  ungroup()

# 计算唯一事件组
data <- data %>%
  group_by(id) %>%
  mutate(unique_event = floor(diff_num / 243) + 1) %>%
  ungroup()

# 计算重置后的天数差
data <- data %>%
  group_by(id, unique_event) %>%
  mutate(diff_reset = paste(date - min(date), "days")) %>%
  ungroup() %>%
  select(id, date, event, diff_earliest_date, diff_reset, unique_event)

# 查看结果
print(data)

运行上述代码后,输出结果与预期完全一致。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 12:49:52