Я работаю с данными, описывающими события, имеющие время начала и окончания.Например, это может быть в форме:
Я хотел бы преобразовать эти данные в форму, где я мог бы подсчитать вхождения событийчерез равные промежутки времени, чтобы можно было ответить на вопрос, сколько событий происходило от 13:15:00
до 13:29:59
и 13:30:00
до 13:45:00
и так далее.В приведенном выше примере вторая запись может быть подсчитана в первом слоте просто с использованием времени начала, но не будет считаться «продолжающейся» во втором регулярном интервале, даже если время окончания было интегрировано.
Для работы с15-минутные интервалы Я нашел неуклюжее решение, которое использует tidyr::uncount
, чтобы «расширить» набор данных до 24*4=96
15-минутных интервалов в течение 24-часового периода, а затем отфильтровать те, которые находятся внутри указанных интервалов.
library(tidyverse)
library(lubridate)
library(magrittr)
df1 <- tibble::tibble(
id = c(1, 2),
start_date = c(ymd_hms("2018-12-10 14:45:51", tz = "Australia/Brisbane"),
ymd_hms("2018-12-10 13:29:37", tz = "Australia/Brisbane")),
end_date = c(ymd_hms("2018-12-10 14:59:04", tz = "Australia/Brisbane"),
ymd_hms("2018-12-10 14:02:37", tz = "Australia/Brisbane")))
df2 <- df1 %>%
mutate(episode = 96) %>%
tidyr::uncount(episode, .id = "sequence")
df2$int_start <- rep(
seq(ymd_hms("2018-12-10 00:00:00", tz = "Australia/Brisbane"),
ymd_hms("2018-12-10 23:59:59", tz = "Australia/Brisbane"),
by = "15 mins"),
2)
df2$int_end <- df2$int_start + 899
df2 %<>%
filter(int_end > start_date & int_start < end_date )
Это дает мне данные в нужном формате:
Но я чувствую, что должен быть более разумный способ сделать это.Например, расширение не будет хорошим решением для очень большого набора данных и / или когда интервал времени мал (я думаю).Вероятно, будет также затруднительно расширять его работу на несколько дней (я думаю).
В Stata можно также использовать команду stsplit
для выполнения чего-то подобного.Я пытался повозиться с survSplit
из пакета survival
, но также получилось много записей:
df1$status <- 1
df1$start_date <- as.numeric(df1$start_date)
df1$end_date <- as.numeric(df1$end_date)
df3 <- survSplit(Surv(end_date, status) ~., df1,
cut=seq(from=as.numeric(as.POSIXct("2018-12-10 00:00:00")),
to=as.numeric(as.POSIXct("2018-12-10 00:00:00")) + 24*60*60,
by=900),
start = "start_int",
id="new_id",
episode ="episode")
df3$start_int <- as.POSIXct(df3$start_int, origin = "1970-01-01", tz = "Australia/Brisbane")
df3$start_date <- as.POSIXct(df3$start_date, origin = "1970-01-01", tz = "Australia/Brisbane")
df3$end_date <- as.POSIXct(df3$end_date, origin = "1970-01-01", tz = "Australia/Brisbane")
Есть какие-нибудь указатели на лучший способ решения такой задачи?