В R: сгруппировать последовательность событий на основе их идентификатора и расчета разницы во времени между первым и последним увиденным событием. - PullRequest
0 голосов
/ 11 февраля 2020

В приведенном ниже кадре данных у меня есть последовательности событий, которые могут повторяться до тех пор, пока не будет сгенерировано новое событие. Я хотел бы использовать функцию, которая помогает мне после выбора этих похожих строк, вычисляет разницу между timestamp_end последнего увиденного события *1003* и timestamp_start первого события .

Фрейм данных:

DF1 <- data.frame(segment_id = c(1, 1, 1, 1, 2 , 3, 4), first_event= c("a", "a", "a","a", "a", "b","c" ), second_event = c("a", "a","a","a", "b", "c", "c"), timestamp_start = c("2019-06-06 11:47:00","2019-06-06 12:59:38", "2019-06-06 13:01:03", "2019-06-06 14:47:03   ", "2019-06-06 18:47:00", "2019-06-06 22:47:00", "2019-06-07 02:47:00") , timestamp_end = c("2019-06-06 12:59:38", "2019-06-06 13:01:03", "2019-06-06 14:47:03", "2019-06-06 18:47:00", "2019-06-06 22:47:00    ", "2019-06-07 02:47:00", "2019-06-07 06:47:00"))


segment_id   first_event   second_event          timestamp_start            timestamp_end

  1            a              a                2019-06-06 11:47:00        2019-06-06 12:59:38
  1            a              a                2019-06-06 12:59:38        2019-06-06 13:01:03
  1            a              a                2019-06-06 13:01:03        2019-06-06 14:47:03
  1            a              a                2019-06-06 14:47:03        2019-06-06 18:47:00
  2            a              b                2019-06-06 18:47:00        2019-06-06 22:47:00
  3            b              c                2019-06-06 22:47:00        2019-06-07 02:47:00
  4            c              c                2019-06-07 02:47:00        2019-06-07 06:47:00

Итак, я попробовал пакет dplyr и функции group_by() и mutate(). Однако я не уверен, какая функция может помочь мне получить продолжительность.

DF2 <- DF1 %>%
   group_by(segment_id)%>%
   mutate("duration" = difftime(????) , units = 'hours')

Окончательный результат, который я ищу, так как DF2 должен выглядеть следующим образом:

>DF2
segment_id   first_event   second_event          timestamp_start            timestamp_end        duration

  1            a              a                2019-06-06 11:47:00        2019-06-06 18:47:00      7        
  2            a              b                2019-06-06 18:47:00        2019-06-06 22:47:00      4
  3            b              c                2019-06-06 22:47:00        2019-06-07 02:47:00      4
  4            c              c                2019-06-07 02:47:00        2019-06-07 06:47:00      4

Буду признателен за вашу помощь в этом.

Ответы [ 3 ]

2 голосов
/ 11 февраля 2020
library(lubridate)

DF1 %>%
    mutate_at(vars(timestamp_start, timestamp_end)
              , function(x) ymd_hms(as.character(x))) %>%
    group_by(segment_id) %>%
    summarise(first_event = first(first_event)
              , second_event = last(second_event)
              , timestamp_start = first(timestamp_start)
              , timestamp_end = last(timestamp_end)
              , duration = max(timestamp_end) - min(timestamp_start))

  segment_id first_event second_event timestamp_start     timestamp_end       duration
       <dbl> <fct>       <fct>        <dttm>              <dttm>              <drtn>  
1          1 a           a            2019-06-06 11:47:00 2019-06-06 18:47:00 7 hours 
2          2 a           b            2019-06-06 18:47:00 2019-06-06 22:47:00 4 hours 
3          3 b           c            2019-06-06 22:47:00 2019-06-07 02:47:00 4 hours 
4          4 c           c            2019-06-07 02:47:00 2019-06-07 06:47:00 4 hours 
2 голосов
/ 11 февраля 2020

Опция с использованием data.table:

setDT(DF1)[, .(timestamp_start=min(timestamp_start), timestamp_end=max(timestamp_end)), .(segment_id, first_event, second_event)][, 
    duration := difftime(timestamp_end, timestamp_start, units="hours")][]

данные:

library(data.table)
cols <- c("timestamp_start", "timestamp_end")
setDT(DF1)[, (cols) := lapply(.SD, as.POSIXct, format="%Y-%m-%d %T"), .SDcols=cols]
1 голос
/ 11 февраля 2020

Мы можем изменить тип столбца timestamp_start и timestamp_end на POSIXct, group_by segment_id, first_event и second_event, получить first timestamp_start и last timestamp_end и посчитайте разницу в часах между ними.

library(dplyr)

DF1 %>%
  mutate_at(vars(starts_with('timestamp')), as.POSIXct) %>%
  group_by(segment_id, first_event, second_event) %>%
  summarise(timestamp_start = first(timestamp_start), 
            timestamp_end = last(timestamp_end),
            duration = as.numeric(difftime(timestamp_end, 
                      timestamp_start, units = "hours")))

#     segment_id first_event second_event timestamp_start     timestamp_end       duration
#       <dbl> <fct>       <fct>        <dttm>              <dttm>                 <dbl>
#1          1 a           a            2019-06-06 11:47:00 2019-06-06 18:47:00        7
#2          2 a           b            2019-06-06 18:47:00 2019-06-06 22:47:00        4
#3          3 b           c            2019-06-06 22:47:00 2019-06-07 02:47:00        4
#4          4 c           c            2019-06-07 02:47:00 2019-06-07 06:47:00        4
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...