2019 Big Contest

big_contest_final

Yang_Kwon_Cho_Lim

2019-09-09


라이브러리 설치

library(tidyverse)

## ── Attaching packages ───────────────────

## ✔ ggplot2 3.1.0       ✔ purrr   0.3.1  
## ✔ tibble  2.0.1       ✔ dplyr   0.8.0.1
## ✔ tidyr   0.8.3       ✔ stringr 1.4.0  
## ✔ readr   1.3.1       ✔ forcats 0.4.0

## ── Conflicts ─── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag()    masks stats::lag()
library(randomForest)

## randomForest 4.6-14

## Type rfNews() to see new features/changes/bug fixes.

## 
## Attaching package: 'randomForest'

## The following object is masked from 'package:dplyr':
## 
##     combine

## The following object is masked from 'package:ggplot2':
## 
##     margin
library(MLmetrics)

## 
## Attaching package: 'MLmetrics'

## The following object is masked from 'package:base':
## 
##     Recall
library(caret)

## Loading required package: lattice

## 
## Attaching package: 'caret'

## The following objects are masked from 'package:MLmetrics':
## 
##     MAE, RMSE

## The following object is masked from 'package:purrr':
## 
##     lift
library(dplyr)
library(ROCR)

## Loading required package: gplots

## 
## Attaching package: 'gplots'

## The following object is masked from 'package:stats':
## 
##     lowess
library(pROC)

## Type 'citation("pROC")' for a citation.

## 
## Attaching package: 'pROC'

## The following objects are masked from 'package:stats':
## 
##     cov, smooth, var
library(plyr)

## -------------------------------------------------------------------------

## You have loaded plyr after dplyr - this is likely to cause problems.
## If you need functions from both plyr and dplyr, please load plyr first, then dplyr:
## library(plyr); library(dplyr)

## -------------------------------------------------------------------------

## 
## Attaching package: 'plyr'

## The following objects are masked from 'package:dplyr':
## 
##     arrange, count, desc, failwith, id, mutate, rename, summarise,
##     summarize

## The following object is masked from 'package:purrr':
## 
##     compact


데이터 불러오기(afsnt, afsnt_dly)

afsnt <- read.csv("AFSNT.csv", header = TRUE, fileEncoding = 'euc-kr')
afsnt_dly <- read.csv("AFSNT_DLY.csv", header = TRUE, fileEncoding = 'euc-kr')
afsnt_dly[3, 5] <- 'ARP1'
head(afsnt)

##   SDT_YY SDT_MM SDT_DD SDT_DY  ARP  ODP FLO   FLT      REG AOD IRR  STT
## 1   2017      1      1     일 ARP1 ARP3   A A1901 SEw3Nzc2   D   N 6:10
## 2   2017      1      1     일 ARP1 ARP3   A A1905 SEw4MjM2   D   N 6:15
## 3   2017      1      1     일 ARP1 ARP3   L L1751 SEw4MjM3   D   N 6:20
## 4   2017      1      1     일 ARP1 ARP3   F F1201 SEw4MjA3   D   N 6:25
## 5   2017      1      1     일 ARP3 ARP1   A A1900 SEw3NzAz   D   N 6:30
## 6   2017      1      1     일 ARP1 ARP3   H H1101 SEw4MDMx   D   N 6:30
##    ATT DLY DRR CNL CNR
## 1 6:18   N       N    
## 2 6:25   N       N    
## 3 6:30   N       N    
## 4 6:34   N       N    
## 5 6:37   N       N    
## 6 6:38   N       N
head(afsnt_dly)

##   SDT_YY SDT_MM SDT_DD SDT_DY  ARP  ODP FLO   FLT AOD   STT DLY DLY_RATE
## 1   2019      9     16     월 ARP1 ARP3   L L1702   A  9:05  NA       NA
## 2   2019      9     16     월 ARP3 ARP1   L L1702   D  7:55  NA       NA
## 3   2019      9     16     월 ARP1 ARP3   L L1720   A 14:40  NA       NA
## 4   2019      9     16     월 ARP3 ARP1   L L1720   D 13:30  NA       NA
## 5   2019      9     16     월 ARP4 ARP3   L L1808   A 20:10  NA       NA
## 6   2019      9     16     월 ARP3 ARP4   L L1808   D 19:10  NA       NA


결항편 삭제하기

afsnt <- afsnt %>% dplyr::filter(CNL == "N")
head(afsnt)

##   SDT_YY SDT_MM SDT_DD SDT_DY  ARP  ODP FLO   FLT      REG AOD IRR  STT
## 1   2017      1      1     일 ARP1 ARP3   A A1901 SEw3Nzc2   D   N 6:10
## 2   2017      1      1     일 ARP1 ARP3   A A1905 SEw4MjM2   D   N 6:15
## 3   2017      1      1     일 ARP1 ARP3   L L1751 SEw4MjM3   D   N 6:20
## 4   2017      1      1     일 ARP1 ARP3   F F1201 SEw4MjA3   D   N 6:25
## 5   2017      1      1     일 ARP3 ARP1   A A1900 SEw3NzAz   D   N 6:30
## 6   2017      1      1     일 ARP1 ARP3   H H1101 SEw4MDMx   D   N 6:30
##    ATT DLY DRR CNL CNR
## 1 6:18   N       N    
## 2 6:25   N       N    
## 3 6:30   N       N    
## 4 6:34   N       N    
## 5 6:37   N       N    
## 6 6:38   N       N


연, 월, 일 데이터 범주형으로 바꾸기

afsnt$SDT_YY <- as.factor(afsnt$SDT_YY)
afsnt$SDT_MM <- as.factor(afsnt$SDT_MM)
afsnt$SDT_DD <- as.factor(afsnt$SDT_DD)

head(afsnt)

##   SDT_YY SDT_MM SDT_DD SDT_DY  ARP  ODP FLO   FLT      REG AOD IRR  STT
## 1   2017      1      1     일 ARP1 ARP3   A A1901 SEw3Nzc2   D   N 6:10
## 2   2017      1      1     일 ARP1 ARP3   A A1905 SEw4MjM2   D   N 6:15
## 3   2017      1      1     일 ARP1 ARP3   L L1751 SEw4MjM3   D   N 6:20
## 4   2017      1      1     일 ARP1 ARP3   F F1201 SEw4MjA3   D   N 6:25
## 5   2017      1      1     일 ARP3 ARP1   A A1900 SEw3NzAz   D   N 6:30
## 6   2017      1      1     일 ARP1 ARP3   H H1101 SEw4MDMx   D   N 6:30
##    ATT DLY DRR CNL CNR
## 1 6:18   N       N    
## 2 6:25   N       N    
## 3 6:30   N       N    
## 4 6:34   N       N    
## 5 6:37   N       N    
## 6 6:38   N       N


시간대별 편 수 계산

afsnt$STT <- as.character(afsnt$STT)
b <- sapply(afsnt[, "STT"],  function(x) {x %>% str_split(pattern = ':')  %>% `[[`(1) })
HOUR <- b[1, ] %>% as.numeric()

afsnt$HOUR <- HOUR
afsnt$HOUR <- as.factor(afsnt$HOUR)

afsnt_count <- afsnt %>%
 dplyr::group_by(SDT_YY, SDT_MM, SDT_DD, ARP, HOUR) %>%
 dplyr::summarise('count' = n())

afsnt <- left_join(afsnt, afsnt_count, by = c("SDT_YY", "SDT_MM", "SDT_DD", "ARP", "HOUR"))

head(afsnt)

##   SDT_YY SDT_MM SDT_DD SDT_DY  ARP  ODP FLO   FLT      REG AOD IRR  STT
## 1   2017      1      1     일 ARP1 ARP3   A A1901 SEw3Nzc2   D   N 6:10
## 2   2017      1      1     일 ARP1 ARP3   A A1905 SEw4MjM2   D   N 6:15
## 3   2017      1      1     일 ARP1 ARP3   L L1751 SEw4MjM3   D   N 6:20
## 4   2017      1      1     일 ARP1 ARP3   F F1201 SEw4MjA3   D   N 6:25
## 5   2017      1      1     일 ARP3 ARP1   A A1900 SEw3NzAz   D   N 6:30
## 6   2017      1      1     일 ARP1 ARP3   H H1101 SEw4MDMx   D   N 6:30
##    ATT DLY DRR CNL CNR HOUR count
## 1 6:18   N       N        6    10
## 2 6:25   N       N        6    10
## 3 6:30   N       N        6    10
## 4 6:34   N       N        6    10
## 5 6:37   N       N        6     2
## 6 6:38   N       N        6    10


시간 변수로 바꾸기

afsnt$STT <- strptime(as.character(afsnt$STT), format = "%H:%M")
afsnt$ATT <- strptime(as.character(afsnt$ATT), format = "%H:%M")
head(afsnt)

##   SDT_YY SDT_MM SDT_DD SDT_DY  ARP  ODP FLO   FLT      REG AOD IRR
## 1   2017      1      1     일 ARP1 ARP3   A A1901 SEw3Nzc2   D   N
## 2   2017      1      1     일 ARP1 ARP3   A A1905 SEw4MjM2   D   N
## 3   2017      1      1     일 ARP1 ARP3   L L1751 SEw4MjM3   D   N
## 4   2017      1      1     일 ARP1 ARP3   F F1201 SEw4MjA3   D   N
## 5   2017      1      1     일 ARP3 ARP1   A A1900 SEw3NzAz   D   N
## 6   2017      1      1     일 ARP1 ARP3   H H1101 SEw4MDMx   D   N
##                   STT                 ATT DLY DRR CNL CNR HOUR count
## 1 2019-09-10 06:10:00 2019-09-10 06:18:00   N       N        6    10
## 2 2019-09-10 06:15:00 2019-09-10 06:25:00   N       N        6    10
## 3 2019-09-10 06:20:00 2019-09-10 06:30:00   N       N        6    10
## 4 2019-09-10 06:25:00 2019-09-10 06:34:00   N       N        6    10
## 5 2019-09-10 06:30:00 2019-09-10 06:37:00   N       N        6     2
## 6 2019-09-10 06:30:00 2019-09-10 06:38:00   N       N        6    10


시간 차 변수 생성하기

afsnt$timediff <- difftime(afsnt$ATT, afsnt$STT, units = "mins")
head(afsnt)

##   SDT_YY SDT_MM SDT_DD SDT_DY  ARP  ODP FLO   FLT      REG AOD IRR
## 1   2017      1      1     일 ARP1 ARP3   A A1901 SEw3Nzc2   D   N
## 2   2017      1      1     일 ARP1 ARP3   A A1905 SEw4MjM2   D   N
## 3   2017      1      1     일 ARP1 ARP3   L L1751 SEw4MjM3   D   N
## 4   2017      1      1     일 ARP1 ARP3   F F1201 SEw4MjA3   D   N
## 5   2017      1      1     일 ARP3 ARP1   A A1900 SEw3NzAz   D   N
## 6   2017      1      1     일 ARP1 ARP3   H H1101 SEw4MDMx   D   N
##                   STT                 ATT DLY DRR CNL CNR HOUR count
## 1 2019-09-10 06:10:00 2019-09-10 06:18:00   N       N        6    10
## 2 2019-09-10 06:15:00 2019-09-10 06:25:00   N       N        6    10
## 3 2019-09-10 06:20:00 2019-09-10 06:30:00   N       N        6    10
## 4 2019-09-10 06:25:00 2019-09-10 06:34:00   N       N        6    10
## 5 2019-09-10 06:30:00 2019-09-10 06:37:00   N       N        6     2
## 6 2019-09-10 06:30:00 2019-09-10 06:38:00   N       N        6    10
##   timediff
## 1   8 mins
## 2  10 mins
## 3  10 mins
## 4   9 mins
## 5   7 mins
## 6   8 mins


시간차 변수가 0보다 작은 것은 0으로 변환하기

afsnt <- afsnt[!is.na(afsnt$ATT), ]
afsnt[(afsnt$timediff) < 0, "timediff"] <- 0
afsnt$timediff <- as.numeric(afsnt$timediff)
head(afsnt)

##   SDT_YY SDT_MM SDT_DD SDT_DY  ARP  ODP FLO   FLT      REG AOD IRR
## 1   2017      1      1     일 ARP1 ARP3   A A1901 SEw3Nzc2   D   N
## 2   2017      1      1     일 ARP1 ARP3   A A1905 SEw4MjM2   D   N
## 3   2017      1      1     일 ARP1 ARP3   L L1751 SEw4MjM3   D   N
## 4   2017      1      1     일 ARP1 ARP3   F F1201 SEw4MjA3   D   N
## 5   2017      1      1     일 ARP3 ARP1   A A1900 SEw3NzAz   D   N
## 6   2017      1      1     일 ARP1 ARP3   H H1101 SEw4MDMx   D   N
##                   STT                 ATT DLY DRR CNL CNR HOUR count
## 1 2019-09-10 06:10:00 2019-09-10 06:18:00   N       N        6    10
## 2 2019-09-10 06:15:00 2019-09-10 06:25:00   N       N        6    10
## 3 2019-09-10 06:20:00 2019-09-10 06:30:00   N       N        6    10
## 4 2019-09-10 06:25:00 2019-09-10 06:34:00   N       N        6    10
## 5 2019-09-10 06:30:00 2019-09-10 06:37:00   N       N        6     2
## 6 2019-09-10 06:30:00 2019-09-10 06:38:00   N       N        6    10
##   timediff
## 1        8
## 2       10
## 3       10
## 4        9
## 5        7
## 6        8


시간변수 삭제

afsnt <- afsnt[, -c(12:13)]

head(afsnt)

