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

在R语言中计算分组数据的上次事件发生间隔时间

解决方法:按ID分组追踪最近事件日期

你的问题核心是要在每个ID内部追踪最近一次事件的日期,并且对该ID第一个事件之前的记录返回NA。你之前的代码出错是因为tmpG的分组没有按ID隔离,导致跨ID的累积计算,同时也没处理第一个事件前的无事件行。

这里提供两种简洁的实现方案,都能完美匹配你的期望输出:

方案1:结合dplyr和tidyr::fill(直观易懂)

这种方法先标记事件行的日期,再向下填充最近的事件日期,最后计算间隔:

library(dplyr)
library(tidyr)

df %>%
  group_by(ID) %>%
  # 给事件行标记日期,非事件行设为NA
  mutate(last_event_date = ifelse(event > 0, date, NA)) %>%
  # 在每个ID内,向下填充最近的事件日期
  fill(last_event_date, .direction = "down") %>%
  # 计算当前日期与最近事件日期的间隔(NA会自动保留)
  mutate(tae = as.numeric(date - last_event_date)) %>%
  # 移除临时列
  select(-last_event_date) %>%
  ungroup()

运行后输出:

# A tibble: 7 x 4
     ID date       event   tae
  <dbl> <date>     <dbl> <dbl>
1     1 2014-08-03     1     0
2     1 2014-08-04     0     1
3     1 2014-08-07     3     0
4     1 2014-08-10     0     3
5     2 2015-07-01     0    NA
6     2 2015-07-03     4     0
7     2 2015-08-01     0    29

方案2:用purrr::accumulate(无需额外加载tidyr)

如果你不想加载tidyr,可以用accumulate来逐个追踪最近的事件日期:

library(dplyr)
library(purrr)

df %>%
  group_by(ID) %>%
  mutate(
    # 逐个遍历日期,遇到事件就更新最近日期,否则保留之前的
    last_event_date = accumulate(date, ~ ifelse(event[.y] > 0, date[.y], .x)),
    # 对第一个事件之前的行,将最近日期设为NA
    last_event_date = ifelse(cumsum(event > 0) == 0, NA, last_event_date),
    # 计算间隔天数
    tae = as.numeric(date - last_event_date)
  ) %>%
  select(-last_event_date) %>%
  ungroup()

这个方案和方案1效果完全一致,适合不想多加载包的场景。

为什么你的原代码出错?

你的tmpG = cumsum(c(FALSE, as.logical(diff(event))))是基于整个数据集的event变化,没有按ID分组,导致ID=2的第一条记录被分到了和ID=1最后一条相同的分组,从而错误累积了3天的间隔。同时,代码也没有处理“ID第一个事件前的无事件行”的情况,所以无法生成NA。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 14:22:47