Notice
Recent Posts
Recent Comments
Link
«   2025/01   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
Archives
Today
Total
관리 메뉴

천선생의 삶

[Kaggle] 타이타닉 생존자 예측 1부 - EDA(3) 본문

Kaggle/Titanic

[Kaggle] 타이타닉 생존자 예측 1부 - EDA(3)

천선생 2019. 7. 23. 14:00

안녕하세요. 천선생입니다.

 

 지난 포스트에서는 Sex, Age, Sibsp / Parch 변수에 대한 탐색을 다뤘는데요.

지나치셨다면 아래 링크를 통하여 확인하시길 바랍니다!

https://cheon9.tistory.com/21

 

[Titanic] 타이타닉 분석하기 1부 - EDA(2)

안녕하세요. 천선생입니다. 지난 포스트에서는 Survived, PassengerId, Pclass, Name 변수에 대한 탐색을 다뤘는데요. 지나셨다면 링크를 통하여 확인하시길 바랍니다! https://cheon9.tistory.com/20 [Titanic]..

cheon9.tistory.com

이번 포스트에서는 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인 관측치의 생존비율을 나타낸 원그래프

 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 변수의 범주별 비율 시각화

 


 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)

Embarked 변수와 종속변수의 Mosaic plot

 Mosaic plot을 통하여 확인해보았을때, 눈으로 연관성을 확인할 수 있습니다.

 

- 마치며

 이번 포스트에서는 Ticket, Fare, Cabin, Embarked 변수에 대한 탐색을 다뤘습니다.

문자열 관련된 전처리에서 어려움을 느끼셨을 수도 있는데요.

이 부분에 대한 설명은 제 블로그에 R Basic 카테고리에 추가적인 포스트를 곧 게시하도록 하겠습니다.

 

 드디어! 모든 변수에 대한 탐색 및 특이점을 찾아냈습니다.

그러나 변수를 탐색하는 것에는 끝이 없고, 여러분들만의 탐색법을 찾는 것 또한 매우 중요합니다!

그러나 이 시리즈는 입문자를 위한 분석과정이므로 더이상은...

 

 이후 2부 시리즈에서는, 이 과정에서 찾아낸 특징점을 기반으로 Feature Engineering 을 진행하도록 하겠습니다.

EDA 진행하시느라 고생 많으셨습니다. 다음 2부 시리즈로 찾아오겠습니다!

Comments