当前位置: 首页 > 知识库问答 >
问题:

datetime-确定多个日期时间范围是否在R中相互重叠

解鸿运
2023-03-14

嗨,朋友们,我很难找到多个日期时间范围是否相互重叠,如果是,则它们重叠的时间段。我已经参考了以下链接 确定两个日期范围是否重叠 和 算法 以检测重叠的时间段等等。

不知道这是否正确,我有n=3的示例解释。

假设我有“n”开关 sw1,sw2

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个重叠的开关概括此日期时间是一项困难的任务。我仍在努力,所以欢迎任何建议或修改。非常感谢。

共有2个答案

乐宜民
2023-03-14

一种html" target="_blank">方法是:

  1. 计算每个交换机的IntimeOuttime之间的唯一分钟/秒。E、 g.如果开关在9:00打开并在9:02关闭,则其在9:00和9:01之间打开的唯一分钟数。
  2. 统计所有交换机上每一唯一分钟/秒出现的次数
  3. 如果任何一分钟/秒发生的次数与开关的次数一样多(即,在您的情况下为三次),则所有开关必须在该分钟/秒内打开

使用该逻辑,这是一个潜在的解决方案(数据存储在数据框 x 中):

# Function to convert string to time.
asTime <- function (tm) as.POSIXlt(tm, format = '%H:%M:%S')

# Calculate unique minutes between Intimes and Outtimes.
minSpan <- function (start, end) seq(asTime(start), asTime(end) - 1, 'min')

# Calculate the time span in minutes for each row.
spans <- mapply(minSpan, x$Intime, x$Outtime)

# Count how many times each minute appears.
counts <- table(do.call(c, spans))

# Total number of switches.
switches <- length(unique(x$Switches))

# Count minutes where all switches have been on.
length(counts[counts == switches])

这将使你精确到一分钟,因为这似乎是你在你的问题中显示的。尽管您可以通过在< code>minSpan()函数中将< code>'min'更改为< code>'sec'来轻松地将其更改为秒。

在< code>minSpan()中,我从< code>Outtime中减去一分钟:

minSpan <- function (start, end) seq(asTime(start), asTime(end) - 1, 'min')

这是因为如果你要计算 10:00 和 10:02 之间的分钟,seq() 将返回三分钟,10:00、10:01、10:02。但实际上,开关在 10:02 关闭,所以你真的想要从 10:00 到 10:01 的跨度。

无论如何,这个解决方案似乎对你给出的小例子有效。根据你的数据有多大,我认为这足够慢,但这可能不是问题。

戴正阳
2023-03-14

1)基于样本数据,我们假设数据的形式为hh: mm: 00其中hh

读入测试数据。创建两个将hh:mm:00形式的字符串转换为分钟数的函数,以及一个将分钟数转换为chron "times"对象的函数。为给出< code >间隔列表的每一行数据创建分钟序列。并集对应于相同开关的序列,给出列表< code>Intervals.u,然后相交该列表的组件,给出序列< code>Intersection。计算< code >交集中的游程,< code>r,以给出一组起点和终点。最后,计算分钟数,并将其转换为持续时间。(分钟数和持续时间仅取决于< code>r和< code>Intersection,因此如果不需要< code>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)。

 类似资料:
  • 问题内容: 问题是我希望它忽略日期,而只考虑时间。这是我所拥有的: 照原样,我得到这个错误: 当我将相关行更改为: 我收到此错误: 我知道我正在使用两个不同的库,但我不确定如何在它们之间进行转换或仅使用一个库就可以完成我想做的事情。我只希望它忽略日期,只检查时间是否在指定范围内。由于我在代码的其他地方使用了一个库,因此必须使用Python 2.6。 问题答案: 这行: 根据docs返回一个对象。

  • 我一直在使用DateTime Diff(在php中)来获取日期对的各种设置—要显示的两个格式化日期、与当前日期的差异(例如“开始日期是3个月2天前”),以及两个日期之间的长度(“长度是2个月3天”)。 问题是DateTime Diff忽略了其中一天,所以如果开始是昨天,结束是明天,它会给出2天,而我想要3天,因为两个日期都应该包含在长度中。如果只是几天,我可以简单地在结果中添加1,但是我想使用Di

  • 问题内容: 我的数据库中有以下一组匹配日期的日期(dd / MM / yyyy): 事件具有开始和结束日期(时间无关紧要),并且endDate为NULL表示事件仍在进行中。 我想确定的是两个任意日期之间的日期范围,其中a)没有事件,b)事件重叠。 因此,对于输入日期范围01/04/2009-30/06/2009,我希望得到以下结果: 注意,作为结果,两个相邻的重叠范围是可以接受的。 谁能用SQL算

  • 问题内容: 如果我在表中有2个日期列,并且。如何返回给定日期介于这两个日期之间的行?例如: 如果给定的日期是 它应该返回以下行 来自以下各行: sql可能吗? 我正在使用sql server 2008。 问题答案: 使用SQL Server,它实际上非常简单:

  • 问题内容: 在所有三个日期都由的实例表示的情况下,如何检查某个日期是否在其他两个日期之间? 问题答案: 这可能更具可读性:

  • 问题内容: 查看当前时间是否在发言和讲话之间的最佳方式是什么。 我会想到以下内容,不确定是否正确: 请让我知道如果这是正确的方法,可以写出更好的东西吗? 问题答案: 我最初的答案非常具体地针对所提出的问题,并且不适应午夜的时间范围。由于六年后这仍然是公认的答案,因此我在下面合并了@rouble的答案,该答案在我的文档中得到扩展以支持午夜。 我仍然坚持下面的原始意见,即该逻辑的大多数应用程序可能更适