データサイエンス入門 - Rを利用したタイタニックデータの予測モデル構築方法

Rを利用した基本的な予測モデル構築方法メモ

#目的
タイタニック号の乗客の属性と生存データを元に、ある乗客の属性から生存率を予測する

#使用するデータの構造
*データはこちらから入手可能(https://www.kaggle.com/c/datasciencedojo-capstone)
1.トレーニング用データ(titanic.train)
891レコード、12列。Survived列に学習用データ有
> str(titanic.train)
'data.frame':	891 obs. of  12 variables:
 $ PassengerId: int  1 2 3 4 5 6 7 8 9 10 ...
 $ Survived   : int  0 1 1 1 0 0 0 0 1 1 ...
 $ Pclass     : int  3 1 3 1 3 3 1 3 3 2 ...
 $ Name       : Factor w/ 891 levels "Abbing, Mr. Anthony",..: 109 191 358 277 16 559 520 629 417 581 ...
 $ Sex        : Factor w/ 2 levels "female","male": 2 1 1 1 2 2 2 2 1 1 ...
 $ Age        : num  22 38 26 35 35 NA 54 2 27 14 ...
 $ 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     : Factor w/ 681 levels "110152","110413",..: 524 597 670 50 473 276 86 396 345 133 ...
 $ Fare       : num  7.25 71.28 7.92 53.1 8.05 ...
 $ Cabin      : Factor w/ 148 levels "","A10","A14",..: 1 83 1 57 1 1 131 1 1 1 ...
 $ Embarked   : Factor w/ 4 levels "","C","Q","S": 4 2 4 4 4 3 4 4 4 2 ...

2.テスト用データ(titanic.test)
418レコード、11列。Survived列無し
> str(titanic.test)
'data.frame':	418 obs. of  11 variables:
 $ PassengerId: int  892 893 894 895 896 897 898 899 900 901 ...
 $ Pclass     : int  3 3 2 3 3 3 3 2 3 3 ...
 $ Name       : Factor w/ 418 levels "Abbott, Master. Eugene Joseph",..: 210 409 273 414 182 370 85 58 5 104 ...
 $ Sex        : Factor w/ 2 levels "female","male": 2 1 2 2 1 2 1 2 1 2 ...
 $ Age        : num  34.5 47 62 27 22 14 30 26 18 21 ...
 $ SibSp      : int  0 1 0 0 1 0 0 1 0 2 ...
 $ Parch      : int  0 0 0 0 1 0 0 1 0 0 ...
 $ Ticket     : Factor w/ 363 levels "110469","110489",..: 153 222 74 148 139 262 159 85 101 270 ...
 $ Fare       : num  7.83 7 9.69 8.66 12.29 ...
 $ Cabin      : Factor w/ 77 levels "","A11","A18",..: 1 1 1 1 1 1 1 1 1 1 ...
 $ Embarked   : Factor w/ 3 levels "C","Q","S": 2 3 2 3 3 3 2 3 1 3 ...

#データのインポート
ワーキングディレクトリの設定
>setwd("~/Documents/Dataset")

トレーニング用/テスト用それぞれのcsvファイルの読み込み
>titanic.train <- read.csv(file="train.csv",stringsAsFactors = FALSE, header = TRUE)

>titanic.test <- read.csv(file="test.csv",stringsAsFactors = FALSE, header = TRUE)

#トレーニングデータとテストデータの連結
トレーニングデータとテストデータを連結した後でもそれぞれを識別できるようにするため、各ファイルに識別用のIsTrainSetという列を追加
> titanic.train$IsTrainSet <- TRUE

> titanic.test$IsTrainSet <- FALSE

> tail(titanic.train$IsTrainSet)
[1] TRUE TRUE TRUE TRUE TRUE TRUE

2つのファイルのデータを連結するときは、列数と列名が完全一致している必要あるため、テストデータ側に欠けているSurvived列を追加する
> titanic.test$Survived <- NA

連結
> titanic.full <- rbind(titanic.train, titanic.test)

#欠損データの調整
Embarked列に２行missingがある
> table(titanic.full$Embarked)
      C   Q   S 
  2 270 123 914 

Embarked列の欠損行だけを抽出する
> titanic.full[titanic.full$Embarked==''", "Embarked"]　
[1] "" ""

抽出した欠損行にEmbarked列の最頻値であるSを代入
> titanic.full[titanic.full$Embarked=='', "Embarked"] <- 'S'

Embarked列の欠損行が無くなったことを確認
> table(titanic.full$Embarked)
  C   Q   S 
270 123 916 

次にAge列の欠損行を調整。Age列のnaをカウントすると、263件の欠損がある事が分かる
> table(is.na(titanic.full$Age))
FALSE  TRUE 
 1046   263 

Age列のna 行を抜いた場合のmedianを取得
> median(titanic.full$Age, na.rm=TRUE)
[1] 28


そのmedianでAge列の欠損行を埋める
> age.median <- median(titanic.full$Age, na.rm=TRUE)

> titanic.full[is.na(titanic.full$Age),"Age"] <- age.median

Age列の欠損値が無くなっている事を確認
> table(is.na(titanic.full$Age))
FALSE 
 1309 

同様にFare列の欠損値もmedianで置き換える
> table(is.na(titanic.full$Fare))
FALSE  TRUE 
 1308     1 

> fare.median <- median(titanic.full$Fare, na.rm=TRUE)

> fare.median
[1] 14.4542

> titanic.full[is.na(titanic.full$Fare),"Fare"] <- fare.median

> table(is.na(titanic.full$Fare))
FALSE 
 1309 

#データ型の調整
元のデータ型
> str(titanic.full)
'data.frame':	1309 obs. of  13 variables:
 $ PassengerId: int  1 2 3 4 5 6 7 8 9 10 ...
 $ Survived   : int  0 1 1 1 0 0 0 0 1 1 ...
 $ Pclass     : int  3 1 3 1 3 3 1 3 3 2 ...
 $ Name       : chr  "Braund, Mr. Owen Harris" "Cumings, Mrs. John Bradley (Florence Briggs Thayer)" "Heikkinen, Miss. Laina" "Futrelle, Mrs. Jacques Heath (Lily May Peel)" ...
 $ Sex        : chr  "male" "female" "female" "female" ...
 $ Age        : num  22 38 26 35 35 28 54 2 27 14 ...
 $ 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  "A/5 21171" "PC 17599" "STON/O2. 3101282" "113803" ...
 $ Fare       : num  7.25 71.28 7.92 53.1 8.05 ...
 $ Cabin      : chr  "" "C85" "" "C123" ...
 $ Embarked   : chr  "S" "C" "S" "S" ...
 $ IsTrainSet : logi  TRUE TRUE TRUE TRUE TRUE TRUE ...

カテゴリーに分類すべき列のデータ型をfactorにキャストする
> titanic.full$Pclass <- as.factor(titanic.full$Pclass)

> titanic.full$Sex <- as.factor(titanic.full$Sex)

> titanic.full$Embarked <- as.factor(titanic.full$Embarked)

結果
> str(titanic.full)
'data.frame':	1309 obs. of  13 variables:
 $ PassengerId: int  1 2 3 4 5 6 7 8 9 10 ...
 $ Survived   : int  0 1 1 1 0 0 0 0 1 1 ...
 $ Pclass     : Factor w/ 3 levels "1","2","3": 3 1 3 1 3 3 1 3 3 2 ...
 $ Name       : chr  "Braund, Mr. Owen Harris" "Cumings, Mrs. John Bradley (Florence Briggs Thayer)" "Heikkinen, Miss. Laina" "Futrelle, Mrs. Jacques Heath (Lily May Peel)" ...
 $ Sex        : Factor w/ 2 levels "female","male": 2 1 1 1 2 2 2 2 1 1 ...
 $ Age        : num  22 38 26 35 35 28 54 2 27 14 ...
 $ 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  "A/5 21171" "PC 17599" "STON/O2. 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 ...
 $ IsTrainSet : logi  TRUE TRUE TRUE TRUE TRUE TRUE ...

#データセットをトレーニング用とテスト用に分割
> titanic.train <- titanic.full[titanic.full$IsTrainSet==TRUE,]

> titanic.test <- titanic.full[titanic.full$IsTrainSet==FALSE,]

分けた後にトレーニング側のSurvivedをfactorにキャストする
> titanic.train$Survived <- as.factor(titanic.train$Survived)

#予測モデルの作成
> survived.equation <- "Survived ~ Pclass + Sex + Age + SibSp + Parch + Fare + Embarked"

> survived.formula <- as.formula(survived.equation)

ランダムフォレストパッケージのインストール
> install.packages("randomForest")

> library(randomForest)

予測モデルの作成
> titanic.model <- randomForest(formula = survived.formula, data = titanic.train, ntree = 500, mtry = 3, nodesize = 0.01 * nrow(titanic.test))

> features.equation <- "Pclass + Sex + Age + SibSp + Parch + Fare + Embarked"

#予測モデルの実行
作成した予測モデルを使用してテストデータを検証
> Survived <- predict(titanic.model,newdata=titanic.test)

結果データにはPassengerIdが必要なので追加する
> PassengerId <- titanic.test$PassengerId

> output.df <- as.data.frame(PassengerId)

予測結果を結果データのSurvived列に挿入する
> output.df$Survived <- Survived

#予測結果データファイルのエクスポート
write.csv(output.df, file="kaggle_submission.csv", row.names=FALSE)