嗨, friend 们,我无法确定多个日期时间范围是否相互重叠,如果是,它们重叠的时间段。我已经引用了以下链接 Determine Whether Two Date Ranges Overlap和 Algorithm to detect overlapping periods还有一些。
不知道这对不对,我有 n=3 的示例解释。
假设我有“n”个开关 sw1、sw2 和 sw3。状态是开/关状态,即 1/0。
Switches,State,Intime,Outtime
sw3,1,9:00:00,10:40:00
sw2,1,9:30:00,10:15:00
sw1,1,10:00:00,11:00:00
sw2,1,10:20:00,10:30:00
我遇到过这种可能性。可能还有更多。仍在寻找其他可能性。这里的常见时间段是从 10:00 到 10:15,即 15 分钟和 10:20 到 10:30,即 10 分钟。这些开关打开 ('1') 的组合时间段为 25 分钟。
10:00 11:00
sw1 |-----------------------------------|
9:30 10:15 10:20 10:30
sw2 |-------------| |-------|
9:00 10:40
sw3 |----------------------------------------|
为 n 个重叠开关概括此日期时间是一项艰巨的任务。我仍在努力,欢迎任何建议或修改。谢谢。
最佳答案
1) 根据示例数据,我们假设数据的格式为 hh:mm:00,其中 hh < 24。
读入测试数据。创建两个将 hh:mm:00 形式的字符串转换为分钟数的函数和一个将分钟数转换为 chron "times"
对象的函数。为提供 Intervals
列表的每一行数据创建逐分钟序列。将对应于同一开关的那些序列联合起来,给出列表 Intervals.u
,然后与该列表的组件相交,给出序列 Intersection
。计算 Intersection
中的行程 r
以给出一组起点和终点。最后计算分钟数并将其转换为 "times"
类持续时间。 (分钟数和持续时间仅取决于 r
和 Intersection
,因此如果 intervals.df
不是,我们可以跳过以 ## 结尾的行需要。)
# test data
Lines <- "Switches,State,Intime,Outtime
sw3,1,9:00:00,10:40:00
sw2,1,9:30:00,10:15:00
sw1,1,10:00:00,11:00:00
sw2,1,10:20:00,10:30:00"
DF <- read.csv(text = Lines, as.is = TRUE)
library(chron)
to.num <- function(x) floor(as.numeric(times(x)) * 24 * 60 + 1e-6)
to.times <- function(x) times(x / (24 * 60))
Seq <- function(r) seq(to.num(DF$Intime[r]), to.num(DF$Outtime[r]))
Intervals <- lapply(1:nrow(DF), Seq)
Intervals.u <- lapply(split(Intervals, DF$Switches),
function(L) Reduce(union, L))
Intersection <- Reduce(intersect, Intervals.u)
r <- rle(c(FALSE, diff(Intersection) == 1))
i.ends <- cumsum(r$lengths)[r$values] ##
ends <- to.times(Intersection[i.ends]) ##
starts <- ends - to.times(r$lengths[r$values]) ##
intervals.df <- data.frame(start = starts, end = ends); intervals.df ##
## start end
## 1 10:00:00 10:15:00
## 2 10:20:00 10:30:00
mins <- length(Intersection) - sum(r$values); mins
## [1] 25
duration <- to.times(mins); duration
## [1] 00:25:00
2) 关于与速度相关的注释,我们可以改用 IRanges 包,它可以有效地编码范围并稍微减少代码大小:
library(IRanges)
Intervals <- IRanges(to.num(DF$Intime), to.num(DF$Outtime))
Intersection <- Reduce(intersect, split(Intervals, DF$Switches))
intervals.df <- data.frame(start = to.times(start(Intersection)),
end = to.times(end(Intersection)))
intervals.df
## start end
## 1 10:00:00 10:15:00
## 2 10:20:00 10:30:00
mins <- sum(width(Intersection) - 1); mins
## [1] 25
duration <- to.times(mins); duration
## [1] 00:25:00
更新 一些修复和更好的变量名称。进一步改进。添加了 (2)。
关于r - 日期时间 - 确定多个(n)日期时间范围是否在 R 中相互重叠,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24736000/