длительность разделения таблицы данных по датам - PullRequest
1 голос
/ 28 апреля 2020

У меня есть данные с 2 столбцами. Один для отметки времени, а другой для условия. Я пытаюсь выяснить продолжительность, в течение которой возникает состояние. Я могу получить продолжительность. Но если мое состояние будет через два дня, тогда я буду получать более 24 часов и все. Мне нужно разбить его на соответствующие даты. Я использую rleid для группировки, а затем я нахожу продолжительность (max(timestamp) - min(timestamp) в каждой группе, которая удовлетворяет условию. Затем я наконец aggregate это для sum).

             timestamp  condition
    2020-01-01 10:10:13 0
    2020-01-01 10:11:23 1
    2020-01-01 10:14:45 1
    2020-01-01 11:23:02 1
    2020-01-01 11:33:14 1
    2020-01-01 16:10:13 0
    2020-01-01 18:34:12 1
    2020-01-01 20:10:33 1
    2020-01-01 23:04:56 1
    2020-01-02 10:14:45 1
    2020-01-02 11:23:02 1
    2020-01-02 11:33:14 0
    2020-01-02 16:10:13 0

Поиск продолжительности, когда условие 1. Ожидаемый результат:

Date            Duration
2020-01-01      05:52:35
2020-01-02      11:23:02

Что я получаю, когда выполняю группировку и нахожу длительность:

 Date            Duration
2020-01-01      18:10:41

Проблема заключается в группировке, поскольку rleid группирует независимо от даты. На самом деле, если условие происходит в течение двух дней непрерывно, то оно должно быть ограничено до 23:59:59 для первого дня и начинаться с 00:00:00 во второй день. Это должно происходить в течение любого количества дней.

Мой код:

fdata = data[, group_id := rleid(condition == 1)][]
out = fdata[(condition == 1),][,.(start = as.Date(min(timestamp)),
         duration = as.numeric(max(timestamp) - min(timestamp),units='mins')),by = .((group_id)][,group_id := NULL]

Ответы [ 2 ]

2 голосов
/ 28 апреля 2020

Вот вариант:

DT[, g := rleid(id, as.IDate(timestamp), condition)][
    condition==1L, duration := as.numeric(timestamp[.N] - timestamp[1L], units='secs'), g]

unique(DT, by="g")[condition==1L & duration > 0, .(Duration=sum(duration)), .(id, date=as.IDate(timestamp))]

Альтернативный подход:

DT[, g := rleid(id, as.IDate(timestamp), condition)][
    condition==1L, .(id=id[1L], date=as.IDate(timestamp)[1L],
        dft=as.numeric(timestamp[.N] - timestamp[1L], units='secs')), g][
            dft > 0, .(Duration==sum(dft)), .(id, date)]

вывод:

   id       date Duration
1:  1 2020-01-01    21155
2:  1 2020-01-02     4097

данные:

library(data.table)
DT <- fread("id,timestamp,condition
1,2020-01-01 10:10:13,0
1,2020-01-01 10:11:23,1
1,2020-01-01 10:14:45,1
1,2020-01-01 11:23:02,1
1,2020-01-01 11:33:14,1
1,2020-01-01 16:10:13,0
1,2020-01-01 18:34:12,1
1,2020-01-01 20:10:33,1
1,2020-01-01 23:04:56,1
1,2020-01-02 10:14:45,1
1,2020-01-02 11:23:02,1
1,2020-01-02 11:33:14,0
1,2020-01-02 16:10:13,0")
DT[, timestamp := as.POSIXct(timestamp, format="%Y-%m-%d %T")]
1 голос
/ 28 апреля 2020

Мы можем использовать rleid в столбце «условие»

library(data.table)
library(lubridate)
out <- setDT(df1)[,  .(Duration = max(timestamp) - min(timestamp)),
        .(Date = as.IDate(timestamp),
    grp = rleid(condition), condition)
     ][as.logical(condition)][, .(Duration = sum(Duration)), .(Date)]

out[, Duration := seconds_to_period(Duration)][]
#       Date   Duration
#1: 2020-01-01 5H 52M 35S
#2: 2020-01-02  1H 8M 17S

data

df1 <- structure(list(timestamp = structure(c(1577891413, 1577891483, 
    1577891685, 1577895782, 1577896394, 1577913013, 1577921652, 1577927433, 
    1577937896, 1577978085, 1577982182, 1577982794, 1577999413), class = c("POSIXct", 
    "POSIXt"), tzone = ""), condition = c(0L, 1L, 1L, 1L, 1L, 0L, 
    1L, 1L, 1L, 1L, 1L, 0L, 0L)), row.names = c(NA, -13L), class = "data.frame")
...