Вычислить продолжительность между вводами и оптимизацией кода выхода

#r

#r

Вопрос:

У меня есть некоторые данные с:

  • Уникальный идентификатор
  • Действие (ввод или выход)
  • Временная метка
  • Идентификатор здания и некоторые другие столбцы.

Я пытаюсь рассчитать время, проведенное в здании, на основе входа, выхода, идентификатора здания и уникального идентификатора (номера автомобиля).

Прямо сейчас я сортирую свой фрейм данных по уникальному идентификатору, а затем по дате и применяю этот алгоритм:

     For each row {
        if row.type = 'entry' and nextRow.type = 'exit' and row.uid = nextRow.uid {
        Calculate time difference and add this data to another df.
        }
    }
  

Для запуска требуется некоторое время, хотя у меня всего 6000 строк…
Я не очень знаком с R, и я думаю, что есть способы ускорить это…

Код выглядит следующим образом:

 # Sort rows: 
BldActivity <- BldActivity[order(BldActivity$UniqueId, BldActivity$DateOfEvent),]


df = data.frame(NULL)
DurationOfStay <- data.frame(NULL) 

for(i in 1:nrow(BldActivity)) {
    row <- BldActivity[i,]
    # do stuff with row
    if(row$Type == 'entry') {
        rowNext <- BldActivity[i 1,] 
        if(!is.na(rowNext$Type)) {
            if(rowNext$Type == 'exit' amp;amp; row$UniqueId == rowNext$UniqueId)
            {
                        newRow <- data.frame( Entry_DateOfEvent = row$DateOfEvent,
                                        Exit_DateOfEvent  = rowNext$DateOfEvent,

                                        BuildingID = row$BuildingID,
                                        BuildingName = row$`Building Name`,
                                        UniqueId = row$UniqueId,
                                        DurationOfStay = difftime(rowNext$DateOfEvent, row$DateOfEvent, units="mins")
                                        )

                    DurationOfStay <- rbind(DurationOfStay,newRow)
            }
        }
    }
}
  

Не могли бы вы, пожалуйста, указать мне на возможные улучшения?

Вот пример ввода:

 DateOfEvent Type    UniqueId    BuildingID  Building Name
2019/03/22 09:15:43 entry   04352e5b6051c311048a5803f8716700    1e98f5c0e699    Building 2
2019/03/22 09:51:45 exit    04352e5b6051c311048a5803f8716700    1e98f5c0e699    Building 2
2019/03/22 10:31:28 entry   066b9a3995acd495318ad70e0d876f00    062e933d6b9f    Building 1
2019/03/22 11:15:02 exit    066b9a3995acd495318ad70e0d876f00    062e933d6b9f    Building 1
2019/03/22 11:11:42 entry   0e027aba359aaecbe8fe3eaf5a1bbb00    062e933d6b9f    Building 1
2019/03/22 14:44:27 exit    0e027aba359aaecbe8fe3eaf5a1bbb00    062e933d6b9f    Building 1
2019/03/22 09:55:03 entry   1747dbaef11176b9ab90f2cfbf056210    1e98f5c0e699    Building 2
2019/03/22 18:13:08 exit    1747dbaef11176b9ab90f2cfbf056210    1e98f5c0e699    Building 2
2019/03/21 14:23:53 entry   3e0d2c4b1b159a24f4dc5fa084b59f00    1e98f5c0e699    Building 2
2019/03/21 15:36:31 exit    3e0d2c4b1b159a24f4dc5fa084b59f00    1e98f5c0e699    Building 2
  

Выходные данные — это просто значения столбцов для ВВОДА / вывода и вычисленная продолжительность.

Спасибо

Филипп

Комментарии:

1. Не могли бы вы добавить воспроизводимый пример вместе с ожидаемым результатом на основе этого?

2. Привет, Ронак, я только что добавил пример ввода. (Правда, всего 10 строк). Спасибо

Ответ №1:

 library(data.table)
setDT(BldActivity)
DurationOfStay <- dcast(BldActivity, UniqueId   BuildingID   `Building Name` ~ Type, value.var = "DateOfEvent")
DurationOfStay[, DurationOfStay := difftime(exit, entry, units="mins"), ]
  

Комментарии:

1. Привет, спасибо за это. Это действительно круто, но я столкнулся с другой проблемой (объясняется в следующем ответе).

Ответ №2:

спасибо за ваш код, он выглядит очень многообещающе. Хотя у меня есть 2 проблемы:

Во-первых, возникла проблема с функцией агрегирования, которая выдает ошибку:

Агрегирующие функции должны принимать векторные входные данные и возвращать единственное значение (длина = 1).

Я решил это, добавив функцию агрегирования

 fun.aggregate = function(x) { 
   lubridate::as_datetime(ifelse(Type == 'entry', min(x), max(x)))
}
  

Я также добавил идентификатор для группировки входов / выходов на основе уникального идентификатора, идентификатора здания и типа (Вход / выход)

Вот новый код:

 setDT(BldActivity)
BldActivity[, ID_Stay := seq_len(.N), by=list(UniqueId, BuildingID, Type)]
DwellTime <- dcast(BldActivity, UniqueId   BuildingID   `Building Name` ~ Type, value.var = "DateOfEvent", 
fun.aggregate = function(x) {
    lubridate::as_datetime(ifelse(Type == 'entry', min(x), max(x)))},
  fill = 0)
DurationOfStay[, DurationOfStay := difftime(exit, entry, units="mins"), ]
  

Но у меня очень странные значения… Причина в том, что если у меня есть 2 входа и между ними нет выходов, вся последовательность перепутана.

Вот пример: пример

Спасибо

Филипп