##   SDT_YY SDT_MM SDT_DD SDT_DY  ARP  ODP FLO   FLT      REG AOD IRR DLY DRR
## 1   2017      1      1     일 ARP1 ARP3   A A1901 SEw3Nzc2   D   N   N    
## 2   2017      1      1     일 ARP1 ARP3   A A1905 SEw4MjM2   D   N   N    
## 3   2017      1      1     일 ARP1 ARP3   L L1751 SEw4MjM3   D   N   N    
## 4   2017      1      1     일 ARP1 ARP3   F F1201 SEw4MjA3   D   N   N    
## 5   2017      1      1     일 ARP3 ARP1   A A1900 SEw3NzAz   D   N   N    
## 6   2017      1      1     일 ARP1 ARP3   H H1101 SEw4MDMx   D   N   N    
##   CNL CNR HOUR count timediff
## 1   N        6    10        8
## 2   N        6    10       10
## 3   N        6    10       10
## 4   N        6    10        9
## 5   N        6     2        7
## 6   N        6    10        8


새로운 변수 만들기 (A/C 정비와 그 외의 지연코드)

afsnt$DRR.group <- ifelse(afsnt$DRR == "C02",
                          "C02",
                          "Non-C02")

afsnt$DRR.group <- as.factor(afsnt$DRR.group)

head(afsnt)

##   SDT_YY SDT_MM SDT_DD SDT_DY  ARP  ODP FLO   FLT      REG AOD IRR DLY DRR
## 1   2017      1      1     일 ARP1 ARP3   A A1901 SEw3Nzc2   D   N   N    
## 2   2017      1      1     일 ARP1 ARP3   A A1905 SEw4MjM2   D   N   N    
## 3   2017      1      1     일 ARP1 ARP3   L L1751 SEw4MjM3   D   N   N    
## 4   2017      1      1     일 ARP1 ARP3   F F1201 SEw4MjA3   D   N   N    
## 5   2017      1      1     일 ARP3 ARP1   A A1900 SEw3NzAz   D   N   N    
## 6   2017      1      1     일 ARP1 ARP3   H H1101 SEw4MDMx   D   N   N    
##   CNL CNR HOUR count timediff DRR.group
## 1   N        6    10        8   Non-C02
## 2   N        6    10       10   Non-C02
## 3   N        6    10       10   Non-C02
## 4   N        6    10        9   Non-C02
## 5   N        6     2        7   Non-C02
## 6   N        6    10        8   Non-C02


편명별 C02 비율

a <- afsnt %>% 
  dplyr::group_by(FLT) %>% 
  dplyr::summarise(n = n())
b <- afsnt %>% 
  dplyr::filter(DRR.group == "C02") %>% dplyr::group_by(FLT) %>% dplyr::summarise(n = n())
c <- as.data.frame(left_join(a, b, by = "FLT"))

c[is.na(c)] <- 0

colnames(c) <- c("FLT", "x", "y")
c$x <- as.numeric(c$x)
c$FLT_C02_ratio <-  (c$y/c$x)*100
colnames(c) <- c("FLT", "x", "y", "FLT_C02_ratio")
c <- c %>% select(-c(x,y))

head(c)

##     FLT FLT_C02_ratio
## 1 A1001      2.398524
## 2 A1002     36.229508
## 3 A1003     11.299435
## 4 A1004     12.109375
## 5 A1005     11.574074
## 6 A1006      7.421875


편명별 부정기 비율

a <- afsnt %>% 
  dplyr::group_by(FLT) %>% 
  dplyr::summarise(n = n())
b <- afsnt %>% 
  dplyr::filter(IRR == "Y") %>% dplyr::group_by(FLT) %>% dplyr::summarise(n = n())
i <- as.data.frame(left_join(a, b, by = "FLT"))

i[is.na(i)] <- 0

colnames(i) <- c("FLT", "x", "y")
i$x <- as.numeric(i$x)
i$FLT.IRR_ratio <-  (i$y/i$x)*100
colnames(i) <- c("FLT","x","y", "FLT_IRR_ratio")
i <- i %>% select(-c(x,y))

head(i)

##     FLT FLT_IRR_ratio
## 1 A1001      0.000000
## 2 A1002      0.000000
## 3 A1003      6.779661
## 4 A1004     10.156250
## 5 A1005      0.000000
## 6 A1006      2.343750


편명별 평균 지연 시간

f <- afsnt %>% 
  dplyr::group_by(FLT) %>% 
  dplyr::summarise(mean(timediff, na.rm = TRUE))

colnames(f) <- c("FLT", "FLT_meantimediff")
f$FLT_meantimediff <- as.numeric(f$FLT_meantimediff)
head(f)

