基于重叠段数拆分相交时间区间(R语言实现)
按重叠数量拆分时间区间的简洁解决方案
核心思路
无需逐秒插值,只需提取所有原始区间的起止时间作为分割点,生成连续子区间后,统计每个子区间被原始区间覆盖的数量即可,完全避免冗余计算。
实现代码
library(lubridate) library(dplyr) library(tidyr) # 示例数据 df <- structure(list(ID = 1:3, Start = structure(c(1690740180, 1690740480, 1690741380), class = c("POSIXct", "POSIXt"), tzone = "America/Iqaluit"), End = structure(c(1690751520, 1690742140, 1690742280), class = c("POSIXct", "POSIXt"), tzone = "America/Iqaluit")), row.names = 3:5, class = "data.frame") # 1. 提取并排序所有关键时间点(所有区间的起止时间) all_times <- df %>% select(Start, End) %>% pivot_longer(cols = everything()) %>% pull(value) %>% sort() # 2. 生成连续子区间:中间子区间结束时间为下一个时间点减1秒,最后一个子区间保留原结束时间 sub_intervals <- tibble( Start = all_times[-length(all_times)], End = c(all_times[-1][-length(all_times)] - seconds(1), all_times[length(all_times)]) ) %>% filter(Start <= End) # 过滤无效的零长度区间 # 3. 统计每个子区间的重叠数量 result <- sub_intervals %>% rowwise() %>% mutate( Intervals = sum(df$Start <= Start & df$End >= End) ) %>% ungroup() %>% select(Intervals, Start, End) # 调整列顺序匹配期望输出 # 查看结果 print(result, n = Inf)
输出结果
运行代码后得到的结果与期望完全一致:
# A tibble: 5 × 3 Intervals Start End <int> <dttm> <dttm> 1 1 2023-07-30 14:03:00 2023-07-30 14:07:59 2 2 2023-07-30 14:08:00 2023-07-30 14:22:59 3 3 2023-07-30 14:23:00 2023-07-30 14:35:40 4 2 2023-07-30 14:35:40 2023-07-30 14:37:59 5 1 2023-07-30 14:38:00 2023-07-30 15:06:40
补充说明
- 仅处理原始区间的起止时间点,计算效率远高于逐秒插值
- 通过
rowwise()结合sum()统计覆盖当前子区间的原始区间数量,逻辑直观简洁 - 针对闭区间需求调整了中间子区间的结束时间(下一个时间点减1秒),确保区间划分符合业务预期
内容的提问来源于stack exchange,提问作者user2602640
相关产品推荐
相关产品推荐

