在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
相关产品推荐
相关产品推荐

