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

创建带重置功能的连续无事件计数变量(R语言)

带重置的分组递推计数问题(R语言)

需求说明

按labs分组统计连续无事件(event=0)的时间步数:

  • 事件发生(event=1)时,计数重置为0
  • 初始无事件的行计数从0开始递增
  • 保留event为NA对应的NA值

示例数据

labs <- c("A", "A", "A", "A", "B", "B", "B", "B", "C", "C", "C", "C", "D", "D", "D", "D", "D")
time <- c(1,2,3,4 ,1,2,3,4 ,1,2,3,4 ,1,2,3,4,5)
event <- c(0,0,0,0, 0,1,0,0, 1,1,0,0, NA,0,0,1,0)
desiredOutcome <- c(0,1,2,3,0,0,0,1,0,0,0,1,NA,0,1,0,0) # 目标输出

exDF <- data.frame(labs,time, event, desiredOutcome)

已尝试代码

library(dplyr)

exDF <- exDF %>%
  group_by(labs) %>%
  mutate(pe1 = lag(event, order_by=time)) # 创建前一事件变量

exDF$count2 <- ifelse(
  ((exDF$pe1 == 1) & (exDF$event == 0)), # 前一步有事件且当前无事件
  0, # 满足条件设为0
  NA) # 否则为NA

exDF$count <- ifelse(
  (is.na(exDF$pe1) & (exDF$event == 0)), # 无前置步且当前无事件
  0, # 满足条件设为0
  exDF$count2) # 否则取count2的值

解决方案

方法1:dplyr + purrr(tidyverse生态)

利用purrr::accumulate实现递推计算,它可以用上一步结果生成当前值,完美适配带重置的计数场景:

library(dplyr)
library(purrr)

exDF <- exDF %>%
  group_by(labs) %>%
  mutate(
    # 清理event的NA,保留NA类型
    event_clean = ifelse(is.na(event), NA_integer_, event),
    # 递推计算计数
    count = accumulate(event_clean, .init = NA_integer_, 
                      ~ if (is.na(.y)) {
                          NA_integer_
                        } else if (.y == 1) {
                          0L
                        } else if (is.na(.x)) {
                          0L
                        } else {
                          .x + 1L
                        })[-1] # 去掉初始的NA
  ) %>%
  ungroup() %>%
  select(-event_clean)

# 验证结果
all.equal(exDF$count, exDF$desiredOutcome, na.rm = TRUE)

方法2:data.table(高效大数据处理)

如果数据集较大,data.table的分组和rleid函数能提供更高的运行效率:

library(data.table)
setDT(exDF)

exDF[, count := {
  # 生成重置点的分组ID:event=1或NA时分割
  rle_group <- rleid(event == 1 | is.na(event))
  # 对每个分组计算计数
  lapply(split(.SD, rle_group), function(sub_df) {
    if (any(is.na(sub_df$event))) {
      rep(NA, nrow(sub_df))
    } else if (any(sub_df$event == 1)) {
      rep(0, nrow(sub_df))
    } else {
      seq_len(nrow(sub_df)) - 1
    }
  }) %>% unlist()
}, by = labs]

# 验证结果
all.equal(exDF$count, exDF$desiredOutcome, na.rm = TRUE)

说明

  • 两种方法均能精准匹配目标输出,覆盖NA处理、事件重置和连续计数的全部逻辑
  • tidyverse方法可读性强,适合日常使用dplyr的场景
  • data.table方法在大数据集上的运行效率更有优势

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 12:22:06