多个日期范围的条件连接

Cia*_*ran 1 r dplyr

我有两个数据框:“探针”和“事件”。下面的代码将生成这些数据帧的可重现样本。Probes.subset 是 Probes 中所有与 Events 中的日期时间范围相交的观测值的数据框。下面的代码将生成 6 个事件……实际上我有近 200 个谨慎的事件。

目标:我需要将 Events 中的 Event.name 连接到基于时间戳的 Probes.subset 中的每个相应观察,以便每个观察都与正确的事件相关联。

以前尝试过 FOR 循环,但速度非常慢,并且无法完成,因为我的数据超过 180,000 行。我有一种感觉,这可以通过编写一个函数并使用诸如 apply 之类的东西来解决,但我是 R 中函数的完全新手,而且我创建的函数都不起作用。

library(dplyr)

# Generate Probes data
start <- as.POSIXct("01/06/2016 01:00", format = "%d/%m/%Y %H:%M")
end <- start + as.difftime(1, units = "days")

Timestamp <- seq(from = start, to = end, by = "10 mins")
Value <- round(runif(145) * 100, 2)

Probes <- data.frame(Timestamp, Value)

# Generate Events data
Event.name <- seq(1, 6)

Event.start <- as.POSIXct(c("01/06/2016 01:20", "01/06/2016 05:00",
                            "01/06/2016 06:30", "01/06/2016 12:00",
                            "01/06/2016 17:40", "01/06/2016 19:20"),
                          format = "%d/%m/%Y %H:%M")

Event.end <- as.POSIXct(c("01/06/2016 02:00", "01/06/2016 05:30",
                            "01/06/2016 07:20", "01/06/2016 14:00",
                            "01/06/2016 18:10", "01/06/2016 21:40"),
                          format = "%d/%m/%Y %H:%M")

Events <- data.frame(Event.name, Event.start, Event.end)

# Subset probes data to fall within Events bounds
Probes.subset <- Probes %>%
  mutate(InRange = Timestamp %in% unlist(Map(
    `:`,
    Events$Event.start,
    Events$Event.end
  ))) %>%
  filter(InRange == "TRUE")
Run Code Online (Sandbox Code Playgroud)

Mik*_* H. 5

在 SQL 中,您可以as在加入时为不同的数据集指定别名。这允许您从每个数据集中选择特定列。采用该答案的代码,您可以执行以下操作:

library(sqldf)
res <- sqldf("SELECT l.*, r.`Event.name`
       FROM Probes as l
       LEFT JOIN Events as r
       ON  l.Timestamp BETWEEN r.`Event.start` AND r.`Event.end`")

head(res)
#            Timestamp Value Event.name
#1 2016-06-01 01:00:00 60.73         NA
#2 2016-06-01 01:10:00 14.01         NA
#3 2016-06-01 01:20:00 17.14          1
#4 2016-06-01 01:30:00 43.64          1
#5 2016-06-01 01:40:00 27.05          1
#6 2016-06-01 01:50:00 57.10          1
Run Code Online (Sandbox Code Playgroud)

一个注意事项 - 我会小心你的数据设置,因为Events你的第 5 行有一个开始时间> 结束时间。


另外一个快速的data.table解决方案是使用foverlaps

library(data.table)
setDT(Probes)[,Time2 := Timestamp] #Clean data
setDT(Events)[, `:=`(start = min(Event.start, Event.end), end = max(Event.start, Event.end)), by = (seq_len(nrow(Events)))]

setkey(setDT(Events), start, end)
res2 <- foverlaps(setDT(Probes), Events, by.x = c("Timestamp", "Time2"), nomatch = NA)[, c("Time2", "Event.start", "Event.end", "start","end") := NULL]
Run Code Online (Sandbox Code Playgroud)