【问题标题】:Match intervals with events in R将间隔与 R 中的事件匹配
【发布时间】:2026-01-14 12:55:01
【问题描述】:

我有一个事件表和一组间隔。我想为每个事件关联一个布尔值,即设置为 T 是事件在区间内。

我的意见:

intervals:
begin                      end
2015-03-01 14:02:00        2015-03-01 14:09:00
2015-03-01 15:13:00        2015-03-01 15:54:00
2015-03-01 16:02:00        2015-03-01 19:09:00

events:
id           date
1            2015-03-01 14:01:00
2            2015-03-01 14:03:00
3            2015-03-01 14:07:00
4            2015-03-01 15:55:00
5            2015-03-01 17:02:00

我的输出是:

id           inInterval
1            F
2            T
3            T
4            F
5            T

我有数百万个事件和数万个间隔。出于性能原因,我不想循环事件,也不想处理每个时间间隔的所有事件。

我可以轻松做的是获取事件和间隔开始/结束的有序数据表:

events:
id           date                     start       end
1            2015-03-01 14:01:00      
NA           2015-03-01 14:02:00      T
2            2015-03-01 14:03:00
3            2015-03-01 14:07:00
NA           2015-03-01 14:09:00                  T
NA           2015-03-01 15:13:00      T
NA           2015-03-01 15:54:00                  T
4            2015-03-01 15:55:00
NA           2015-03-01 16:02:00      T
5            2015-03-01 17:02:00
NA           2015-03-01 19:09:00                  T

现在我停留在最后一部分:为 start=T 和 end=T 之间的所有行设置 inInterval=T。它显然需要某种延迟,但我缺少所需的功能。

任何帮助将不胜感激。谢谢

编辑:似乎这个现有问题提供了一些见解:What is an efficient method for partitioning and aggregating intervals from timestamped rows in a data frame? 一旦我发表了我的问题,就提出了建议。基本上 findInterval 应该可以帮助我解决我的问题。

【问题讨论】:

  • 可以从data.table检查foverlaps
  • 你试过简单的 ifelse 语句吗? ifelse( date < begin | date > end, F, T)
  • @akrun 它看起来完全符合我的需要。谢谢。
  • @grrgrrbla 该解决方案适用于单个间隔。使用多个间隔是可行的,但是您需要在每个间隔的所有事件上调用 ifelse,这就是我不想要的。
  • 无论如何,如果格式良好,如 akrun 建议的那样,您可以使用 data.table 包执行类似 setkey(setDT(intervals)) ; setkey(setDT(events)[, date2 := date], date, date2) ; foverlaps(events, intervals, which = TRUE) 的操作。

标签: r


【解决方案1】:

我在基础 R 中的新手想法(给定间隔表是有序的并且没有重叠间隔):

pint <- as.POSIXct(as.vector(t(intervals)))
results <- data.frame(
            id = events$id,
            inInterval = findInterval( as.POSIXct(events$date), pint) %% 2 != 0
         )

给予:

  id inInterval
1  1      FALSE
2  2       TRUE
3  3       TRUE
4  4      FALSE
5  5       TRUE

findInterval返回找到的区间内的索引:

  • 如果它是奇数,我们在一个真正的区间返回 TRUE
  • 如果我们甚至超出了实际间隔。返回 FALSE

【讨论】: