Циклический подход к подготовке журнала событий для `bupaR`: это можно векторизовать? - PullRequest
0 голосов
/ 25 января 2019

Фон

У меня есть реальные данные из ПЛК, которые я готовлю к преобразованию в журнал событий для использования с пакетом bupaR. Приведенные ниже данные ограничены и упрощены, но содержат информацию о ресурсе, отметке времени, типе состояния и идентификаторе события.

Я добился желаемого преобразования, задокументированного ниже с помощью циклов. У меня вопрос, можно ли это сделать без петель, "векторизованным" способом?

Цель:

С этого я хочу

  • определяет, когда возникает ошибка , и я хочу отследить ее до конца. Он заканчивается, когда `State_type`` - это не что иное, как" Error "," Comlink Down "," Not Active ".
  • назначить номер ошибки всем строкам одной и той же "трассировки ошибок" (назначить "Error_ID")
  • имеют время начала ошибки (отметка времени первой строки ошибки) (присваивается «Error_startTS»)
  • имеют время окончания ошибки (отметка времени 1-й строки после ошибки , другими словами временная метка события, которое завершает ошибку) ((назначить «Error_endTS»))
  • присвойте Life_cycle_ID строкам ошибки: «Пуск» или «Текущий». (На более позднем этапе «Complete» Life_cycle_id будет вставлен после последней строки «running» каждого «error-trace»; одна проблема в то время; -)

Мои данные

my_df <- 
  structure(list(Resource = structure(c(2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L), 
                                      .Label = c("L54", "L60", "L66", "L68", "L70", "L76", 
                                                 "L78", "L95", "L96", "L97", "L98", "L99"), 
                                      class = "factor"), 
                 Datetime_local = structure(c(1535952594, 1535952618, 1535952643, 1535952651, 
                                              1535952787, 1535952835, 1535952840, 1535952846, 
                                              1535952890, 1535952949, 1535952952, 1535952958, 
                                              1535953066), 
                                            class = c("POSIXct", "POSIXt"), tzone = ""), 
                 State_type = structure(c(6L, 4L, 8L, 4L, 8L, 4L, 12L, 4L, 8L, 4L, 12L, 4L, 12L), 
                                        .Label = c("Comlink Down", "Comlink Up", "Counter", 
                                                   "Error", "Message", "No part in", "No part out", 
                                                   "Not active", "Part changing", "Part in", "Part out", 
                                                   "Producing", "Waiting"), 
                                        class = "factor"), 
                 event_ID = c("e00000000000072160", "e00000000000072270", "e00000000000072400", 
                              "e00000000000072430", "e00000000000072810", "e00000000000073110", 
                              "e00000000000073150", "e00000000000073170", "e00000000000073300", 
                              "e00000000000073520", "e00000000000073540", "e00000000000073570", 
                              "e00000000000074040")), 
            .Names = c("Resource", "Datetime_local", "State_type", "event_ID"), 
            row.names = 160:172, class = "data.frame")

... выглядит так

    Resource      Datetime_local State_type           event_ID
160      L60 2018-09-03 07:29:54 No part in e00000000000072160
161      L60 2018-09-03 07:30:18      Error e00000000000072270
162      L60 2018-09-03 07:30:43 Not active e00000000000072400
163      L60 2018-09-03 07:30:51      Error e00000000000072430
164      L60 2018-09-03 07:33:07 Not active e00000000000072810
165      L60 2018-09-03 07:33:55      Error e00000000000073110
166      L60 2018-09-03 07:34:00  Producing e00000000000073150
167      L60 2018-09-03 07:34:06      Error e00000000000073170
168      L60 2018-09-03 07:34:50 Not active e00000000000073300
169      L60 2018-09-03 07:35:49      Error e00000000000073520
170      L60 2018-09-03 07:35:52  Producing e00000000000073540
171      L60 2018-09-03 07:35:58      Error e00000000000073570
172      L60 2018-09-03 07:37:46  Producing e00000000000074040

Мой UDF:

AssignErrorNumber <- function(df) {

  # set start values
  require(dplyr)
  errorNumber <- 0
  i <- 1
  j <- 0
  df$Error_ID <- 0
  df$Error_startTS <- NA
  df$Error_endTS <- NA
  df$Lifecycle_ID <- NA

  # loop through all rows
  while (i <= nrow(df)) {

    ## find the first row with an error raised
    if ( df$State_type[i] == "Error") {

      # for the first row for this error, 
      #   increase error counter and get startTS
      #   save them for this row
      errorNumber <- errorNumber + 1
      startTS <- df$Datetime_local[i] 
      df$Error_ID[i] <- errorNumber
      df$Error_startTS[i] <- startTS
      df$Lifecycle_ID[i] <- "Start"

      # do the following for each following row 
      #   until state_type goes to non-error state
      #   save error_number and startTS for this row
      i <- i+1
      j <- 1 # counter for the loop
      while (df$State_type[i] %in% c("Error", "Comlink Down", "Not active")) {
        df$Error_ID[i] <- errorNumber
        df$Error_startTS[i] <- startTS
        df$Lifecycle_ID[i] <- "Ongoing"
        i <- i+1 
        j <- j+1
      }
      # we saw the last row for this error, mark as "ongoing" AND add a row later on with "complete"
      # alternatively we could mark this as "completed", but this
      # mixes things up: the time when an error is finished is not this Datetime_local!
      if (j!=1){ # if not first line, this should remain "start"
        df$Lifecycle_ID[i-1] <- "Ongoing"
      }

    }
    # before going to the next row, 
    #   get TS from the row following the last error-row (if not end of file)
    #   go back and set endTS for this error_number
    if (i <= nrow(df)) {
      endTS <- df$Datetime_local[i]
    }
    else {
      endTS <- df$Datetime_local[i-1] # last row: endTS = startTS of last row of error
    }

    while (j >= 1) {
      df$Error_endTS[i-j] <- endTS
      j <- j-1
    }

    # to go to next row
    i <- i+1
  }
  # transform TS's to Date and time POSIXct
  df$Error_startTS <- as.POSIXct(df$Error_startTS, origin = "1970-01-01")
  df$Error_endTS <- as.POSIXct(df$Error_endTS, origin = "1970-01-01")
  return(df)
}

Позвоните в UDF

AssignErrorNumber(my_df)

Требуемый вывод // вывод функции зацикливания

Resource      Datetime_local State_type           event_ID Error_ID       Error_startTS         Error_endTS Lifecycle_ID
160      L60 2018-09-03 07:29:54 No part in e00000000000072160        0                <NA>                <NA>         <NA>
161      L60 2018-09-03 07:30:18      Error e00000000000072270        1 2018-09-03 07:30:18 2018-09-03 07:34:00        Start
162      L60 2018-09-03 07:30:43 Not active e00000000000072400        1 2018-09-03 07:30:18 2018-09-03 07:34:00      Ongoing
163      L60 2018-09-03 07:30:51      Error e00000000000072430        1 2018-09-03 07:30:18 2018-09-03 07:34:00      Ongoing
164      L60 2018-09-03 07:33:07 Not active e00000000000072810        1 2018-09-03 07:30:18 2018-09-03 07:34:00      Ongoing
165      L60 2018-09-03 07:33:55      Error e00000000000073110        1 2018-09-03 07:30:18 2018-09-03 07:34:00      Ongoing
166      L60 2018-09-03 07:34:00  Producing e00000000000073150        0                <NA>                <NA>         <NA>
167      L60 2018-09-03 07:34:06      Error e00000000000073170        2 2018-09-03 07:34:06 2018-09-03 07:35:52        Start
168      L60 2018-09-03 07:34:50 Not active e00000000000073300        2 2018-09-03 07:34:06 2018-09-03 07:35:52      Ongoing
169      L60 2018-09-03 07:35:49      Error e00000000000073520        2 2018-09-03 07:34:06 2018-09-03 07:35:52      Ongoing
170      L60 2018-09-03 07:35:52  Producing e00000000000073540        0                <NA>                <NA>         <NA>
171      L60 2018-09-03 07:35:58      Error e00000000000073570        3 2018-09-03 07:35:58 2018-09-03 07:37:46        Start
172      L60 2018-09-03 07:37:46  Producing e00000000000074040        0                <NA>                <NA>         <NA>

Моя искренняя благодарность всем, кто прочитал этот длинный вопрос. И я повторяю свой вопрос: « Можно ли векторизовать этот набор проблем? »

...