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

如何用向量化方法计算多重叠/间断时段的办公室总占用天数?

问题描述

我们需要计算办公室的总占用天数,给定不同角色的出勤时间段(如下表),需合并重叠/连续的占用时段后计算总天数。已知合并后的连续时段为1-20日、31-35日、41-55日,总天数为40天。

typeday_inday_out
A110
A515
A3135
B515
C1020
C4555
D4150

现有基于for循环的实现,但希望找到向量化的更优解法。


方法1:dplyr合并重叠区间

核心思路是提取所有时间段并排序,通过分组标记合并重叠/连续区间,最后计算总天数。

library(dplyr)

df_raw <- read.table(
  header = TRUE,
  text = "
type day_in day_out
A  1 10
A  5 15
A 31 35
B  5 15
C 10 20
C 45 55
D 41 50 
"
)

# 合并重叠/连续区间
merged_intervals <- df_raw %>%
  select(day_in, day_out) %>%
  arrange(day_in) %>%
  mutate(
    # 标记新的独立区间:当前起始日 > 上一个结束日+1时,分组编号+1
    group = cumsum(day_in > lag(day_out, default = -Inf) + 1)
  ) %>%
  group_by(group) %>%
  summarise(
    start = min(day_in),
    end = max(day_out)
  )

# 计算总占用天数
total_days <- sum(merged_intervals$end - merged_intervals$start + 1)
total_days # 输出40

思路说明

  1. 提取所有出勤时段,按起始日排序。
  2. 用cumsum生成分组:当当前区间的起始日与上一个区间不连续时,视为新分组。
  3. 按分组合并,取每组的最小起始日和最大结束日,得到合并后的连续区间。
  4. 每个区间的天数为end - start + 1,求和得到总占用天数。

方法2:data.table高效合并

针对大数据量场景,data.table的向量化操作效率更高:

library(data.table)

setDT(df_raw)

# 排序并合并区间
merged_intervals <- df_raw[, .(day_in, day_out)][
  order(day_in), 
  .(start = min(day_in), end = max(day_out)), 
  by = .(group = cumsum(day_in > shift(day_out, fill = -Inf) + 1))
]

# 计算总天数
total_days <- sum(merged_intervals$end - merged_intervals$start + 1)
total_days # 输出40

方法3:lubridate区间原生处理

利用lubridate的区间操作函数,更直观地处理重叠/连续逻辑:

library(lubridate)
library(dplyr)

# 转换为lubridate区间对象
intervals <- df_raw %>%
  mutate(interval = interval(day_in, day_out)) %>%
  pull(interval)

# 迭代合并所有重叠/连续区间
merged_intervals <- reduce(intervals, function(x, y) {
  if (int_overlaps(x, y) | int_adjacent(x, y)) union(x, y) else x
})

# 计算总天数:int_length返回天数差,每个区间需+1包含起始日
total_days <- sum(int_length(merged_intervals)) + length(merged_intervals)
total_days # 输出40

思路说明

  • int_overlaps判断区间是否重叠,int_adjacent判断是否连续(如前一个结束日为10,后一个起始日为11)。
  • reduce迭代合并所有区间,最终得到无重叠的连续区间集合。
  • int_length返回区间的天数差,因此每个区间需加1来覆盖起始日,再求和得到总天数。

方案优势对比

  • 完全向量化操作,避免for循环的性能瓶颈,数据量越大效率提升越明显。
  • 代码逻辑清晰简洁,减少手动状态管理的复杂度,易读易维护。
  • 依赖成熟的第三方包内置函数,稳定性更高。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 17:12:22