dplyr: добавление новой строки в конце каждой группы, рассчитанной по переменным из предыдущей строки - PullRequest
0 голосов
/ 27 января 2019

Ключевая проблема

Я могу заполнить новую строку значениями предыдущей строки. Я могу назначить константы переменным в новом ряду. Но я не могу рассчитать значения на основе предыдущих строк и назначить их в новой строке.

Фон

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

Уже достигнут

  • Я добавил Error_ID, Error_startTS, Error_EndTS и часть жизненного цикла , как было задокументировано в другом SO вопросе
  • Ошибка определяется как любая серия событий, которая начинается с state_type == "error", пока не встретится событие, которое это не что иное, как «Ошибка», «Comlink Down», «Не активен».
  • и номер ошибки был назначен для всех строк одной и той же «трассировки ошибок» («Error_ID»)
  • назначено время начала ошибки (отметка времени первой строки ошибки) («Error_startTS»)
  • время окончания ошибки, отметка времени 1-й строки после ошибки , другими словами временная метка события, завершающего ошибку, была назначена («Error_endTS»)
  • a «Life_cycle_ID» был присвоен строкам ошибки: «Пуск» или «Текущий».

Цель:

Теперь я хочу вставить новую строку

  • с Life_cycle_id == "Завершено"
  • после последней строки «продолжается» каждой «трассировки ошибок»

Детали

  • Решаемо с fill(): копия из последней строки
    • "Ресурс"
    • "Error_ID",
    • «Error_startTS»,
    • "Error_endTS"
  • Решаемо с add.row(): назначить константу
    • «Lifecycle_ID» должен быть «завершен»
    • «State_type» должно быть «Error»
  • Проблематично для меня: присваивать значения на основе значений предыдущих строк
    • Отметка времени «Datetime_local» должна получить значение «Error_endTS» в группе
    • "event_ID" должен быть увеличен на 1

Данные

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"), 
       Error_ID = c(0, 1, 1, 1, 1, 1, 0, 2, 2, 2, 0, 3, 0), 
       Error_startTS = structure(c(NA, 1535952618, 1535952618, 1535952618, 1535952618, 
                                   1535952618, NA, 1535952846, 1535952846, 1535952846, 
                                   NA, 1535952958, NA), 
                                 class = c("POSIXct", "POSIXt"), tzone = ""), 
       Error_endTS = structure(c(NA, 1535952840, 1535952840, 1535952840, 1535952840, 
                                 1535952840, NA, 1535952952, 1535952952, 1535952952, 
                                 NA, 1535953066, NA), 
                               class = c("POSIXct", "POSIXt"), tzone = ""), 
       Lifecycle_ID = c(NA, "Start", "Ongoing", "Ongoing", "Ongoing", "Ongoing", NA, 
                        "Start", "Ongoing", "Ongoing", NA, "Start", NA)), 
  .Names = c("Resource", "Datetime_local", "State_type", "event_ID", "Error_ID", 
            "Error_startTS", "Error_endTS", "Lifecycle_ID"), 
  row.names = 160:172, class = "data.frame")

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

# 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>

UDF

ErrorNumberAddLastRow <- function(df){
  df %>%
    mutate_if(is.factor, as.character) %>%
    group_by(Error_ID) %>%
    do(add_row(.,
               Lifecycle_ID = "Complete", State_type = "Error")) %>%
    ungroup() %>%
    fill("Resource", "event_ID","Error_ID", "Error_startTS", "Error_endTS") %>%
    # mutate(event_ID = event_ID+1) %>%          # error: non-numeric argument to binary operator.
    # mutate(Datetime_local = Error_endTS) %>%   # assigns the same TS to the whole group
    arrange(event_ID) %>% 
    filter( !(Error_ID==0 & Lifecycle_ID=="Complete") | is.na(Lifecycle_ID))
}

Позвоните на udf

ErrorNumberAddLastRow(my_df)

Дает этот результат

# A tibble: 16 x 8
   Resource Datetime_local      State_type event_ID           Error_ID Error_startTS       Error_endTS         Lifecycle_ID
   <chr>    <dttm>              <chr>      <chr>                 <dbl> <dttm>              <dttm>              <chr>       
 1 L60      2018-09-03 07:29:54 No part in e00000000000072160        0 NA                  NA                  NA          
 2 L60      2018-09-03 07:30:18 Error      e00000000000072270        1 2018-09-03 07:30:18 2018-09-03 07:34:00 Start       
 3 L60      2018-09-03 07:30:43 Not active e00000000000072400        1 2018-09-03 07:30:18 2018-09-03 07:34:00 Ongoing     
 4 L60      2018-09-03 07:30:51 Error      e00000000000072430        1 2018-09-03 07:30:18 2018-09-03 07:34:00 Ongoing     
 5 L60      2018-09-03 07:33:07 Not active e00000000000072810        1 2018-09-03 07:30:18 2018-09-03 07:34:00 Ongoing     
 6 L60      2018-09-03 07:33:55 Error      e00000000000073110        1 2018-09-03 07:30:18 2018-09-03 07:34:00 Ongoing     
 7 L60      NA                  Error      e00000000000073110        1 2018-09-03 07:30:18 2018-09-03 07:34:00 Complete    
 8 L60      2018-09-03 07:34:00 Producing  e00000000000073150        0 NA                  NA                  NA          
 9 L60      2018-09-03 07:34:06 Error      e00000000000073170        2 2018-09-03 07:34:06 2018-09-03 07:35:52 Start       
