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()
我有以下形式的数据:
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()