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列に2行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)