R:从多个时间跨度创建时间序列

R: Creating a timeseries out of multiple timespans

我有以下形式的数据:

startDate             | endDate              | type
---------------------------
2017-04-11 10:45:06.0 |2017-04-11 10:47:30.0 | Type1
2017-04-11 10:15:01.0 |2017-04-11 11:47:33.0 | Type2
2017-04-11 10:44:09.0 |2017-04-11 10:50:00.0 | Type1
2017-04-11 10:35:06.0 |2017-04-11 10:53:33.0 | Type2

我的目标是在 time-series 中将其可视化。但据我所知,我需要矢量形式的数据来描述每个时间点的频率。 是否有一个库或一种很好的方法可以将我的数据转换成这种形式?或者我是否必须检查我想要可视化的每个时间点的每个条目?

基本上图表应该看起来像这样: (请注意图片与示例数据不符)

OP 已指定他有许多具有给定开始和结束时间的事件,并且他想要描述覆盖范围,即每个点的事件数及时。

使用 Bioconductor 的 IRanges 包(参见第 5.5 节 计算重叠范围 IRanges vignette).

但是,Q 中的图表表明使用 binning 的解决方案对于 OP 来说是可以接受的。分箱意味着计算与时间栅格重叠的事件数。这类似于创建直方图,只是特定事件可能跨越多个 bin。

data.table 包中的 foverlaps() 函数可用于合并过程。但首先我们需要准备一些虚拟数据来演示。

正在创建虚拟数据

我们创建两种类型的事件。 Type1 是较少但较长的事件,Type2 是数量较多但较短的事件。

set.seed(1L)
n1 <- 10L
n2 <- n1 * 10L
ref_time <- lubridate::ymd_hms("2017-4-26 10:11:12")
DT <- rbindlist(list(
  data.table(t = ref_time + rnorm(n1) * 60 * 60,
       d = rnorm(n1) * 60 * 60,
       type = "Type1"),
  data.table(t = ref_time + rnorm(n2) * 60 * 60,
       d = rnorm(n2) * 60 * 6,
       type = "Type2")
))
# 
DT[, c("start", "end") := .(pmin(t, t + d), pmax(t, t + d))]  
setkey(DT, start, end)
# add row numbers
DT[, rn := .I]

DT
#                       t           d  type               start                 end  rn
#  1: 2017-04-26 08:11:50   -64.64035 Type2 2017-04-26 08:10:45 2017-04-26 08:11:50   1
#  2: 2017-04-26 08:22:54   -91.80973 Type2 2017-04-26 08:21:22 2017-04-26 08:22:54   2
#  3: 2017-04-26 08:39:47  -528.21001 Type2 2017-04-26 08:30:58 2017-04-26 08:39:47   3
#  4: 2017-04-26 08:42:57   -13.54830 Type2 2017-04-26 08:42:43 2017-04-26 08:42:57   4
#  5: 2017-04-26 09:21:03 -2236.46609 Type1 2017-04-26 08:43:47 2017-04-26 09:21:03   5
# ---                                                                                  
#106: 2017-04-26 11:52:07   183.63903 Type2 2017-04-26 11:52:07 2017-04-26 11:55:11 106
#107: 2017-04-26 11:57:14   899.15817 Type2 2017-04-26 11:57:14 2017-04-26 12:12:13 107
#108: 2017-04-26 12:10:01  -387.06923 Type2 2017-04-26 12:03:34 2017-04-26 12:10:01 108
#109: 2017-04-26 12:21:33    74.71380 Type2 2017-04-26 12:21:33 2017-04-26 12:22:48 109
#110: 2017-04-26 12:35:17   153.03614 Type2 2017-04-26 12:35:17 2017-04-26 12:37:50 110

这更好看:

library(ggplot2)
ggplot(DT, aes(x = start, y = rn, xend = end, yend = rn, colour = type)) + 
  geom_segment(size = 1) + theme_bw()

为分箱创建时间栅格

我们创建一个时间间隔为 15 分钟的时间栅格

bin_start_time <- DT[, lubridate::floor_date(min(start), unit = "hour")]
bin_end_time<- DT[, lubridate::ceiling_date(max(end), unit = "hour")]
# time interval can be adjusted 
bin_step <- as.difftime(15L, units = "mins")
bin_cuts <- seq(bin_start_time, bin_end_time, by = bin_step)
bins <- data.table(start = head(bin_cuts, -1L),
                   end   = tail(bin_cuts, -1L),
                   key = "start,end")
# add row numbers
bins[, bn := .I]

head(bins)
#                 start                 end bn
#1: 2017-04-26 08:00:00 2017-04-26 08:15:00  1
#2: 2017-04-26 08:15:00 2017-04-26 08:30:00  2
#3: 2017-04-26 08:30:00 2017-04-26 08:45:00  3
#4: 2017-04-26 08:45:00 2017-04-26 09:00:00  4
#5: 2017-04-26 09:00:00 2017-04-26 09:15:00  5
#6: 2017-04-26 09:15:00 2017-04-26 09:30:00  6

合并

分箱需要使用 foverlaps() 找到 DT 中给出的事件与时间栅格的所有重叠,并计算重叠的数量。这可以在一条语句中完成:

result <- foverlaps(DT, bins)[, .N, by = .(type, start, end)]

result[18:24]
#    type               start                 end  N
#1: Type1 2017-04-26 11:00:00 2017-04-26 11:15:00  5
#2: Type1 2017-04-26 11:15:00 2017-04-26 11:30:00  4
#3: Type1 2017-04-26 11:30:00 2017-04-26 11:45:00  4
#4: Type1 2017-04-26 11:45:00 2017-04-26 12:00:00  2
#5: Type2 2017-04-26 09:45:00 2017-04-26 10:00:00 14
#6: Type2 2017-04-26 10:00:00 2017-04-26 10:15:00 17
#7: Type2 2017-04-26 10:15:00 2017-04-26 10:30:00 11

请注意,频率是按类型单独计算的。

可视化

ggplot(result, aes(start + bin_step/2, N, group = type, colour = type)) + 
  geom_line(size = 1) + expand_limits(y = 0) + theme_bw() 

此处,数据点位于时间栅格间隔的中间。

另一种可能是geom_step():

ggplot(result, aes(start, N, group = type, colour = type)) + 
  geom_step(size = 1) + expand_limits(y = 0) + theme_bw()