천선생의 삶
[Kaggle] 타이타닉 생존자 예측 1부 - EDA(3) 본문
안녕하세요. 천선생입니다.
지난 포스트에서는 Sex, Age, Sibsp / Parch 변수에 대한 탐색을 다뤘는데요.
지나치셨다면 아래 링크를 통하여 확인하시길 바랍니다!
이번 포스트에서는 Ticket, Fare, Cabin, Embarked 변수에 대한 탐색을 다루도록 하겠습니다.
- Ticket : 여객권에 대한 정보
Ticket 변수는 각 승객이 소지하고 있던 여객권에 대한 정보입니다.
영어와 숫자가 함께 포함된 복합적인 값이지만, Unique한 값이 필요하기에 숫자만 남기도록 하겠습니다.
문자열 전처리 과정에서 table함수를 통하여 잘 제거되었는지 꼼꼼히 확인하도록 하겠습니다.
# sapply를 활용하여 Ticket 변수를 전처리합니다.
Ticket <- sapply(data$Ticket, function(x) {
res <- gsub('[A-z]', '', x)
res <- gsub('[.]', '', res)
res <- gsub('[/]', '', res)
res <- str_trim(res)
if (grepl(' ', res)) {
res <- unlist(strsplit(res, split = ' '))[2]
}
return(res)
})
head_tail_ticket <- c(head(table(Ticket)), tail(table(Ticket)))
t(head_tail_ticket)
# 10482 110152 110413 110465 110469 8471 8475 851 9232 9234 9549
#[1,] 4 1 3 3 2 1 1 1 3 1 1 3
#비어있는 값이 있는 것을 확인했습니다.
#변환전_변환후 의 값을 반환하도록 다시 연산합니다.
Ticket <- sapply(data$Ticket, function(x) {
res <- gsub('[A-z]', '', x)
res <- gsub('[.]', '', res)
res <- gsub('[/]', '', res)
res <- str_trim(res)
if (grepl(' ', res)) {
res <- unlist(strsplit(res, split = ' '))[2]
}
res <- paste(x, res, sep = '_') #_로 끝나는 값을 찾습니다. 이는 곧 변환이후 아무것도 없는 값입니다.
return(res)
})
# _로 끝나는 값의 정보를 불러옵니다.
Ticket[grepl('_$', Ticket)]
#[1] "LINE_" "LINE_" "LINE_" "LINE_"
# LINE이라는 티켓값이 있네요. 이를 새로운 값으로 대치하기 위해 index를 저장하겠습니다.
LINE_idx <- grep('_$', Ticket)
# index를 저장이후, 처음 연산을 반복합니다.
Ticket <- sapply(data$Ticket, function(x) {
res <- gsub('[A-z]', '', x)
res <- gsub('[.]', '', res)
res <- gsub('[/]', '', res)
res <- str_trim(res)
if (grepl(' ', res)) {
res <- unlist(strsplit(res, split = ' '))[2]
}
return(res)
})
# 저장한 index(LINE에 해당하는 위치)에 9999값을 입력하겠습니다.
Ticket[LINE_idx] <- 9999
head_tail_ticket <- c(head(table(Ticket)), tail(table(Ticket)))
t(head_tail_ticket)
# 10482 110152 110413 110465 110469 110489 8475 851 9232 9234 9549 9999
# [1,] 1 3 3 2 1 1 1 3 1 1 3 4
#전처리 완료한 Ticket 변수를 데이터프레임에 입력하겠습니다.
data$Ticket <- Ticket
# 중복되는 티켓의 수를 확인하겠습니다.
not_unique_Ticket <- table(data$Ticket)[table(data$Ticket)>1]
table(not_unique_Ticket)
# not_unique_Ticket
# 2 3 4 5 6 7 8 11
# 134 49 17 7 4 5 2 1
Feature Engineering IDEA 3.
같은 티켓번호를 갖고 있다는 것은, 가까운 사이라는 것을 의미할 것입니다.
즉 티켓번호가 단일일때, 같은 것이 2개(couple)일때, 3개 이상(Family)일때로 나누어 범주화하도록하겠습니다.
- Fare : 요금에 대한 정보
Fare 변수는 요금정보는 일정부분이지만, 개인의 특성을 반영할 수 있을 것으로 생각됩니다.
변수를 탐색해보며 활용방안을 찾아보도록 하겠습니다.
Fare변수는 금액이기 때문에 치우친 모양을 보일 것입니다. Log-Transformation을 사용하여 변환해보겠습니다.
# 분포의 확인
fare_hist <- ggplot(data = data) +
geom_histogram(aes(x = Fare), binwidth = 2)
fare_hist_log <- ggplot(data = data) +
geom_histogram(aes(x = log(Fare)), binwidth = .2)
grid.arrange(fare_hist, fare_hist_log, ncol = 2)
Log-Transformation 결과 해석
- 분포의 모양에 있어서 스펙타클한 변화는 없었지만, scale 자체를 줄일 수 있었습니다.
- 정의되지 않는 수(0이하의 수)가 발견되었습니다. 이 관측치에 대한 특징을 찾아보겠습니다.
# Fare에서 0이하의 값을 갖는 관측치의 특이점을 파악해보겠습니다.
(data_farezero <- data[which(data$Fare <= 0), ])
# PassengerId Pclass Sex Age SibSp Parch Ticket Fare Cabin Embarked Survived
# 180 180 3 male 36.00000 0 0 9999 0 S No
# 264 264 1 male 40.00000 0 0 112059 0 B94 S No
# 272 272 3 male 25.00000 0 0 9999 0 S Yes
# 278 278 2 male 31.56903 0 0 239853 0 S No
# 303 303 3 male 19.00000 0 0 9999 0 S No
# 414 414 2 male 35.79474 0 0 239853 0 S No
# 467 467 2 male 36.53352 0 0 239853 0 S No
# 482 482 2 male 32.95287 0 0 239854 0 S No
# 598 598 3 male 49.00000 0 0 9999 0 S No
# 634 634 1 male 48.78653 0 0 112052 0 S No
# 675 675 2 male 40.71845 0 0 239856 0 S No
# 733 733 2 male 40.40416 0 0 239855 0 S No
# 807 807 1 male 39.00000 0 0 112050 0 A36 S No
# 816 816 1 male 42.73671 0 0 112058 0 B102 S No
# 823 823 1 male 38.00000 0 0 19972 0 S No
# 1158 1158 1 male 33.31653 0 0 112051 0 S
# 1264 1264 1 male 49.00000 0 0 112058 0 B52 B54 B56 S
이번에는 Fare가 0인 관측값의 생존비율을 확인해보겠습니다.
data_farezero %>%
na.omit() %>% # NA가 포함된 관측치(test)를 제외합니다.
group_by(Survived) %>% # 생존여부로 묶습니다.
summarize(count = n()) %>%
ggplot() +
geom_bar(aes(x = "", y = count, fill = Survived), stat = 'identity', width = 1) +
coord_polar(theta = 'y') + # Pie 그래프를 그리겠습니다.
ggtitle("Survived people proportion in Zero-fare people") +
theme_void()
Fare의 값이 0인 사람들 중 생존자의 비율이 굉장히 적은 것을 확인할 수 있습니다.
Feature Engineering IDEA 4.
자료의 분포에 있어서 금액이라는 특성상, 굉장히 큰 값들이 존재합니다.
이 값들의 영향력을 줄이기 위하여 Log-Transformation을 진행하겠습니다.
단, 0인 값이 존재하기때문에 모든 값에 1을 더하고, 변환을 진행하겠습니다.
Feature Engineering IDEA 5.
Fare에 0값을 갖고 있는 몇개의 관측치가 발견되었습니다.
이 관측치를 따로 뽑아 종속변수와의 관계를 확인해본 결과, 생존자의 비율이 작은 것을 확인할 수 있었습니다.
따라서 이 특징을 활용한 binary 변수를 추가할 수 있을 것 같습니다.
- Cabin : 객실번호에 대한 정보
Cabin 변수는 객실에 부여된 고유 key값이라고 생각됩니다. 변수탐색 이후, 처리방안을 고려해보겠습니다.
# Cabin 변수 탐색
head_tail_cabin <- c(head(table(data$Cabin)), tail(table(data$Cabin)))
t(head_tail_cabin)
# A10 A14 A16 A19 A20 E45 E52 E60 F F E46 F E57
#[1,] 1014 1 1 1 1 1 1 1 1 1 1 1
값이 존재하지 않는 관측치가 1014개나 존재하네요. 지나치게 많이 관측하지 못한 변수는 제거하도록 하겠습니다.
Feature Engineering IDEA 6.
Cabin에 관측하지 못한 자료가 지나치게 많습니다. 변수 자체의 삭제를 고려해야 할 것 같습니다.
- Embarked : 승선지에 대한 정보
Embarked 변수는 승선지에 관한 정보를 포함한 변수입니다.
'어디에서 승선했냐?' 라는 물음은 생존여부에 과연 어떠한 영향을 주는지, 변수탐색을 통하여 확인해보도록 하겠습니다.
# Embarked 변수 탐색
str(data$Embarked)
# Factor w/ 4 levels "","C","Q","S": 4 2 4 4 4 3 4 4 4 2 ...
변수의 구조를 확인한 결과, 결측값을 발견하였습니다.
결측값을 제외한다면, 총 3개의 레벨을 갖는 범주형 변수입니다. 먼저, 결측값의 수를 확인해보겠습니다.
table(data$Embarked)
# C Q S
# 2 270 123 914
결측치는 총 2개로 큰 비중을 차지하지 않습니다.
또한 각 범주의 비율차가 존재하므로, 가장 많은 수를 차지하는 S로 대체하면 무리가 없을 것 같습니다.
시각화를 통하여 각 범주의 비율을 확인해보겠습니다.
# Embarked 변수를 문자열로 변환이후에 다시 팩터형으로 변환하겠습니다.
# 이렇게 2번 변환하는 이유는, 팩터형 변수의 레벨값을 맞춰주기 위함입니다. (4-Levels -> 3-Levels)
data$Embarked <- as.factor(as.character(data$Embarked))
# 이제, Embarked 변수의 특징을 찾기 위하여 탐색을 진행해보도록 하겠습니다.
data %>%
group_by(Embarked) %>%
summarise(count = n()) %>%
ggplot() +
geom_col(aes(x = Embarked, y = count, fill = Embarked))
Embarked 변수는 생존여부와 관련이 어느정도 있을지, chisq.test를 통해 확인해보도록 하겠습니다.
chisq.test(data$Embarked, data$Survived)
# Pearson's Chi-squared test
#
# data: data$Embarked and data$Survived
# X-squared = 25.964, df = 2, p-value = 2.301e-06
P-value가 굉장히 낮기 때문에, 두 변수는 연관성이 있음을 확인할 수 있었습니다.
이번에는 Mosaic plot의 시각화를 통한 확인을 해보겠습니다.
# Mosiac plot을 통한 두 범주형 변수의 시각화
mosaicplot(Embarked~Survived, data = data)
Mosaic plot을 통하여 확인해보았을때, 눈으로 연관성을 확인할 수 있습니다.
- 마치며
이번 포스트에서는 Ticket, Fare, Cabin, Embarked 변수에 대한 탐색을 다뤘습니다.
문자열 관련된 전처리에서 어려움을 느끼셨을 수도 있는데요.
이 부분에 대한 설명은 제 블로그에 R Basic 카테고리에 추가적인 포스트를 곧 게시하도록 하겠습니다.
드디어! 모든 변수에 대한 탐색 및 특이점을 찾아냈습니다.
그러나 변수를 탐색하는 것에는 끝이 없고, 여러분들만의 탐색법을 찾는 것 또한 매우 중요합니다!
이후 2부 시리즈에서는, 이 과정에서 찾아낸 특징점을 기반으로 Feature Engineering 을 진행하도록 하겠습니다.
EDA 진행하시느라 고생 많으셨습니다. 다음 2부 시리즈로 찾아오겠습니다!
'Kaggle > Titanic' 카테고리의 다른 글
[Kaggle] 타이타닉 생존자 예측 3부 - Modeling (3) | 2019.07.30 |
---|---|
[Kaggle] 타이타닉 생존자 예측 2부 - Feature Engineering (0) | 2019.07.26 |
[Kaggle] 타이타닉 생존자 예측 1부 - EDA(2) (0) | 2019.07.22 |
[Kaggle] 타이타닉 생존자 예측 1부 - EDA(1) (0) | 2019.07.21 |
[Kaggle] 타이타닉 생존자 예측 - 시작하기 전에 해야할 일은? (0) | 2019.07.17 |