#r #timestamp #lubridate
Вопрос:
Во фрейм данных, приведенный ниже, я хочу включить столбец с разницей между временем начала строки и временем окончания предыдущей строки. Так как apply не позволяет использовать индексы и следует избегать циклов в R, у меня заканчиваются идеи о том, как построить эту функцию. Вот пример ввода и как он должен выглядеть в конце
| start_time | end_time | Waiting_Time |
| ------------------- | ------------------- | ------------ |
| 1970-01-12 07:24:00 | 1970-01-12 07:24:00 | 0 |
| 1970-01-12 07:24:00 | 1970-01-12 07:30:00 | 0 |
| 1970-01-12 07:34:00 | 1970-01-12 07:47:00 | 4 |
| 1970-01-12 07:45:00 | 1970-01-12 07:45:00 | 15 |
| 1970-01-12 07:47:00 | 1970-01-12 07:52:00 | 2 |
| 1970-01-12 07:58:00 | 1970-01-12 07:58:00 | 6 |
| 1970-01-12 07:58:00 | 1970-01-12 08:12:00 | 0 |
| 1970-01-12 08:12:00 | 1970-01-12 07:30:00 | 0 |
| 1970-01-12 07:24:00 | 1970-01-12 08:20:00 | 72 |
| 1970-01-12 08:26:00 | 1970-01-12 08:26:00 | 6 |
В случае, если время начала до времени окончания предыдущей строки, функция должна сначала просмотреть две строки (см. Пример в строках 4 и 9).
structure(list(Case_id = c(501L, 501L, 501L, 501L, 501L, 501L,
501L, 501L, 501L, 501L, 501L, 501L, 501L, 501L, 501L), start_time = structure(c(977040,
977040, 978300, 977640, 978420, 979080, 979080, 979920, 980760,
980760, 981360, 982260, 982260, 985200, 985980), class = c("POSIXct",
"POSIXt"), tzone = "UTC"), end_time = structure(c(977040, 977400,
978300, 978420, 978720, 979080, 979920, 980400, 980760, 981360,
981720, 982260, 985200, 985680, 985980), class = c("POSIXct",
"POSIXt"), tzone = "UTC"), Resource_id = c("System", "Tester5",
"System", "SolverC2", "Tester3", "System", "SolverC1", "Tester2",
"System", "SolverC1", "Tester5", "System", "SolverC3", "Tester1",
"System"), Activity_id = c("Register", "Analyze Defect", "Inform User",
"Repair (Complex)", "Test Repair", "Restart Repair", "Repair (Complex)",
"Test Repair", "Restart Repair", "Repair (Complex)", "Test Repair",
"Restart Repair", "Repair (Complex)", "Test Repair", "Archive Repair"
), Log = c("ORIG", "ORIG", "ORIG", "ORIG", "ORIG", "ORIG", "ORIG",
"ORIG", "ORIG", "ORIG", "ORIG", "ORIG", "ORIG", "ORIG", "ORIG"
), ExecTime = structure(c(0, 6, 0, 13, 5, 0, 14, 8, 0, 10, 6,
0, 49, 8, 0), class = "difftime", units = "secs")), row.names = c(4121L,
4122L, 4123L, 4124L, 4125L, 4126L, 4127L, 4129L, 4130L, 4132L,
4133L, 4134L, 4135L, 4136L, 4137L), class = "data.frame")
Ответ №1:
Вы можете получить доступ к строке до (или после) с помощью функции (функций) {dplyr} lead () (или lag ()).
Например:
library(dplyr)
df %>%
mutate(delta = start_time - lag(end_time)) %>%
select(start_time, end_time, delta) # to truncate payload, remove in your case
Это дает:
start_time end_time delta
4121 1970-01-12 07:24:00 1970-01-12 07:24:00 NA secs
4122 1970-01-12 07:24:00 1970-01-12 07:30:00 0 secs
4123 1970-01-12 07:45:00 1970-01-12 07:45:00 900 secs
4124 1970-01-12 07:34:00 1970-01-12 07:47:00 -660 secs
4125 1970-01-12 07:47:00 1970-01-12 07:52:00 0 secs
4126 1970-01-12 07:58:00 1970-01-12 07:58:00 360 secs
4127 1970-01-12 07:58:00 1970-01-12 08:12:00 0 secs
4129 1970-01-12 08:12:00 1970-01-12 08:20:00 0 secs
4130 1970-01-12 08:26:00 1970-01-12 08:26:00 360 secs
4132 1970-01-12 08:26:00 1970-01-12 08:36:00 0 secs
4133 1970-01-12 08:36:00 1970-01-12 08:42:00 0 secs
4134 1970-01-12 08:51:00 1970-01-12 08:51:00 540 secs
4135 1970-01-12 08:51:00 1970-01-12 09:40:00 0 secs
4136 1970-01-12 09:40:00 1970-01-12 09:48:00 0 secs
4137 1970-01-12 09:53:00 1970-01-12 09:53:00 300 secs
Очевидно, что первое время начала не имеет предыдущей записи и, следовательно, приводит к NA. Возможно, вы захотите обработать этот случай по-другому с помощью условной операции или установить это значение равным нулю.
Для большего контроля над вашими временными интервалами прочитайте раздел Разное время(…, единицы = …). Здесь вы можете установить единицы измерения в «минуты», если это лучший шаг для вас.
Комментарии:
1. Именно то, что я искал, спасибо!
2. Примечание: Если вам нужно продолжить математику, вы можете избавиться от временных единиц (здесь секунд), приведя дельту к числовому значению!
Ответ №2:
Базовый вариант R с использованием difftime
df <- transform(df, Waiting_Time = c(0, difftime(start_time[-1] ,
end_time[-nrow(df)], units = "mins")))
df$Waiting_Time
#[1] 0 0 15 -11 0 6 0 0 6 0 0 9 0 0 5