[R 프로그램] Kaggle 타이타닉 생존자 예측(5) - Feature Engineering
이번 실습은 Feature Engineering 단계이다. Feature Engineering단계에서 모형의 성능을 향상시킬 수 있는 다양한 변수 처리를 할 수 있는데, EDA단계에서 탐색한 결과를 잘 반영하여 적용하면 모델 구현에 큰 도움이 된다.
EDA를 통해 도출한 Feature Engineering IDEA 정리
Feature Engineering IDEA 1. Age
특정 나이대, 즉 영유아의 생존률이 상대적으로 굉장히 높음 → 영유아 여부에 따른 binomial variable 생성
Feature Engineering IDEA 2. SibSp & Parch
동승객에 대한 정보는 동승그룹에 대한 정보로 치환이 가능 → 즉, SibSp + Parch + 1(본인) = 동승그룹의 인원수로 변환 가능
Feature Engineering IDEA 3. Ticket
같은 티켓번호를 갖고 있다는 것은, 가까운 사이라는 것을 의미 → 티켓번호가 단일일때, 같은 것이 2개(couple)일때, 3개 이상(Family)일때로 나누어 범주화
Feature Engineering IDEA 4. Fare
자료의 분포에 있어서 금액이라는 특성상, 굉장히 큰 값들이 존재 → 이 값들의 영향력을 줄이기 위하여 log변환 진행. (*단, 0인 값이 존재하기때문에 모든 값에 1을 더하고, 변환 진행)
Feature Engineering IDEA 5. Fare
Fare에 0값을 갖고 있는 몇개의 관측치가 존재.
이 관측치를 따로 뽑아 종속변수와의 관계를 확인해본 결과, 생존자의 비율이 작음 → 이 특징을 활용한 binary 변수 추가 고려
Feature Engineering IDEA 6. Cabin
관측하지 못한 자료가 지나치게 많아 변수 자체의 삭제 고려
전처리 완료된 변수상태 확인
#전처리 후 변수 확인
> str(data)
'data.frame': 1309 obs. of 11 variables:
$ PassengerId: int 1 2 3 4 5 6 7 8 9 10 ...
$ Survived : Factor w/ 2 levels "No","Yes": 1 2 2 2 1 1 1 1 2 2 ...
$ Pclass : Factor w/ 3 levels "1","2","3": 3 1 3 1 3 3 1 3 3 2 ...
$ Sex : chr "male" "female" "female" "female" ...
$ Age : num 22 38 26 35 35 ...
$ SibSp : int 1 1 0 1 0 0 0 3 0 1 ...
$ Parch : int 0 0 0 0 0 0 0 1 2 0 ...
$ Ticket : chr "21171" "17599" "3101282" "113803" ...
$ Fare : num 7.25 71.28 7.92 53.1 8.05 ...
$ Cabin : chr "" "C85" "" "C123" ...
$ Embarked : Factor w/ 3 levels "C","Q","S": 3 1 3 3 3 2 3 3 3 1 ...
IDEA1. 영유아 변수 만들기
#Baby 변수 생성
data$Baby <- as.factor(ifelse((data$Age<=5), 1, 0))
5세 이하의 그룹을 영유아로 판단하여 Baby 변수를 생성하였다.
IDEA2. 구성원 수 변수 만들기
> # Group_size 변수 생성
> data$Group_size <- data$SibSp + data$Parch + 1
>
> # sapply 활용한 각 변수 변환
> data$Group_size <- sapply(data$Group_size, function(x) {
+ if (x == 1) {
+ res <- 'Single'
+ } else if(x < 5) {
+ res <- 'Small'
+ } else {
+ res <- 'Large'
+ }
+ return(res)
+ })
>
> #level 지정한 팩터변수 생성
> data$Group_size <- factor(data$Group_size, levels = c('Single', 'Small', 'Large'))
>
> table(data$Group_size)
Single Small Large
790 437 82
SibSp + Parch + 1 = Group_size 인 새로운 변수 Group_size를 생성한 후.
Single, Small, Large로 Level을 지정하였다.
IDEA3. 동일한 티켓번호 범주화
#Ticket-T_group 변수 생성
table(not_unique_Ticket)
not_unique_Ticket
2 3 4 5 6 7 8 11
134 49 17 7 4 5 2 1
couple_T <- names(not_unique_Ticket)[not_unique_Ticket == 2]
# couple_T : 동일한 이름이 2개인 티켓의 이름(Ticket 값)
Family_T <- names(not_unique_Ticket)[not_unique_Ticket >= 3]
# Family_T : 동일한 이름이 3개 이상 티켓의 이름(Ticket 값)
# T_Group이라는 변수에서 조건에 해당하는 row에 각 값을 입력
data$T_Group[data$Ticket %in% couple_T] <- 'Couple_T'
data$T_Group[data$Ticket %in% Family_T] <- 'Family_T'
data$T_Group[is.na(data$T_Group)] <- 'Single_T'
# T_Group 변수를 팩터로 변환합니다.
data$T_Group <- factor(data$T_Group, levels = c('Single_T', 'Couple_T', 'Family_T'))
table(data$T_Group, useNA = 'always')
Single_T Couple_T Family_T <NA>
705 268 336 0
# Ticket 변수 삭제
data$Ticket <- NULL
Ticket번호가 단일할 때,(Single) 같은 것이 2개일 때(Couple), 3개 이상일 때(Family)로 나누어 범주화하였다.
IDEA4. 요금변수 로그 변환
#Fare변수 로그 변환
data$Fare <- log(data$Fare+1)
ggplot(data=data)+
geom_histogram(aes(x=Fare), binwidth=0.3)
요금변수인 Fare은 연속형변수이므로 한 쪽으로 치우친 분포를 보였다. 로그 변환을 통해 분포를 고르게 바꾸어 주었다.
하지만 남은 문제는 이상치 0값이 존재한다는 것.
IDEA5. 요금변수 로그 변환 파생 - 0값 관측치 분할
#Crew변수 만들기
data$Crew[(data$Fare==0)] <- 1
data$Crew[is.na(data$Crew)] <- 0
data$Crew <- as.factor(data$Crew)
table(data$Crew, useNA='always')
#0 1 <NA>
#1292 17 0
요금변수에서 0값을 갖는 관측치는 무임승차자 혹은 승무원의 값일 수 있다.
이를 구분하여 주기 위해 승무원 변수 Crew를 생성한 후, 결측값을 0으로, 0값을 갖는 관측치는 1값을 지정하였다.
IDEA6. Cabin 변수 삭제
#Cabin 변수 처리
data$Cabin <- NULL
EDA를 통해 확인해 본 결과, Cabin변수는 결측값이 너무 많아 분석에 활용하기 어려운 변수로 판단되어 삭제해주었다.