## # A tibble: 6 x 2
##   FLT   FLT_meantimediff
##   <fct>            <dbl>
## 1 A1001             10.3
## 2 A1002             27.9
## 3 A1003             18.3
## 4 A1004             18.6
## 5 A1005             21.3
## 6 A1006             18.4


편명별 지연율

a <- afsnt %>% 
  dplyr:::group_by(FLT) %>% 
  dplyr:::summarise(n = n())
b <- afsnt %>% dplyr:::filter(DLY == "Y") %>%
  dplyr:::group_by(FLT) %>% 
  dplyr:::summarise(n = n())
g <- as.data.frame(left_join(a, b, by = "FLT"))

g[is.na(g)] <- 0

colnames(g) <- c("FLT", "x", "y")
g$x <- as.numeric(g$x)
g$FLT_DLY_ratio <-  (g$y/g$x)*100
g <- g %>%  select(-c(x,y))
colnames(g) <- c("FLT","FLT_DLY_ratio")

m <- left_join(c, i, by = "FLT")
m <- left_join(m, f, by = "FLT")
m <- left_join(m, g, by = "FLT")
afsnt <- left_join(afsnt, m, by = "FLT")

head(afsnt)

##   SDT_YY SDT_MM SDT_DD SDT_DY  ARP  ODP FLO   FLT      REG AOD IRR DLY DRR
## 1   2017      1      1     일 ARP1 ARP3   A A1901 SEw3Nzc2   D   N   N    
## 2   2017      1      1     일 ARP1 ARP3   A A1905 SEw4MjM2   D   N   N    
## 3   2017      1      1     일 ARP1 ARP3   L L1751 SEw4MjM3   D   N   N    
## 4   2017      1      1     일 ARP1 ARP3   F F1201 SEw4MjA3   D   N   N    
## 5   2017      1      1     일 ARP3 ARP1   A A1900 SEw3NzAz   D   N   N    
## 6   2017      1      1     일 ARP1 ARP3   H H1101 SEw4MDMx   D   N   N    
##   CNL CNR HOUR count timediff DRR.group FLT_C02_ratio FLT_IRR_ratio
## 1   N        6    10        8   Non-C02     0.8324084     0.0000000
## 2   N        6    10       10   Non-C02     0.7168459     0.0000000
## 3   N        6    10       10   Non-C02     0.0000000     0.0000000
## 4   N        6    10        9   Non-C02     0.6365741     0.0000000
## 5   N        6     2        7   Non-C02     0.2257336     0.3386005
## 6   N        6    10        8   Non-C02     0.4540295     0.0000000
##   FLT_meantimediff FLT_DLY_ratio
## 1         8.551054      2.164262
## 2         9.765233      2.508961
## 3         8.232143      2.380952
## 4         9.984954      3.298611
## 5         6.276524      1.467269
## 6        10.640182      3.064699


afsnt_dly에 변수 추가

afsnt_dly <- left_join(afsnt_dly, m, by = "FLT")

## Warning: Column `FLT` joining factors with different levels, coercing to
## character vector
afsnt_dly$FLT <- as.factor(afsnt_dly$FLT)

head(afsnt_dly)

##   SDT_YY SDT_MM SDT_DD SDT_DY  ARP  ODP FLO   FLT AOD   STT DLY DLY_RATE
## 1   2019      9     16     월 ARP1 ARP3   L L1702   A  9:05  NA       NA
## 2   2019      9     16     월 ARP3 ARP1   L L1702   D  7:55  NA       NA
## 3   2019      9     16     월 ARP1 ARP3   L L1720   A 14:40  NA       NA
## 4   2019      9     16     월 ARP3 ARP1   L L1720   D 13:30  NA       NA
## 5   2019      9     16     월 ARP4 ARP3   L L1808   A 20:10  NA       NA
## 6   2019      9     16     월 ARP3 ARP4   L L1808   D 19:10  NA       NA
##   FLT_C02_ratio FLT_IRR_ratio FLT_meantimediff FLT_DLY_ratio
## 1      5.091312     1.8262313         12.28832      5.755396
## 2      5.091312     1.8262313         12.28832      5.755396
## 3     22.232472     0.1845018         20.32472     22.785978
## 4     22.232472     0.1845018         20.32472     22.785978
## 5     22.436604     0.2205072         21.50331     20.507166
## 6     22.436604     0.2205072         21.50331     20.507166


afsnt_dly의 편명별 비율 데이터 결측치 채우기

