Расчет совокупного времени в R

У меня есть кадр данных, который выглядит так:

     POI   LOCAL.DATETIME
1    1     2017-07-11 15:02:13
2    1     2017-07-11 15:20:28
3    2     2017-07-11 15:20:31
4    2     2017-07-11 15:21:13
5    3     2017-07-11 15:21:18
6    3     2017-07-11 15:21:21
7    2     2017-07-11 15:21:25
8    2     2017-07-11 15:21:59
9    1     2017-07-11 15:22:02
10   1     2017-07-11 15:22:05

Я хочу иметь возможность рассчитать (возможно, с помощью смазки) совокупное время, проведенное в каждой точке интереса, и объединить их в таблицу, которая выглядит примерно так:

     POI   TOTAL.TIME
1    1     00:18:18
2    2     00:01:11
3    3     00:00:03

Кроме того, я не уверен, как работать со временем между POI, например, с 3 секундами между строками 2 и 3. Я думаю, может быть, мне нужно рассчитать время от строки 1 до строки 3, а не от строки 1 до строки 2.


person Sam    schedule 13.07.2017    source источник


Ответы (2)


Чтобы получить общее время в периодах каждой группы, вам сначала нужно создать индекс группы. Я использую rleid из data.table Затем вы можете рассчитать общее время, проведенное в каждой из этих групп, а затем суммировать по начальной точке интереса, используя sum.

df <- read.table(text="     POI   LOCAL.DATETIME
1     '2017-07-11 15:02:13'
1     '2017-07-11 15:20:28'
2     '2017-07-11 15:20:31'
2     '2017-07-11 15:21:13'
3     '2017-07-11 15:21:18'
3     '2017-07-11 15:21:21'
2     '2017-07-11 15:21:25'
2     '2017-07-11 15:21:59'
1     '2017-07-11 15:22:02'
1     '2017-07-11 15:22:05'",
                 header=TRUE,stringsAsFactors=FALSE)
df$LOCAL.DATETIME <- as.POSIXct(df$LOCAL.DATETIME)

library(dplyr)
df%>%
  mutate(grp=data.table::rleid(POI))%>%
  group_by(grp)%>%
  summarise(POI=max(POI),TOTAL.TIME=difftime(max(LOCAL.DATETIME),
                                     min(LOCAL.DATETIME),units="secs"))%>%
  group_by(POI)%>%
  summarise(TOTAL.TIME=sum(TOTAL.TIME))

# A tibble: 3 × 2
    POI TOTAL.TIME
  <int>     <time>
1     1  1098 secs
2     2    76 secs
3     3     3 secs

Чтобы получить минуты и секунды, вы можете использовать as.period из lubridate:

library(lubridate)
df%>%
  mutate(grp=data.table::rleid(POI))%>%
  group_by(grp)%>%
  summarise(POI=max(POI),TOTAL.TIME=difftime(max(LOCAL.DATETIME),
                                    min(LOCAL.DATETIME),units="secs"))%>%
  group_by(POI)%>%
  summarise(TOTAL.TIME=sum(TOTAL.TIME))%>%
  mutate(TOTAL.TIME =as.period((TOTAL.TIME), unit = "sec"))

    POI   TOTAL.TIME
  <int> <S4: Period>
1     1      18M 18S
2     2       1M 16S
3     3           3S
person Pierre Lapointe    schedule 13.07.2017
comment
Разве этот метод не будет принимать строку 10 — строку 1, строку 8 — строку 3 и строку 6 — строку 5? Мне нужно уметь делать (строка 2 — строка 1) + (строка 10 — строка 9) и т. д. - person Sam; 13.07.2017
comment
@P Lapointe Большое спасибо, это именно то, что я искал. - person Sam; 14.07.2017

Другой вариант data.table состоит в том, чтобы создать группы из 2 строк для каждого POI, взять разницу во времени между ними и, наконец, суммировать ее с помощью POI:

library(data.table)

dt <- as.data.table(df)
dt[, grp2 := (seq_len(.N)+1) %/% 2, by = POI]
dt[, time_diff := difftime(LOCAL.DATETIME, shift(LOCAL.DATETIME), unit = "min"), by = .(POI, grp2)]
dt[ , .(TOTAL.TIME = sum(time_diff, na.rm = T)), by = POI]

#   POI     TOTAL.TIME
#1:   1 18.300000 mins
#2:   2  1.266667 mins
#3:   3  0.050000 mins
person Mike H.    schedule 13.07.2017