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

如何用R按分组高效识别并列出满足条件的连续时间区间?

简洁R实现方案:按ID分组提取连续0值时间区间

用tidyverse工具链(dplyr + data.table)可以高效完成需求,完全替代复杂循环逻辑,且能覆盖所有边界场景,步骤如下:

核心步骤

  1. 数据排序与预处理:先按id和ts排序,保证时间序列的连续性;同时标记出有效0值(排除NA,NA视为非0)。
  2. 标记连续0值区间:用rleid()函数给连续的0值段分配唯一标识,方便后续分组汇总。
  3. 汇总统计与格式整理:按ID和区间分组,提取起止时间并格式化为指定字符串,同时统计总0值次数,最后合并结果。

完整代码

library(dplyr)
library(data.table)
library(lubridate)

# 假设你的数据框名为df
result <- df %>%
  # 按id和时间戳排序,确保时间顺序正确
  arrange(id, ts) %>%
  # 标记有效0值(排除NA),生成连续区间的分组ID
  mutate(
    is_zero = !is.na(cnt) & cnt == 0,
    # 仅给连续0值分配分组ID,非0值设为NA
    group_id = ifelse(is_zero, rleid(is_zero), NA)
  ) %>%
  # 过滤出仅包含0值的行
  filter(is_zero) %>%
  # 按id和分组ID提取每个区间的起止时间与次数
  group_by(id, group_id) %>%
  summarise(
    start_ts = first(ts),
    end_ts = last(ts),
    interval_cnt = n(),
    .groups = "drop"
  ) %>%
  # 按id汇总最终结果
  group_by(id) %>%
  summarise(
    date = as_date(first(start_ts)),
    total_zero = sum(interval_cnt),
    # 格式化为「起始时间 - 结束时间」,多区间用分号分隔
    zero_intervals = paste0(format(start_ts, "%Y-%m-%d %H:%M:%S"), " - ", format(end_ts, "%Y-%m-%d %H:%M:%S"), collapse = "; ")
  ) %>%
  ungroup()

关键细节说明

  • rleid()函数来自data.table,能快速识别连续相同值的分组,比手动判断前后行连续性更高效且不易出错。
  • 预处理时通过!is.na(cnt) & cnt == 0严格区分0值和NA,符合需求中NA视为非0的规则。
  • 若需保留无0值的ID,可在最后添加complete(id, fill = list(total_zero = 0, zero_intervals = ""))补充空值记录。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 08:17:10