FLO_J <- afsnt %>% 
  dplyr::filter(FLO == "J") %>% 
  select(20:23) %>% 
  summarise(mean_FLT_CO2_ratio = median(FLT_C02_ratio),
            mean_FLT_IRR_ratio = median(FLT_IRR_ratio),
            mean_FLT_meantimediff = median(FLT_meantimediff),
            mean_FLT_DLY_ratio = median(FLT_DLY_ratio))

IRR_y <- afsnt %>% 
  dplyr::filter(IRR == "Y") 

IRR_yy <- IRR_y %>% 
  select(20:23) %>% 
  summarise(mean_FLT_CO2_ratio = median(FLT_C02_ratio),
            mean_FLT_IRR_ratio = 0,
            mean_FLT_meantimediff = median(FLT_meantimediff),
            mean_FLT_DLY_ratio = median(FLT_DLY_ratio))

afsnt_dly[afsnt_dly$FLO == "J" & afsnt_dly$FLT_C02_ratio %>% is.na(), c(13:16)] <- FLO_J

afsnt_dly[afsnt_dly$FLO == "M", c(13:16)] <- IRR_yy


afsnt_dly 시간대별 편 수 계산

afsnt_dly$STT <- as.character(afsnt_dly$STT)
b <- sapply(afsnt_dly[, "STT"],  function(x) {x %>% str_split(pattern = ':')  %>% `[[`(1) })
HOUR_nd <- b[1, ] %>% as.numeric()

afsnt_dly$HOUR <- HOUR_nd
afsnt_dly$HOUR <- as.factor(afsnt_dly$HOUR)

afsnt_dly_count <- afsnt_dly %>%
 dplyr::group_by(SDT_YY, SDT_MM, SDT_DD, ARP, HOUR) %>%
 dplyr::summarise('count' = n())

afsnt_dly <- left_join(afsnt_dly, afsnt_dly_count, by = c("SDT_YY", "SDT_MM", "SDT_DD", "ARP", "HOUR"))

head(afsnt_dly)

##   SDT_YY SDT_MM SDT_DD SDT_DY  ARP  ODP FLO   FLT AOD   STT DLY DLY_RATE
## 1   2019      9     16     월 ARP1 ARP3   L L1702   A  9:05  NA       NA
## 2   2019      9     16     월 ARP3 ARP1   L L1702   D  7:55  NA       NA
## 3   2019      9     16     월 ARP1 ARP3   L L1720   A 14:40  NA       NA
## 4   2019      9     16     월 ARP3 ARP1   L L1720   D 13:30  NA       NA
## 5   2019      9     16     월 ARP4 ARP3   L L1808   A 20:10  NA       NA
## 6   2019      9     16     월 ARP3 ARP4   L L1808   D 19:10  NA       NA
##   FLT_C02_ratio FLT_IRR_ratio FLT_meantimediff FLT_DLY_ratio HOUR count
## 1      5.091312     1.8262313         12.28832      5.755396    9    25
## 2      5.091312     1.8262313         12.28832      5.755396    7    24
## 3     22.232472     0.1845018         20.32472     22.785978   14    26
## 4     22.232472     0.1845018         20.32472     22.785978   13    30
## 5     22.436604     0.2205072         21.50331     20.507166   20     3
## 6     22.436604     0.2205072         21.50331     20.507166   19    28


Train set, Test set 샘플링

afsnt <- afsnt[ , -c(6,8,9,11,13,14,15,18,19)]

afsnt_dly$SDT_YY <- as.factor(afsnt_dly$SDT_YY)
afsnt_dly$SDT_MM <- as.factor(afsnt_dly$SDT_MM)
afsnt_dly$SDT_DD <- as.factor(afsnt_dly$SDT_DD)
afsnt_dly$HOUR <- as.factor(afsnt_dly$HOUR)

# 예측률을 높이기 위하여 미지연과 지연 비율을 73:27로 맞춰서 학습데이터 적합 
# 같은 결과를 얻기 위해 seed를 설정합니다. 
set.seed(seed = 123)

# 목적변수 비율 맞춰 샘플링 하기 
afsnt_Y <- afsnt[(afsnt$DLY == "Y"), ]
afsnt_N <- afsnt[(afsnt$DLY == "N"), ]

# 트레인 테스트 셋 샘플링하기 위해 다음과 같이 처리합니다. 
index <- sample(x = 1:2, 
                size = nrow(x = afsnt_N), 
                prob = c(0.7, 0.3), 
                replace = TRUE) 

trainSet_N <- afsnt_N[index == 2,]

index <- sample(x = 1:2, 
                size = nrow(x = afsnt_Y), 
                prob = c(0.8, 0.2), 
                replace = TRUE) 

trainSet_Y <- afsnt_Y[index == 1,]
trainSet <- rbind(trainSet_Y, trainSet_N)

