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

如何计算主时间区间与其他区间的非重复重叠时长(Tidyverse优先)

计算主时间区间与多区间的非重复重叠时长

问题背景

需计算主时间区间与第二、第三区间的非重复重叠时长,重复重叠部分仅统计一次。当前逐分钟枚举的方法效率低下,寻求基于Tidyverse的高效解决方案。

示例数据

library(tidyverse)
library(lubridate)

main_start <- c("2024-01-01 4:50:00 PM", "2024-03-22 11:00:00 AM")
main_end <- c("2024-01-01 11:40:00 PM", "2024-03-22 9:00:00 PM")

second_start <- c("2024-01-01 2:00:00 PM", "2024-03-22 12:00:00 PM")
second_end <- c("2024-01-02 12:15:00 AM", "2024-03-22 8:00:00 PM")

third_start <- c("2024-01-01 8:00:00 AM", "2024-03-22 8:00:00 AM")
third_end <- c("2024-01-01 5:00:00 PM", "2024-03-22 5:00:00 PM")

df <- tibble::tibble(main_start, main_end,
                     second_start, second_end,
                     third_start, third_end) %>% 
  mutate(main_start = ymd_hms(main_start),
         main_end = ymd_hms(main_end),
         second_start = ymd_hms(second_start),
         second_end = ymd_hms(second_end),
         third_start = ymd_hms(third_start),
         third_end = ymd_hms(third_end))

需求详情

  • 统计主区间与第二/第三区间的总重叠时长,重复重叠部分仅计算一次
  • 行1预期结果:6小时50分钟(主区间4:50 PM-11:40 PM完全被另外两个区间覆盖)
  • 行2预期结果:9小时(主区间11:00 AM-9:00 PM的重叠区间为11:00 AM-8:00 PM)

高效解决方案

核心思路:先提取主区间与每个子区间的重叠部分,再合并这些重叠区间(消除内部重复),最后计算合并后区间的总时长。

实现代码

# 定义辅助函数:计算主区间与多个子区间的非重复重叠时长
calc_unique_overlap <- function(main_start, main_end, sub_starts, sub_ends) {
  main_int <- interval(main_start, main_end)
  # 生成每个子区间与主区间的重叠区间
  overlaps <- map2(sub_starts, sub_ends, ~intersect(interval(.x, .y), main_int))
  # 过滤空区间
  overlaps <- keep(overlaps, ~!is.na(.x))
  
  if (length(overlaps) == 0) {
    return(duration(0))
  }
  
  # 合并重叠或相邻的区间
  merged <- reduce(overlaps, ~union(.x, .y))
  # 计算总时长
  sum(int_length(merged)) %>% duration(units = "seconds")
}

# 应用到数据框
df_result <- df %>%
  rowwise() %>%
  mutate(
    unique_overlap = calc_unique_overlap(
      main_start, main_end,
      sub_starts = c(second_start, third_start),
      sub_ends = c(second_end, third_end)
    ),
    # 转换为易读的小时+分钟格式
    overlap_hm = sprintf("%d小时%d分钟", hour(unique_overlap), minute(unique_overlap))
  ) %>%
  ungroup()

# 查看结果
df_result %>% select(main_start, main_end, unique_overlap, overlap_hm)

结果验证

运行代码后,输出结果符合预期:

  • 行1:unique_overlap为24600s (~6.83 hours),对应6小时50分钟
  • 行2:unique_overlap为32400s (~9 hours),对应9小时

代码说明

  1. 辅助函数calc_unique_overlap:
    • 生成主时间区间,计算每个子区间与主区间的重叠部分
    • 使用reduce(..., union)合并重叠/相邻区间,自动消除重复部分
    • 计算合并后所有区间的总时长,返回duration类型
  2. 数据框处理:
    • 用rowwise()逐行处理数据
    • 转换结果为易读的小时+分钟格式,便于查看

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 21:23:30