10 L60      2018-09-03 07:34:50 Not active e00000000000073300        2 2018-09-03 07:34:06 2018-09-03 07:35:52 Ongoing     
11 L60      2018-09-03 07:35:49 Error      e00000000000073520        2 2018-09-03 07:34:06 2018-09-03 07:35:52 Ongoing     
12 L60      NA                  Error      e00000000000073520        2 2018-09-03 07:34:06 2018-09-03 07:35:52 Complete    
13 L60      2018-09-03 07:35:52 Producing  e00000000000073540        0 NA                  NA                  NA          
14 L60      2018-09-03 07:35:58 Error      e00000000000073570        3 2018-09-03 07:35:58 2018-09-03 07:37:46 Start       
15 L60      NA                  Error      e00000000000073570        3 2018-09-03 07:35:58 2018-09-03 07:37:46 Complete    
16 L60      2018-09-03 07:37:46 Producing  e00000000000074040        0 NA                  NA                  NA      

Желаемый результат

# # A tibble: 16 x 8
# Resource Datetime_local      State_type event_ID           Error_ID Error_startTS       Error_endTS         Lifecycle_ID
# <chr>    <dttm>              <chr>      <chr>                 <dbl> <dttm>              <dttm>              <chr>       
#  1 L60      2018-09-03 07:29:54 No part in e00000000000072160        0 NA                  NA                  NA          
#  2 L60      2018-09-03 07:30:18 Error      e00000000000072270        1 2018-09-03 07:30:18 2018-09-03 07:34:00 Start       
#  3 L60      2018-09-03 07:30:43 Not active e00000000000072400        1 2018-09-03 07:30:18 2018-09-03 07:34:00 Ongoing     
#  4 L60      2018-09-03 07:30:51 Error      e00000000000072430        1 2018-09-03 07:30:18 2018-09-03 07:34:00 Ongoing     
#  5 L60      2018-09-03 07:33:07 Not active e00000000000072810        1 2018-09-03 07:30:18 2018-09-03 07:34:00 Ongoing     
#  6 L60      2018-09-03 07:33:55 Error      e00000000000073110        1 2018-09-03 07:30:18 2018-09-03 07:34:00 Ongoing     
#  7 L60      2018-09-03 07:34:00 Error      e00000000000073111        1 2018-09-03 07:30:18 2018-09-03 07:34:00 Complete    
#  8 L60      2018-09-03 07:34:00 Producing  e00000000000073150        0 NA                  NA                  NA          
#  9 L60      2018-09-03 07:34:06 Error      e00000000000073170        2 2018-09-03 07:34:06 2018-09-03 07:35:52 Start       
# 10 L60      2018-09-03 07:34:50 Not active e00000000000073300        2 2018-09-03 07:34:06 2018-09-03 07:35:52 Ongoing     
# 11 L60      2018-09-03 07:35:49 Error      e00000000000073520        2 2018-09-03 07:34:06 2018-09-03 07:35:52 Ongoing     
# 12 L60      2018-09-03 07:35:52 Error      e00000000000073521        2 2018-09-03 07:34:06 2018-09-03 07:35:52 Complete    
# 13 L60      2018-09-03 07:35:52 Producing  e00000000000073540        0 NA                  NA                  NA          
# 14 L60      2018-09-03 07:35:58 Error      e00000000000073570        3 2018-09-03 07:35:58 2018-09-03 07:37:46 Start       
# 15 L60      2018-09-03 07:37:46 Error      e00000000000073571        3 2018-09-03 07:35:58 2018-09-03 07:37:46 Complete    
# 16 L60      2018-09-03 07:37:46 Producing  e00000000000074040        0 NA                  NA                  NA   

Подробно

В строке 7, 12 и 15

  • увеличить event_ID с 1
  • добавить «Error_endTS» группы к метке времени Datetime_local

Когда вы раскомментируете операторы mutate в функции

  1. mutate(event_ID = event_ID+1) %>%

... возникает ошибка

Ошибка в mutate_impl (.data, точки): Ошибка оценки: не числовой аргумент бинарного оператора.

  1. mutate(Datetime_local = Error_endTS) %>%

... это назначает один и тот же TS всей группе

Спасибо за любую помощь, которую вы можете оказать мне.

1 Ответ

0 голосов
/ 27 января 2019

Вот идея

library(tidyverse)
library(gsubfn)

my_df %>%
  split(.$Error_ID) %>%
  map_dfr(~ add_row(.x, 
                    Lifecycle_ID = "Complete", 
                    State_type = "Error", 
                    # Take the last event_ID in each group, find the last digit 
                    # in the string, convert it to numeric and add +1
                    event_ID = gsubfn("\\d{1}$", ~ as.numeric(x) + 1, last(.$event_ID)),
                    # Assign Datetime_local to the last Error_endTS in each group
                    Datetime_local = last(.$Error_endTS))) %>%
  fill("Resource", "Error_ID", "Error_startTS", "Error_endTS")
...