# 테스트 데이터 셋은 실제 미지연과 지연 데이터 비율인 87:13에 맞춰 적합
testSet_N <- afsnt_N[index == 1,]
testSet_N <- sample_n(testSet_N, 160000)

testSet_Y <- afsnt_Y[index == 2, ]

testSet <- rbind(testSet_Y, testSet_N)

# 훈련용, 시험용 데이터셋의 목표변수 비중을 확인합니다.  
trainSet$DLY %>% table() %>% prop.table()

## .
##         N         Y 
## 0.7305399 0.2694601
testSet$DLY %>% table() %>% prop.table()

## .
##         N         Y 
## 0.8704925 0.1295075


랜덤포레스트 모델 성능확인

# 랜덤 포레스트 분류모형 성능 확인하기 위해 ntree = 50, mtry = 5를 임의로 넣어 모델 적합
fitRFC <- randomForest(x = trainSet[, -8], 
                       y = trainSet[, 8], 
                       xtest = testSet[, -8], 
                       ytest = testSet[, 8], 
                       ntree = 50, 
                       mtry = 5, 
                       importance = TRUE, 
                       do.trace = 50, 
                       keep.forest = TRUE)

## ntree      OOB      1      2|    Test      1      2
##    50:  22.05% 11.91% 49.52%|  13.02%  7.59% 49.54%
# 모형 적합 결과를 확인합니다. 
print(x = fitRFC)

## 
## Call:
##  randomForest(x = trainSet[, -8], y = trainSet[, 8], xtest = testSet[,      -8], ytest = testSet[, 8], ntree = 50, mtry = 5, importance = TRUE,      do.trace = 50, keep.forest = TRUE) 
##                Type of random forest: classification
##                      Number of trees: 50
## No. of variables tried at each split: 5
## 
##         OOB estimate of  error rate: 22.05%
## Confusion matrix:
##        N     Y class.error
## N 227195 30717   0.1190988
## Y  47113 48018   0.4952434
##                 Test set error rate: 13.02%
## Confusion matrix:
##        N     Y class.error
## N 147859 12141  0.07588125
## Y  11793 12011  0.49542094
# OOB 에러 추정값을 그래프로 그립니다. 
plot(x = fitRFC$err.rate[, 1], 
     ylab = 'OOB Error', 
     type = 'l')

# 변수의 중요도를 그래프로 출력합니다. 내림차순으로 정렬되어 출력되므로 한 눈에 파악됩니다.
varImpPlot(x = fitRFC, main = 'Random Forest Classification Model with afsnt Dataset')


AUROC 구하는 함수 적합

# 분류모형의 ROC 커브 및 AUROC를 반환하는 사용자 정의 함수를 생성합니다. 
getROC <- function(real, pred) {

  # pred와 real이 범주형일 수 있으므로 숫자형 벡터로 변환합니다. 
  pred <- pred %>% as.numeric()
  real <- real %>% as.numeric()

  # ROC 커브를 그리기 위해 prediction object를 생성합니다. 
  # pred와 real이 범주형일 수 있으므로 숫자형 벡터로 변환합니다. 
  predObj <- prediction(predictions = pred, 
                        labels = real)

  # predObj 객체를 활용하여 performance 객체를 생성합니다. 
  perform <- performance(prediction.obj = predObj, 
                         measure = 'tpr', 
                         x.measure = 'fpr')

  # ROC 커브를 그립니다. 
  plot(x = perform, main = 'ROC curve')

  # 편의상 왼쪽 아래 모서리에서 오른쪽 위 모서리를 잇는 대각선을 추가합니다. 
  lines(x = c(0, 1), y = c(0, 1), col = 'red', lty = 2)

  # AUROC를 계산합니다. 
  auroc <- auc(real, pred)
  print(x = auroc)

  # AUROC를 ROC 그래프 오른쪽 아래에 추가합니다. 
  text(x = 0.9, y = 0, labels = str_c('AUROC : ', auroc), col = 'red', font = 2)

}


모델 성능 확인

# trainSet의 추정확률과 추정값(레이블)을 trProb, trPred에 할당합니다. 
trProb <- fitRFC$test$votes[, 2]
trPred <- fitRFC$test$predicted

# 훈련셋의 실제값을 trReal에 할당합니다. 
trReal <- testSet$DLY

# 혼동행렬을 출력합니다. 
confusionMatrix(data = trPred, reference = trReal, positive = 'Y')

