이번 포스팅에서는 장비별로 On, Off 상태 변화 간의 가동 시간(run time)을 구하고, 이렇게 구한 장비별 가동 시간의 평균을 집계해보겠습니다.
먼저, 장비(device), 날짜/시간(time), status('ON', 'OFF') 의 3개 변수로 구성된 간단한 예제 DataFrame을 만들어보겠습니다.
> #=========================== > # time difference by device > #=========================== > > device <- c('A', 'A', 'A', 'A', 'B', 'B', 'B', 'C', 'C', 'C', 'C', 'C') > time <- c('2018-07-01 10:20:23', '2018-07-01 10:30:55', '2018-07-01 11:11:01', + '2018-07-01 11:51:41', '2018-07-02 07:11:02', '2018-07-02 09:00:33', + '2018-07-02 09:20:24', '2018-07-02 12:12:21', '2018-07-02 14:01:09', + '2018-07-02 18:11:41', '2018-07-02 19:21:51', '2018-07-02 20:30:00') > status <- c('ON', 'ON', 'ON', 'OFF', 'ON', 'ON', 'OFF', 'ON', 'OFF', 'ON', 'ON', 'OFF') > > df <- data.frame(device, time, status) > df device time status 1 A 2018-07-01 10:20:23 ON <-- start 2 A 2018-07-01 10:30:55 ON 3 A 2018-07-01 11:11:01 ON 4 A 2018-07-01 11:51:41 OFF <-- end 5 B 2018-07-02 07:11:02 ON <-- start 6 B 2018-07-02 09:00:33 ON 7 B 2018-07-02 09:20:24 OFF <-- end 8 C 2018-07-02 12:12:21 ON <-- start 9 C 2018-07-02 14:01:09 OFF <-- end 10 C 2018-07-02 18:11:41 ON <-- start 11 C 2018-07-02 19:21:51 ON 12 C 2018-07-02 20:30:00 OFF <-- end > |
다음으로 장비(device)와 날짜/시간(time)을 기준으로 정렬(sort)을 하겠습니다.
> # sort df by device and time in ascending order > df <- df[order(device, time),] > df device time status 1 A 2018-07-01 10:20:23 ON 2 A 2018-07-01 10:30:55 ON 3 A 2018-07-01 11:11:01 ON 4 A 2018-07-01 11:51:41 OFF 5 B 2018-07-02 07:11:02 ON 6 B 2018-07-02 09:00:33 ON 7 B 2018-07-02 09:20:24 OFF 8 C 2018-07-02 12:12:21 ON 9 C 2018-07-02 14:01:09 OFF 10 C 2018-07-02 18:11:41 ON 11 C 2018-07-02 19:21:51 ON 12 C 2018-07-02 20:30:00 OFF > |
각 장비(device) 별로 'ON' 이후에 다음 'OFF' 까지의 사이 중간에 끼어있는 'ON'은 필요가 없으므로 삭제를 해서 새로운 'df_2' 이름의 DataFrame을 만들어보겠습니다.
[ 전처리 후의 Output Image ]
device time status 1 A 2018-07-01 10:20:23 ON <-- start
4 A 2018-07-01 11:51:41 OFF <-- end 5 B 2018-07-02 07:11:02 ON <-- start
7 B 2018-07-02 09:20:24 OFF <-- end 8 C 2018-07-02 12:12:21 ON <-- start 9 C 2018-07-02 14:01:09 OFF <-- end 10 C 2018-07-02 18:11:41 ON <-- start
12 C 2018-07-02 20:30:00 OFF <-- end
|
> # set of device > device_set <- as.character(unique(df$device)) > > # blank DataFrame to store the preprocessed dataset > df_2 <- data.frame() > > for (i in 1:length(device_set)){ + # split dataframe by device + device_i <- device_set[i] + df_i <- df[df$device == device_i, ] + + # add the first time of df_i to df2 + df_2 <- rbind(df_2, df_i[1,]) + + # add the time if the device is turned off or turned on again + for (j in 1:(nrow(df_i)-1)){ + if((df_i$status[j] == 'ON' & df_i$status[j+1] == 'OFF') | + (df_i$status[j] == 'OFF' & df_i$status[j+1] == 'ON')){ + df_2 <- rbind(df_2, df_i[j+1,]) + } + } + } > > df_2 device time status 1 A 2018-07-01 10:20:23 ON 4 A 2018-07-01 11:51:41 OFF 5 B 2018-07-02 07:11:02 ON 7 B 2018-07-02 09:20:24 OFF 8 C 2018-07-02 12:12:21 ON 9 C 2018-07-02 14:01:09 OFF 10 C 2018-07-02 18:11:41 ON 12 C 2018-07-02 20:30:00 OFF > |
lag() window function을 사용해서 장비, 날짜/시간, 상태를 한칸씩 밑으로 내리고(Lag), 장비 이름과 상태를 기준으로 필요한 행만 남기고 나머지는 삭제하겠습니다.
> # lag window function > library(dplyr) > df_2_lag <- mutate(df_2, + device_lag = lag(device, 1), + time_lag = lag(time, 1), + status_lag = lag(status, 1)) > > > # filtering > df_2_lag_filtered <- df_2_lag %>% + filter(device == device_lag & status == 'OFF') > > df_2_lag_filtered device time status device_lag time_lag status_lag 1 A 2018-07-01 11:51:41 OFF A 2018-07-01 10:20:23 ON 2 B 2018-07-02 09:20:24 OFF B 2018-07-02 07:11:02 ON 3 C 2018-07-02 14:01:09 OFF C 2018-07-02 12:12:21 ON 4 C 2018-07-02 20:30:00 OFF C 2018-07-02 18:11:41 ON > |
이제 장비(device)별로 'ON' 이후 다음번 'OFF' 까지의 가동 시간(run_time)을 difftime() 함수를 사용해서 구해보겠습니다. 이때 strptime() 함수를 사용해서 문자열 값을 '년/월/일/시간/분/초("%Y-%m-%d %H:%M:%S")' 형태로 만들어준 후에 difftime() 함수를 사용할 수 있습니다. 이렇 구한 가동시간은 '시간(hour)' 단위 값입니다. (분으로 환산하려면 곱하기 60, 초로 환산하려면 곱하기 60*60 을 해주면 됩니다)
> # calculate the run_time > df_2_lag_filtered$run_time <- as.numeric(difftime(strptime(df_2_lag_filtered$time, "%Y-%m-%d %H:%M:%S"), + strptime(df_2_lag_filtered$time_lag, "%Y-%m-%d %H:%M:%S"))) > > df_2_lag_filtered device time status device_lag time_lag status_lag run_time 1 A 2018-07-01 11:51:41 OFF A 2018-07-01 10:20:23 ON 1.521667 2 B 2018-07-02 09:20:24 OFF B 2018-07-02 07:11:02 ON 2.156111 3 C 2018-07-02 14:01:09 OFF C 2018-07-02 12:12:21 ON 1.813333 4 C 2018-07-02 20:30:00 OFF C 2018-07-02 18:11:41 ON 2.305278 > |
마지막으로, 각 장비(device)별 가동시간(run_time)의 평균을 구해보겠습니다.
> # average of run_time by device > run_time_by_device <- df_2_lag_filtered %>% + group_by(device) %>% + summarise(run_time_avg = mean(run_time)) > > run_time_by_device # A tibble: 3 x 2 device run_time_avg <fct> <dbl> 1 A 1.52 2 B 2.16 3 C 2.06 > |
많은 도움이 되었기를 바랍니다.
이번 포스팅이 도움이 되었다면 아래의 '공감~'를 꾹 눌러주세요.