R: Создание таймсерий из нескольких промежутков времени

У меня есть данные в следующем виде:

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

Моя цель - визуализировать это за время - серия. Но насколько я понимаю, мне нужны данные в виде вектора, показывающего частоты на момент времени. Есть ли библиотека или хороший способ преобразовать мои данные в эту форму? Или мне нужно проверять каждую запись для каждого момента времени, который я хочу визуализировать?

В основном график должен выглядеть примерно так: (Обратите внимание, что изображение не соответствует данным примера)

введите здесь описание изображения


person Abaddon666    schedule 26.04.2017    source источник
comment
Подобные проблемы я решил с помощью foverlaps() из пакета data.table. Вам необходимо указать временные интервалы, за которые вы хотите агрегировать. foverlaps()находит пересечения, которые можно подсчитать.   -  person Uwe    schedule 26.04.2017
comment
Ваш образец данных кажется неправильным, потому что в строках 3 и 4 даты окончания раньше, чем даты начала. Кроме того, выборочные данные охватывают только минуты или часы в течение одного дня, в то время как диаграмма отображает 3 года.   -  person Uwe    schedule 26.04.2017
comment
@UweBlock конечно ты прав. я просто скопировал некоторые данные без учета их действительности. Исходные данные намного сложнее (и достоверны). Изображение является лишь произвольным примером. Я посмотрю foverlaps() и опубликую свои выводы!   -  person Abaddon666    schedule 26.04.2017


Ответы (1)


OP указал, что у него есть несколько событий с заданным временем начала и окончания и что он хочет изобразить охват, то есть количество событий для каждого момента времени.

Точное решение возможно с использованием пакета Bioconductor IRanges (см. Раздел 5.5 Подсчет диапазонов перекрытия в IRanges vignette).

Однако график в Q предполагает, что решение с использованием биннинга приемлемо для OP. Биннинг означает, что подсчитывается количество событий, которые перекрываются с временным растром. Это похоже на создание гистограммы, за исключением того, что конкретное событие может охватывать более одной ячейки.

Функция foverlaps() из пакета data.table может использоваться для процесса биннинга. Но сначала нам нужно подготовить фиктивные данные для демонстрации.

Создание фиктивных данных

Мы создаем два типа событий. 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

Биннинг

Для биннинга требуется найти все совпадения событий, указанных в DT, с растром времени, используя foverlaps() и подсчитывая количество перекрытий. Это можно сделать одним оператором:

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()

введите здесь описание изображения

person Uwe    schedule 26.04.2017
comment
Спасибо за этот замечательный ответ! Это именно то, что мне было нужно, и я смог использовать его по своим средствам с очень небольшими корректировками! - person Abaddon666; 27.04.2017
comment
@ Abaddon666 Отлично, я на это надеялся. - person Uwe; 27.04.2017