Разница между метками времени за день с ночным перерывом в R

Я пытаюсь рассчитать разницу между двумя временными метками и агрегировать их по дате и uid. Я рассчитал разницу для каждого временного интервала, но хотел бы разделить эти интервалы на день (поэтому создайте какой-нибудь полуночный перерыв). Учитывая, что разница между временными интервалами проходит в одночасье, у меня возникли проблемы с вычислением времени между каждым интервалом в день и, следовательно, этих перерывов.

Вот фрагмент моих данных:

df <- structure(list(
start_timestamp = c("2013-03-27 01:21:23", "2013-03-28 07:11:58", "2013-03-28 09:09:56", "2013-03-29 00:19:32", "2013-03-29 02:22:53"), 
uid = c(0, 0, 0, 0, 0),
prev_start_timestamp = c("2013-03-27 01:13:26", "2013-03-27 05:58:53", "2013-03-28 08:41:41", "2013-03-28 10:47:01", "2013-03-29 02:17:26")), row.names = c("1", "2", "3", "4", 
"5"), class = "data.frame")

Обычно я работал с этим выводом и использовал dplyr или data.table для агрегирования данных за день. но теперь эта разница во времени просто вычисляется путем вычитания меток времени. В то время как я хочу разделить эти различия в день.

вывод, нежелательный

Ожидаемый результат будет примерно таким: Но этот не делает никаких ночных перерывов, чтобы разделить время каждый день. Этот вывод указывает, что некоторые дни имеют временные интервалы более 24 часов, что, конечно, невозможно..

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


person Onno van der Horst    schedule 03.06.2020    source источник
comment
Пожалуйста, покажите ожидаемый результат для вашего примера ввода.   -  person Roland    schedule 03.06.2020
comment
Не очень полезно. Я именно хотел увидеть вывод данных с ночными перерывами.   -  person Roland    schedule 03.06.2020
comment
Фрагмент данных выглядит нерепрезентативно, как должно рассчитываться время звонков? Является ли prev_start_timestamp временем начала вызова, а start_timestamp временем окончания?   -  person Daniel O    schedule 03.06.2020
comment
Я не знаю, как это сделать, поэтому и спрашиваю здесь.   -  person Onno van der Horst    schedule 03.06.2020
comment
@DanielO Действительно, prev_start_time — это время начала, а start_timestamp — время окончания.   -  person Onno van der Horst    schedule 03.06.2020


Ответы (1)


Вот вариант с использованием data.table::foverlaps:

#create a data.table of daily intervals
datetimes <- DT[, seq(trunc(min(start), "days"), trunc(max(end)+24*60*60), "days")]
days <- data.table(start=datetimes[-length(datetimes)], end=datetimes[-1L], key=cols)

#set keys on original dataset and perform overlaps before calculating usage per day
setkeyv(DT, cols)
foverlaps(DT, days)[,
    .(phone_usage=sum(pmin(i.end, end) - pmax(i.start, start))), 
    .(uid, date=start)]

вывод (остается OP, чтобы проверить вручную, правильно ли это для набора данных образца):

   uid       date phone_usage
1:   0 2013-03-27  65344 secs
2:   0 2013-03-28  75192 secs
3:   0 2013-03-29   1499 secs

данные (обратите внимание, что я сократил имена столбцов OP):

library(data.table)
DT <- data.table(
    end = c("2013-03-27 01:21:23", "2013-03-28 07:11:58", "2013-03-28 09:09:56", "2013-03-29 00:19:32", "2013-03-29 02:22:53"), 
    uid = c(0, 0, 0, 0, 0),
    start = c("2013-03-27 01:13:26", "2013-03-27 05:58:53", "2013-03-28 08:41:41", "2013-03-28 10:47:01", "2013-03-29 02:17:26"))
cols <- c('start', 'end')
DT[, (cols) := lapply(.SD, as.POSIXct, format="%Y-%m-%d %T"), .SDcols=cols]
person chinsoon12    schedule 03.06.2020