## Confusion Matrix and Statistics
## 
##           Reference
## Prediction      N      Y
##          N 147859  11793
##          Y  12141  12011
##                                           
##                Accuracy : 0.8698          
##                  95% CI : (0.8682, 0.8713)
##     No Information Rate : 0.8705          
##     P-Value [Acc > NIR] : 0.8177          
##                                           
##                   Kappa : 0.426           
##  Mcnemar's Test P-Value : 0.0249          
##                                           
##             Sensitivity : 0.50458         
##             Specificity : 0.92412         
##          Pos Pred Value : 0.49731         
##          Neg Pred Value : 0.92613         
##              Prevalence : 0.12951         
##          Detection Rate : 0.06535         
##    Detection Prevalence : 0.13140         
##       Balanced Accuracy : 0.71435         
##                                           
##        'Positive' Class : Y               
## 
# F1 점수를 확인합니다.
F1_Score(y_pred = trPred, y_true = trReal, positive = 'Y')

## [1] 0.5009175
# 추정레이블로 ROC 그래프를 그리고 AUROC를 확인합니다. 
getROC(real = trReal, pred = trPred)

## Area under the curve: 0.7143
# 추정확률로 ROC 그래프를 그리고 AUROC를 확인합니다. 
getROC(real = trReal, pred = trProb)

## Area under the curve: 0.8562


afsnt_dly DLY 예측 학습 셋 적합

# 위와 마찬가지로 미지연과 지연의 비율을 73:27로 맞춰 학습셋 적합
afsnt_Y <- afsnt[(afsnt$DLY == "Y"), ]
afsnt_N <- afsnt[(afsnt$DLY == "N"), ]

# 존재하는 지연 데이터 개수에 맞는 미지연 데이터(32150행) 추출 후 바인딩
trainSet_N <- sample_n(afsnt_N, 321560)
trainSet <- rbind(afsnt_Y, trainSet_N)
afsnt_dly <- afsnt_dly[c(colnames(trainSet))]

# 랜덤 포레스트 분류모형을 적합합니다. (그리드 서칭 결과 최적의 ntree, mtry 결정)
# 다른 범주가 존재하는 'FLO' 변수 제거
fitRFC <- randomForest(x = trainSet[, -c(6,8)], 
                       y = trainSet[, 8], 
                       xtest = afsnt_dly[, -c(6,8)], 
                       ntree = 500, 
                       mtry = 5, 
                       importance = TRUE, 
                       do.trace = 50, 
                       keep.forest = TRUE)

## ntree      OOB      1      2
##    50:  21.91% 11.63% 49.70%
##   100:  21.08% 10.66% 49.24%
##   150:  20.79% 10.34% 49.05%
##   200:  20.66% 10.17% 49.02%
##   250:  20.58% 10.07% 49.00%
##   300:  20.53% 10.03% 48.91%
##   350:  20.47%  9.97% 48.85%
##   400:  20.42%  9.92% 48.80%
##   450:  20.42%  9.91% 48.85%
##   500:  20.40%  9.89% 48.82%
trProb <- fitRFC$test$votes[, 2]
trPred <- fitRFC$test$predicted

final <- cbind(trPred, trProb) %>% as.data.frame()
colnames(final) <- c("DLY", "DLY_RATE")
final$DLY <- as.factor(final$DLY)
final$DLY = revalue(final$DLY, replace=c("1"="N", "2"="Y"))

# 기존 afsnt_dly에 예측한 DLY, DLY_RATE 컬럼 추가
afsnt_dly_final <- cbind(afsnt_dly, final)

write.csv(afsnt_dly_final, file = "afsnt_dly_final.csv", row.names = FALSE)
head(afsnt_dly_final)

##   SDT_YY SDT_MM SDT_DD SDT_DY  ARP FLO AOD DLY HOUR count FLT_C02_ratio
## 1   2019      9     16     월 ARP1   L   A  NA    9    25      5.091312
## 2   2019      9     16     월 ARP3   L   D  NA    7    24      5.091312
## 3   2019      9     16     월 ARP1   L   A  NA   14    26     22.232472
## 4   2019      9     16     월 ARP3   L   D  NA   13    30     22.232472
## 5   2019      9     16     월 ARP4   L   A  NA   20     3     22.436604
## 6   2019      9     16     월 ARP3   L   D  NA   19    28     22.436604
##   FLT_IRR_ratio FLT_meantimediff FLT_DLY_ratio DLY DLY_RATE
## 1     1.8262313         12.28832      5.755396   N    0.062
## 2     1.8262313         12.28832      5.755396   N    0.272
## 3     0.1845018         20.32472     22.785978   N    0.346
## 4     0.1845018         20.32472     22.785978   Y    0.842
## 5     0.2205072         21.50331     20.507166   N    0.346
## 6     0.2205072         21.50331     20.507166   Y    0.560