Вот подход data.table
к вашему вопросу.
Он использует data.table::rleid()
для создания групп на основе условия v1 or v2 > 110
.Затем он суммирует строки, в которых это условие выполняется, путем вычитания первой временной отметки каждой группы из последней временной отметки каждой группы.Это приводит к столбцу duration
разностей по группам.
В качестве альтернативы, вы можете рассчитать всю сумму всей продолжительности.format()
используется для вывода ответа в виде строки вместо difftime.
пример данных
library(data.table)
DT <- fread("timestamp v1 v2
14-05-2019T04:28 112.2 111.0
14-05-2019T04:30 112.2 110.9
14-05-2019T04:39 101.4 101.8
14-05-2019T04:40 108.0 108.8
14-05-2019T04:45 101.1 101.5
14-05-2019T04:46 100.8 101.2
14-05-2019T05:32 111.6 111.5
14-05-2019T05:36 111.5 111.5
14-05-2019T05:39 111.5 111.5
14-05-2019T05:41 111.5 111.5
14-05-2019T05:46 111.5 111.4
14-05-2019T05:46 111.5 111.3
14-05-2019T05:47 111.5 111.3
14-05-2019T05:51 111.2 111.2
14-05-2019T05:56 111.2 111.2
14-05-2019T05:57 111.2 111.2")
#create timestamps
DT[, timestamp := as.POSIXct( timestamp, format = "%d-%m-%YT%H:%M" )]
код
#create groups based on v1|v2 > 110
DT[, group_id := rleid( v1 > 110 | v2 > 110 ) ][]
#group by group_id, only on rows where v1 or v2 > 110
DT[ v1 > 110 | v2 > 110, ][, .(duration = max(timestamp) - min(timestamp) ), by = .(group_id)]
выход
# group_id duration
# 1: 1 2 mins
# 2: 3 25 mins
альтернативное резюме
заменить последнюю строку кода на:
format(
sum(
DT[ v1 > 110 | v2 > 110, ][, .(duration = max(timestamp) - min(timestamp) ), by = .(group_id)]$duration
)
)
, который дает общее количество всех «групп».
#27 mins
обновление на основе вопроса в комментарии
Чтобы включить начало и конец каждого периода, используйте:
DT[ v1 > 110 | v2 > 110, ][, .(start = min(timestamp),
end = max(timestamp),
duration = max(timestamp) - min(timestamp) ),
by = .(group_id)][,group_id := NULL]
# start end duration
# 1: 2019-05-14 04:28:00 2019-05-14 04:30:00 2 mins
# 2: 2019-05-14 05:32:00 2019-05-14 05:57:00 25 mins