多个日期范围的条件连接

时间:2017-05-05 14:00:34

标签: r dplyr

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

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

have previously tried a FOR loop但是这非常缓慢而且没有完成,因为我的数据超过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")

1 个答案:

答案 0 :(得分:4)

在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

一个注意事项 - 我会谨慎对待您的数据设置,因为在Events的第5行中您有一个开始时间&gt;结束时间。

快速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]