我正在处理描述具有开始和结束时间的事件的数据。例如,它可以采用以下形式:
我想将此数据转换为可以定期计数事件发生次数的形式,以便能够回答从13:15:00
到{{1}发生了多少事件的问题。 }和13:29:59
至13:30:00
等。在上面的示例中,仅使用开始时间就可以将第二条记录计入第一个时隙,但是即使集成了结束时间,也不会在第二个规则间隔中将其记录为“进行中”。
要以15分钟的间隔工作,我想出了一个笨拙的解决方案,该解决方案使用13:45:00
将数据集“扩展”到tidyr::uncount
在24小时内间隔15分钟,然后过滤指定间隔内的数据
24*4=96
这为我提供了所需格式的数据:
但是我感觉必须有一种更聪明的方法来做到这一点。例如,对于非常大的数据集和/或当时间间隔小时(我认为),扩展将不是很好的解决方案。将其扩展为可以工作几天(可能会很痛苦)。
在Stata中,也可以使用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 )
命令来完成类似的操作。我尝试修改stsplit
包中的survSplit
,但最终也得到了很多记录:
survival
是否有任何指向实现此类任务的更好方法的指针?
答案 0 :(得分:2)
您也可以通过将每个start_time视为添加一个活动事件,将每个end_time视为将活动事件减少一个来解决此问题。这种方法使您可以在任何给定的瞬间识别活动事件,并且可以很好地扩展。 (我使用类似的方法来计数数百万个事件,并且基本上是瞬时的。)
BackHandler.exitApp()
如果您还希望定期评估活动计数,则可以将这些时间间隔集成到输出数据框中,如下所示:
df2 <- df1 %>%
gather(type, time, start_date:end_date) %>%
mutate(event_chg = if_else(type == "start_date", 1, -1)) %>%
arrange(time) %>%
mutate(active_events = cumsum(event_chg))
df2
# A tibble: 4 x 5
# id type time event_chg active_events
# <dbl> <chr> <dttm> <dbl> <dbl>
#1 2 start_date 2018-12-10 13:29:37 1 1
#2 2 end_date 2018-12-10 14:02:37 -1 0
#3 1 start_date 2018-12-10 14:45:51 1 1
#4 1 end_date 2018-12-10 14:59:04 -1 0
ggplot(df2, aes(time, active_events)) + geom_step()
然后可以直接绘制这些计数,或者过滤输出数据框以查看它们。在这种情况下,事件ID 1完全在两个15分钟的间隔之间发生。
df2b <- df1 %>%
gather(type, time, start_date:end_date) %>%
mutate(event_chg = if_else(type == "start_date", 1, -1)) %>%
# NEW SECTION HERE
bind_rows(data_frame(type = "marker",
time = seq.POSIXt(ymd_h(2018121013, tz = "Australia/Brisbane"),
ymd_h(2018121016, tz = "Australia/Brisbane"),
by = 15*60), # 15 minutes of seconds = 15*60
event_chg = 0)) %>%
# END OF NEW SECTION
arrange(time) %>%
mutate(active_events = cumsum(event_chg))