이 분석의 목적은 hflights 패키지에 내장된 hflights의 데이터를 다양한 방식으로 탐색하는 것이다.
이러한 탐색을 통해서 이 데이터로부터 통찰력을 얻고, 어떤 머신러닝 분석을 수행할 수 있는지 탐색해 보는 것이다.
library(hflights) # hflights 데이터를 사용하기 위해서 필요함
str(hflights)
'data.frame': 227496 obs. of 21 variables:
$ Year : int 2011 2011 2011 2011 2011 2011 2011 2011 2011 2011 ...
$ Month : int 1 1 1 1 1 1 1 1 1 1 ...
$ DayofMonth : int 1 2 3 4 5 6 7 8 9 10 ...
$ DayOfWeek : int 6 7 1 2 3 4 5 6 7 1 ...
$ DepTime : int 1400 1401 1352 1403 1405 1359 1359 1355 1443 1443 ...
$ ArrTime : int 1500 1501 1502 1513 1507 1503 1509 1454 1554 1553 ...
$ UniqueCarrier : chr "AA" "AA" "AA" "AA" ...
$ FlightNum : int 428 428 428 428 428 428 428 428 428 428 ...
$ TailNum : chr "N576AA" "N557AA" "N541AA" "N403AA" ...
$ ActualElapsedTime: int 60 60 70 70 62 64 70 59 71 70 ...
$ AirTime : int 40 45 48 39 44 45 43 40 41 45 ...
$ ArrDelay : int -10 -9 -8 3 -3 -7 -1 -16 44 43 ...
$ DepDelay : int 0 1 -8 3 5 -1 -1 -5 43 43 ...
$ Origin : chr "IAH" "IAH" "IAH" "IAH" ...
$ Dest : chr "DFW" "DFW" "DFW" "DFW" ...
$ Distance : int 224 224 224 224 224 224 224 224 224 224 ...
$ TaxiIn : int 7 6 5 9 9 6 12 7 8 6 ...
$ TaxiOut : int 13 9 17 22 9 13 15 12 22 19 ...
$ Cancelled : int 0 0 0 0 0 0 0 0 0 0 ...
$ CancellationCode : chr "" "" "" "" ...
$ Diverted : int 0 0 0 0 0 0 0 0 0 0 ...
총 21개의 컬럼에 227486 개의 행으로 이루어졌다.
?hflights
Year, Month, DayofMonth: 출발 년월일
DayOfWeek: 출발 요일 (주말 효과 제거에 유용)
DepTime, ArrTime: 출발 및 도착 시간 (현지 시간, hhmm)
UniqueCarrier: 운송 업체의 고유 약어(항공사)
FlightNum: 항공편 번호
TailNum: 비행기 꼬리 번호(항공기 등록 번호)
ActualElapsedTime: 비행 경과 시간 (분): ArrTime - DepTime
AirTime: 비행 시간 (분): 하늘에 떠 있는 시간
ArrDelay, DepDelay: 도착 및 출발 지연 (분)
Origin, Dest origin and destination airport codes: 출발지, 목적지 출발지 및 목적지 공항 코드
Distance: 비행 거리 (마일)
TaxiIn, TaxiOut: 몇 분 안에 택시를 타고 내릴 수 있습니다.
Cancelled: 취소됨 표시기 : 1 = 예, 0 = 아니요
CancellationCode: 취소 이유 : A = 항공사, B = 날씨, C = 국가 항공 시스템, D = 보안
Diverted: 전환됨 표시기 : 1 = 예, 0 = 아니요
위 각 컬럼의 의미를 세세히 아는 것은 항공 산업의 영역이라고 할 수 있다. 그래서 데이터 분석가는 항공 산업의 전문가와 소통을 통해서 위 컬럼의 의미를 최대한 정확히 아는 것이 중요하다.
R 데이터 프레임에서 결측치는 NA, NaN, Infinite가 있을수 있는데, 모든 컬럼에 대해 확인해 보자.
결측치는 아래와 같이 4가지 종류가 있다.
NA: is.na, NaN: is.nan, Infinite: is.infinite
library(dplyr) # %>% 연산자를 사용하기 위해서 필요함
hflights %>% sapply(is.na) %>% class() # 이 함수를 수행하면 matrix, array 형이다.
[1] "matrix" "array"
hflights %>% sapply(is.na) %>% colSums()
Year Month DayofMonth DayOfWeek
0 0 0 0
DepTime ArrTime UniqueCarrier FlightNum
2905 3066 0 0
TailNum ActualElapsedTime AirTime ArrDelay
0 3622 3622 3622
DepDelay Origin Dest Distance
2905 0 0 0
TaxiIn TaxiOut Cancelled CancellationCode
3066 2947 0 0
Diverted
0
hflights %>% sapply(is.nan) %>% colSums()
Year Month DayofMonth DayOfWeek
0 0 0 0
DepTime ArrTime UniqueCarrier FlightNum
0 0 0 0
TailNum ActualElapsedTime AirTime ArrDelay
0 0 0 0
DepDelay Origin Dest Distance
0 0 0 0
TaxiIn TaxiOut Cancelled CancellationCode
0 0 0 0
Diverted
0
hflights %>% sapply(is.infinite) %>% colSums()
Year Month DayofMonth DayOfWeek
0 0 0 0
DepTime ArrTime UniqueCarrier FlightNum
0 0 0 0
TailNum ActualElapsedTime AirTime ArrDelay
0 0 0 0
DepDelay Origin Dest Distance
0 0 0 0
TaxiIn TaxiOut Cancelled CancellationCode
0 0 0 0
Diverted
0
hflights %>% sapply(is.na) %>% class() 를 수행하면, 자료의 구조가 matrix, array이다. 그래서 테이블에 적용하는 함수들 적용이 가능하다.(예, colSums()) 확인 결과 NA 값의 결측치만 있고, NaN 또는 Inf 결측값은 없다.
결측치를 어떻게 처리할 지는 좀 더 탐색을 수행한 후 정하기로 한다.
library(data.table) # table() 함수를 사용하기 위해서 필요함
hflights %>% sapply(table) %>% sapply(length)
Year Month DayofMonth DayOfWeek
1 12 31 7
DepTime ArrTime UniqueCarrier FlightNum
1207 1283 15 3740
TailNum ActualElapsedTime AirTime ArrDelay
3320 435 398 463
DepDelay Origin Dest Distance
429 2 116 159
TaxiIn TaxiOut Cancelled CancellationCode
96 143 2 5
Diverted
2
2011년 12개월 데이터, 항공사(UniqueCarrier)는 총 15개, 출발지(Origin)는 2개, 도착지(Dest)는 총 116개인 것을 알 수 있다.
library(ggplot2) # ggplot 함수를 사용하기 위해서 필요함
hflights %>% group_by(Month) %>% summarise(n=n())
# A tibble: 12 x 2
Month n
<int> <int>
1 1 18910
2 2 17128
3 3 19470
4 4 18593
5 5 19172
6 6 19600
7 7 20548
8 8 20176
9 9 18065
10 10 18696
11 11 18021
12 12 19117
hflights %>% group_by(Month) %>% summarise(n=n()) %>% ggplot()+aes(x = as.factor(Month), y = n, fill=as.factor(Month))+geom_col()+xlab("Month")+ylab("운황 횟수")+labs(title = "월별 운항 횟수")+theme(plot.title = element_text(hjust = 0.5, size =15))+guides(fill=guide_legend(title="Month"))+theme(legend.position = "none")+theme(axis.title.y = element_text(size = 15))
hflights %>% group_by(DayOfWeek) %>% summarise(n=n())
# A tibble: 7 x 2
DayOfWeek n
<int> <int>
1 1 34360
2 2 31649
3 3 31926
4 4 34902
5 5 34972
6 6 27629
7 7 32058
hflights %>%
group_by(DayOfWeek) %>%
summarise(n=n()) %>%
ggplot()+
aes(x = as.factor(DayOfWeek), y=n, fill=as.factor(DayOfWeek))+
geom_col()+
xlab("Day of Week")+
ylab("운항 횟수") +
labs(title = "요일별 운항 횟수")+
theme(plot.title = element_text(hjust = 0.5, size = 15))+
guides(fill=guide_legend(title = "Day Of Week"))+
theme(legend.position = "none")+
theme(axis.title.y = element_text(size = 15))
월별로는 7~8월이 성수기인 것으로 보이고, 요일별로는 금요일이 가장 적어 보인다.
hflights %>% group_by(UniqueCarrier ) %>%
ggplot()+aes(x = UniqueCarrier, fill = UniqueCarrier)+
geom_bar()+
labs(title = "항공사별 운항 횟수")+
ylab("운항 횟수")+
xlab("항공사")+
theme(plot.title = element_text(hjust = 0.5, size = 25))+
theme(axis.title = element_text(size = 15))+
theme(legend.position = "none")
hflights %>% group_by(UniqueCarrier) %>% filter(Cancelled==1) %>% summarise(n=n())
# A tibble: 14 x 2
UniqueCarrier n
<chr> <int>
1 AA 60
2 B6 18
3 CO 475
4 DL 42
5 EV 76
6 F9 6
7 FL 21
8 MQ 135
9 OO 224
10 UA 34
11 US 46
12 WN 703
13 XE 1132
14 YV 1
hflights %>% group_by(UniqueCarrier) %>% filter(Cancelled==1) %>% ggplot()+aes(x = UniqueCarrier, fill=UniqueCarrier)+geom_bar()+labs(title = "항공사별 운항 취소 횟수")+theme(plot.title = element_text(hjust = 0.5, size = 15))+theme(legend.position = "none")
hflights %>% group_by(UniqueCarrier) %>% summarise(n=n()) -> total
hflights %>% group_by(UniqueCarrier) %>% filter(Cancelled==1) %>% summarise(CCC=n())-> Cancel
merge(total, Cancel, by = "UniqueCarrier", all = T) %>%
mutate(CCC=case_when(CCC=is.na(CCC) ~ 0L, TRUE ~ CCC)) %>%
mutate(Cancelled_ratio=100*CCC/n) %>%
ggplot()+
aes(x = UniqueCarrier, y = Cancelled_ratio, fill = UniqueCarrier)+
geom_col()+
labs(title = "항공사별 운항 취소율")+
ylab("운항 취소율(%)")+
xlab("항공사")+
theme(plot.title = element_text(hjust = 0.5, size = 25))+
theme(axis.title = element_text(size = 15))+
theme(legend.position = "none")
항공사별 운항 횟수와 취소율을 비교해보니, 운항 횟수가 적은 회사들의 취소율이 매우 높은 것을 알 수 있다.
EV 항공사가 3.5% 대로 가장 높고, AS는 취소율이 거의 없다는 것을 알 수 있다.
그렇다면 취소 이유를 살펴볼 필요가 있다.
#### 2.6 각 항공사별 취소 이유 분석
# 항공사별 취소 이유의 개수를 A,B,C,D만 막대그래프로 그려보자.
hflights %>% group_by(UniqueCarrier) %>% select(CancellationCode) %>% table()
CancellationCode
UniqueCarrier A B C D
AA 3184 20 29 11 0
AS 365 0 0 0 0
B6 677 5 13 0 0
CO 69557 37 436 2 0
DL 2599 13 27 2 0
EV 2128 60 14 2 0
F9 832 2 4 0 0
FL 2118 8 12 1 0
MQ 4513 39 71 25 0
OO 15837 121 87 15 1
UA 2038 21 10 3 0
US 4036 27 17 2 0
WN 44640 517 181 5 0
XE 71921 331 751 50 0
YV 78 1 0 0 0
hflights %>%
group_by(UniqueCarrier) %>%
count(CancellationCode) %>%
filter(CancellationCode!="") %>%
ggplot()+aes(x = UniqueCarrier, y = n, fill=CancellationCode)+
geom_bar(stat = "identity", position = "dodge")+
labs(title = "원인 별 취소 건수:A-항공사,B-날씨, C-국가항공시스템, D-보안")+
theme(plot.title = element_text(hjust = 0.5))
이제 출발 지연(DepDelay), 도착 지연(ArrDelay)이 얼마나 이루어지고 있는지 확인해 보자.
지연이 “-” 값이 있는 것은 빨리 출발하거나 빨리 도착하는 경우가 될 것이다.
이제 항공사별로 출발 지연 및 도착 지연의 횟수, 총 시간 등을 확인해 보자.(“-” 값은 제외하고.)
# 항공사 전체 출발 및 도착 지연 총 횟수
hflights %>% ggplot()+aes(DepDelay)+stat_count(color='blue', alpha=0.5)
Warning: Removed 2905 rows containing non-finite values (stat_count).
hflights %>% ggplot()+aes(ArrDelay)+stat_count(color='blue', alpha=0.5)
Warning: Removed 3622 rows containing non-finite values (stat_count).
# 항공사별 지연 시간
hflights %>%ggplot()+aes(x = DepDelay, group = UniqueCarrier, color=UniqueCarrier)+geom_line(stat="count")
Warning: Removed 2905 rows containing non-finite values (stat_count).
# 항공사 별 30분 이상 출발 지연 횟수
hflights %>% filter(DepDelay>30) %>% group_by(UniqueCarrier) %>%
ggplot()+aes(UniqueCarrier, fill=UniqueCarrier)+
geom_bar()+
labs(title = "30분 이상 출발 지연")+ theme(plot.title = element_text(hjust = 0.5, size = 20))+
theme(legend.position = "none")
# 항공사 별 60분 이상 출발 지연 횟수 : 시간을 바꿔가며 볼 필요가 있다.
hflights %>% filter(DepDelay>60) %>% ggplot()+aes(x = DepDelay, group = UniqueCarrier, color=UniqueCarrier)+geom_line(stat="count")
hflights %>% filter(ArrDelay>60) %>% ggplot()+aes(x = DepDelay, group = UniqueCarrier, color=UniqueCarrier)+geom_line(stat="count")
# boxplot으로 출발 및 도착 지연을 살펴보자
hflights %>%
ggplot()+
aes(x = DepDelay, y = UniqueCarrier, fill=UniqueCarrier)+
geom_boxplot()
Warning: Removed 2905 rows containing non-finite values (stat_boxplot).
hflights %>%
ggplot()+
aes(x = ArrDelay, y = UniqueCarrier, fill=UniqueCarrier)+
geom_boxplot()+
coord_flip()
Warning: Removed 3622 rows containing non-finite values (stat_boxplot).
# 항공사별 출발 및 도착 시간의 통계를 살펴보자
hflights %>% group_by(UniqueCarrier) %>% filter(DepDelay>0) %>% summarise(mean=mean(DepDelay, na.rm = T), max=max(DepDelay, na.rm = T), sum=sum(DepDelay, na.rm = T))
# A tibble: 15 x 4
UniqueCarrier mean max sum
<chr> <dbl> <int> <int>
1 AA 24.7 970 29116
2 AS 20.8 172 2639
3 B6 43.5 310 11059
4 CO 17.9 981 719252
5 DL 32.4 730 30015
6 EV 49.3 479 32659
7 F9 22.7 275 6637
8 FL 33.4 507 16552
9 MQ 37.9 931 62763
10 OO 24.6 360 167882
11 UA 28.8 869 29281
12 US 26.5 425 22005
13 WN 21.9 548 630786
14 XE 26.9 628 718548
15 YV 24.5 54 367
hflights %>% group_by(UniqueCarrier) %>% filter(DepDelay>0) %>% summarise(mean=mean(DepDelay, na.rm = T)) %>%
ggplot()+aes(x = UniqueCarrier, y = mean, fill=UniqueCarrier)+
geom_col()+
labs(title = "항공사별 평균 출발 지연 시간")+
theme(plot.title = element_text(hjust = 0.5, size = 20))
hflights %>% group_by(UniqueCarrier) %>% filter(ArrDelay>0) %>% summarise(mean=mean(ArrDelay, na.rm = T), max=max(ArrDelay, na.rm = T), sum=sum(ArrDelay, na.rm = T))
# A tibble: 15 x 4
UniqueCarrier mean max sum
<chr> <dbl> <int> <int>
1 AA 28.5 978 27443
2 AS 22.9 183 3643
3 B6 45.5 335 12097
4 CO 22.1 957 753521
5 DL 32.1 701 32221
6 EV 40.2 469 31389
7 F9 18.7 277 8652
8 FL 27.9 500 18302
9 MQ 38.8 918 64521
10 OO 24.1 380 203870
11 UA 32.5 861 32773
12 US 20.7 433 27265
13 WN 25.3 499 522865
14 XE 24.2 634 857147
15 YV 18.7 72 691
hflights %>% group_by(UniqueCarrier) %>% filter(ArrDelay>0) %>% summarise(mean=mean(DepDelay, na.rm = T)) %>%
ggplot()+aes(x = UniqueCarrier, y = mean, fill=UniqueCarrier)+
geom_col()+
labs(title = "항공사별 평균 도착 지연 시간")+
theme(plot.title = element_text(hjust = 0.5, size = 20))
# 항공사별 평균 출발/도착 지연시간을 하나의 그래프에서 살펴보자
library(tidyverse) # gather() & spread() 함수르 사용하기 위해서 필요함.
hflights %>% group_by(UniqueCarrier) %>%
filter(DepDelay>0 & ArrDelay>0) %>%
summarise(dep_mean=mean(DepDelay, na.rm = T), arr_mean=mean(ArrDelay, na.rm = T)) %>%
# 가로형 테이블을 세로형 테이블로 변경
gather(key = "dep_arr", value = "mean", -UniqueCarrier) %>%
ggplot()+
aes(x = UniqueCarrier, y = mean, group=dep_arr, fill=dep_arr)+
geom_col(position = "dodge")+
labs(title = "항공사별 평균 출발/도착 지연 시간")+
theme(plot.title = element_text(hjust = 0.5, size = 20))
# 나타난 그래프를 보니 출발이 지연된 항공사는 도착도 지연된다는 것을 보여준다.
# 어쩌면 이것은 당연한 것인 것 같다.
위와 같이 데이터를 탐색해보니 어떤 회사가 운항 취소가 많은지, 어떤 회사가 출발 및 도착 지연이 많은지, 확인할 수 있었다.
이 탐색 결과를 통해서 어떤 예측 및 머신러닝을 수행할 것인지는 업계 종사자와 논의한다.