Это распространенная проблема в геномике.Пакет IRanges
на BioConductor имеет функцию findOverlaps()
для этой цели.foverlaps()
- это data.table версия, которая используется здесь.AFAIK, нет эквивалента dplyr .
Сначала нам нужно создать вектор времени начала и окончания дня.Вызов foverlaps()
возвращает все возможные типы перекрытий.Наконец, время начала и окончания корректируется в соответствии с ожидаемым результатом.
library(data.table)
library(lubridate)
day_seq <- setDT(df)[, .(day_start = seq(
floor_date(min(sleepdatestarttime), "day"),
ceiling_date(max(sleepdateendtime), "day"), "day"))][
, day_end := day_start + days(1)]
setkey(day_seq, day_start, day_end)
foverlaps(
df, day_seq, by.x = c("sleepdatestarttime", "sleepdateendtime"), nomatch = 0L)[
, `:=`(sleepdatestarttime = pmax(sleepdatestarttime, day_start),
sleepdateendtime = pmin(sleepdateendtime, day_end - seconds(1)))][
, c("day_start", "day_end") := NULL][]
i sleepdatestarttime sleepdateendtime sleepstage
1: 1 2018-03-02 23:31:00 2018-03-02 23:54:00 rem
2: 2 2018-03-02 23:54:00 2018-03-02 23:55:00 light
3: 3 2018-03-02 23:55:00 2018-03-02 23:59:59 wake
4: 3 2018-03-03 00:00:00 2018-03-03 00:02:00 wake
5: 4 2018-03-03 00:02:00 2018-03-03 00:03:30 light
6: 5 2018-03-03 00:03:30 2018-03-03 00:23:30 deep
7: 6 2018-03-03 00:23:30 2018-03-03 02:58:00 light
Данные
df <- readr::read_table("i sleepdatestarttime sleepdateendtime sleepstage
1 2018-03-02 23:31:00 2018-03-02 23:54:00 rem
2 2018-03-02 23:54:00 2018-03-02 23:55:00 light
3 2018-03-02 23:55:00 2018-03-03 00:02:00 wake
4 2018-03-03 00:02:00 2018-03-03 00:03:30 light
5 2018-03-03 00:03:30 2018-03-03 00:23:30 deep
6 2018-03-03 00:23:30 2018-03-03 02:58:00 light")