泰坦尼克號生存預測——kaggle排名403

選取了來自kaggle的數據集Titanic: Machine Learning from Disaster,利用隨機森林建立模型,預測測試集的乘客在沉船事件中的生存情況。

整個數據分析的過程是:

1.導入數據

2.理解數據

3.數據預處理

4.數據計算&顯示

5.數據建模

6.保存結果

一、導入數據

train <- read.csv(F:/titanic/train.csv,stringsAsFactors = T)ntest <- read.csv(F:/titanic/test.csv,stringsAsFactors = T)nlibrary(dplyr)nfull <- bind_rows(train,test)nView(full)n

查看數據:

二、理解數據

Survived:生存情況,1為存活,0為死亡

Pclass:客艙等級,1為高級,2為中級,3為低級

Name:乘客名字

Sex:乘客性別

Age:乘客年齡

SibSp:在船兄弟姐妹數/配偶數

Parch:在船父母數/子女數

Ticket:船票編號

Fare:船票價格

Cabin:客艙號

Embarked:登船港口

這次的分析目的主要是根據訓練集預測測試集的乘客生存情況,也就是補充test集中缺失的Survived數據。

三、數據預處理

3.1查看是否有缺失值

##查找缺失值nsapply(full,function(x) sum(is.na(x))) 查找數據的NA值nsapply(full,function(x) sum(x==)) 查找數據中的空白值n

結果顯示,survived有418個缺失值,age有263個缺失值,fare有1個缺失值,而Cabin有1024個空白值,Embarked有2個空白值。

其中Survived的缺失值是由於數據的合併造成的,這418個數據是需要我們對測試集做出預測。在這裡我們需要補充Age、Fare和Embarked的缺失值。

3.2補充缺失值

3.2.1補充Embarked數據

先利用下面代碼找出空白值所在位置:

第62和第830位乘客的登船港口數據是空白值。接著提取這兩個乘客的信息,看是否有分析思路:

從上面信息可以知道62號乘客和830號乘客的票價Fare都是80,且Pclass皆是1,那麼是不是可以假設相同票價的乘客是在同一個登船港口登船的呢?

從圖中可以Pclass為1、票價中位數為80的登船港口是「C」,因此我們定義Embarked空白值為「C"。

full$Embarked[c(62,830)] <- Cn

再次查看Embarked是否還有空白值:

到這裡,Embarked的空白值已經補全完整。

3.2.2補充Fare數據

先查找缺失值的位置:

再提取第1044位乘客的信息:

可以看出該乘客是在S登船港口上船,且Pclass為3,由於前面我們補充登船港口的空白值的時候就是利用Fare和Pclass來分析的,因此票價這裡我們可以從相同的思路考慮,提取都是從S登船港口上船且Pclass為3的乘客信息,然後繪圖看是否可以用中位數補充缺失數據。

圖中信息表明相同登船港口和客艙等級的票價大部分分布在0~20中,因此我們可以用中位數補充缺失值。

###對票價缺失的1044乘客補全票價nfull$Fare[1044] <- median(full.fare$Fare,na.rm = T)n

3.2.2補充Age數據

使用MICE預測填補Age的缺失數據:

####設置隨機種子nset.seed(129)n####執行多重插補法,刪除一些沒什麼用的變數nlibrary(mice)nA <- c(PassengerId,Name,Ticket,Cabin,family,Surname,Survived)nmice_mod <- mice(full[,!names(full) %in% A],method = rf)n#####保存完整輸出nmice_output <- complete(mice_mod)n

接著查看使用MICE預測補充的數據跟原來數據趨勢是否有區別:

###繪製年齡分布圖npar(mfrow=c(1,2))nhist(full$Age,freq = F,main = Age:ORiginal Data,col=darkblue,ylim = c(0,0.04))nhist(mice_output$Age,freq = F,main = Age:MICE Output,col = skyblue,ylim = c(0,0.04))n

用MICE預測後填補的數據跟原來的數據趨勢變化不大,也就是說可以用預測後的數據填充Age中的缺失值:

###使用MEIC模型結果替換年齡變數nfull$Age <- mice_output$Agen

最後查看Age和Fare是否還有缺失值:

至此,缺失數據已經補充完整了。

四、數據計算&顯示

這部分主要是從以下幾點分析數據:

1.頭銜對生存率的影響?

2.家庭人數對生存率的影響?

3.性別對生存率的影響?母親身份對生存率的影響?

4.年齡對生存率的影響?兒童身份對生存率的影響?

5.票價對生存率的影響?

4.1分析頭銜對生存率的影響

從列名『Name』中提取中間關於頭銜的欄位,例如『Miss』、『Mrs』等。

###提取頭銜nlibrary(stringr)nfull$Title <- gsub((.*, )|(..*),,full$Name)n

查看頭銜的類別數量:

table(full$Sex,full$Title)n

###將數量較少的頭銜歸類nrare_title <- c(Capt,Col,Don,Dona,Dr,Jonkheer,Lady,Major,Rev,Sir,the Countess)n###重新定義一些稱呼nfull$Title[full$Title==Mlle] <- Missnfull$Title[full$Title==Mme] <- Mrsnfull$Title[full$Title==Ms] <- Missnfull$Title[full$Title %in% rare_title] <- Rare titlen###再次查看頭銜和性別的關係ntable(full$Sex,full$Title)n

對性別、頭銜和生存率的影響情況用ggplot繪製圖分析:

###繪製sex、title和survived的關係圖nlibrary(ggplot2)nggplot(full[1:891,],aes(Title,fill=factor(Survived)))+geom_bar()+facet_grid(.~Sex)+theme_few()+ggtitle(The Survival by Title and Sex)n

從圖中可以得出,頭銜為Miss和Mrs的生存率佔比比較大,而頭銜為Mr的生存率佔比較小。這裡反面驗證了性別對生存率存在一定的影響,為了驗證這點,下面進行性別對生存率的影響分析。

PS:當我採用以下的代碼進行頭銜數據提取時,卻無法對頭銜進行重新編碼歸位,目前還沒有找到答案。

Title <- strsplit(full$Name,split = [,.])nfull$Title <- sapply(Title,[,2)n

4.2分析性別對生存率影響

用馬賽克圖分析性別對生存率的影響:

###性別對存活率的影響nmosaicplot(table(full$Sex,full$Survived),main = Survival By Sex,shade = T)n

圖中顯示,女性存活的佔比更高一點,男性存活的佔比較低。也就是說,當危險發生的時候,女性存活的機會更大一些。那麼如果是一個母親,結果又會是怎樣呢?

需要在數據中新增一個母親的數據,其中滿足母親的要求是:女性,年齡大於18歲,至少有1個小孩:

####生成母親的變數nfull$mother <- Not mothernfull$mother[full$Sex==female&full$Age>18&full$Parch>0&full$Title!=Miss] <- mothern

繪圖查看母親與生存率之間的關係:

####繪製馬賽克圖觀察母親和生存情況的關係圖nmosaicplot(table(full$mother,full$Survived),main = The Survival by Mother,color = c(skyblue,pink))n

在這次的數據中母親的佔比不高,但是生存率卻比非母親的生存率高,說明當一名女性為母親時,會增加她的生存概率。

4.3分析家庭人數對生存率的影響

由於數據中有提到船上兄弟姐妹和父母配偶數,所以,考慮家庭人口對存活率是否有影響呢?

首先,新生成一列家庭人口數的數據:

####家庭人數nfull$familysize <- full$SibSp+full$Parch+1n

接著,提取乘客的姓氏,再生成一個家庭變數,以「姓_家庭人口」的形式存儲數據:

###提取乘客姓氏nfull$Surname <- sapply(strsplit(full$Name,split = [,.]),[,1)n###生成一個家庭變數nfull$family <- paste(full$Surname,full$familysize,sep = _)n

最後,使用ggplot2繪製分析家庭人數與生存情況的關係:

ggplot(full[1:891,],aes(x=familysize,fill=factor(Survived)))+geom_bar(stat = count,position=dodge)+scale_x_continuous(breaks = c(1:11))+labs(x=Family size)+theme_bw()+ggtitle("Family size VS Survived")n

圖中顯示,家庭人口為1和家庭人口大於4人的比較容易死亡,而家庭人口在2至4人中的生存率較高。根據這個發現,我們可以將家庭人口進行分類,分成單身、小家庭和大家庭:

###將上述結果進行合併nfull$Fsize[full$familysize==1] <- singletonnfull$Fsize[full$familysize>1&full$familysize<5] <- small familynfull$Fsize[full$familysize>=5] <- big familyn

同樣畫圖進行分析,看結果是否與上述的情況一致:

###通過繪製馬賽克圖查看家庭規模和生存情況的關係nmosaicplot(table(full$Fsize,full$Survived),main = Family Size by Survival,shade = T)n

同樣是小家庭的生存率較高,因此當初船上的家庭人口數量對生存率有一定的影響。

4.4分析年齡對生存率的影響

根據性別來劃分年齡,繪製圖分析年齡對生存率的影響:

###分析性別和年齡與生存情況的關係nggplot(full[1:891,],aes(Age,fill=factor(Survived)))+geom_histogram()+facet_grid(.~Sex)+theme_few()+ggtitle(The Survival by Age and Sex)n

其中代碼「facet_grid(.~Sex)」即是按年齡劃分的意思。

從圖中可以得出,無論是哪個年齡階段仍然是女性的生存率較高,但是,我們同時也注意到0至20歲這部分,無論是女性還是男性生存率都比較高,那麼是不是可以考慮一下年齡在20歲以下的對生存率的影響呢?參考了其他的案例,決定以18歲作為一個分界點,也就是考慮兒童與成人對生存率的影響。

首先生成一個新數據,劃分「兒童」與「成年人」:

###將年齡層進行劃分成兒童和成人,再觀察和生存情況的關係nfull$child[full$Age < 18] <- childnfull$child[full$Age >= 18] <- adultntable(full$child,full$Survived)n

繪製馬賽克圖分析結果:

####繪製馬賽克圖觀察兒童和生存情況的關係圖nmosaicplot(table(full$child,full$Survived),main = The Survival by Age,shade = T)n

child的生存率比成人的更高,那是不是說明了小女孩的存活率會更高呢?

4.5分析票價對生存率的影響

最後一個是分析票價對生存率是否有影響的分析。為了便於分析,對票價進行了歸類:

##分析票價Fare與生存率的關係nfull$Fare1 <- lownfull$Fare1[full$Fare>=100 & full$Fare <300] <- middlenfull$Fare1[full$Fare>=300] <- hightn

同樣繪製馬賽克圖進行分析:

結果顯示高等票和中等票的生存率更高一些,而低等票的生存率最低。為了更直觀的表示結果,我們可以看看計算出來的數據:

###自定義函數,查看各數據生存率的佔比nrate_survived <- function(n){n full_rate <- xtabs(~n+Survived,data = full)n rate <- prop.table(full_rate,1)n return(rate)n}nrate_survived(full$Fare1)n

計算結果跟圖示的一樣,高等票和中等票的生存率更高一些,特別是高等票的存活率達到了百分百。

到了這裡,數據分析已經結束了,我們知道了頭銜、性別、母親、年齡、小孩、票價等都對生存率有著一定的影響。究竟哪個影響更大,目前尚不知道。

五、數據建模

這部分主要是進行建立模型、因子重要性分析以及測試集數據的預測。

5.1建立模型

模型因子的選擇:在數據分析部分,我們已經知道了頭銜、性別、母親、年齡、小孩、票價以及家庭人口數量等都對生存率有著一定的影響,其中性別和母親屬於重複項,所以只考慮性別這一項,年齡中主要是小孩的因素起決定作用,所以這部分的結果我們主要選擇了頭銜、性別、小孩、票價以及家庭人口數量的影響,而客艙等級和登船港口在某方面決定了我們在船上的位置,所以這兩個也選擇了考慮因子的範圍內。

###拆分訓練集和測試集ntrain <- full[1:891,]ntest <- full[892:1309,]n####模型nlibrary(randomForest)n###設置隨機種子nset.seed(754)n###建立模型nrf_mode <- randomForest(factor(Survived)~Pclass+Fare+Embarked+Title++Sex+Fsize+child,data = train)n###顯示模型誤差nplot(rf_mode,ylim = c(0,0.36))nlegend(topright,colnames(rf_mode$err.rate),col=1:3,fill=1:3)n

顯示模型誤差的這張圖中,我們可以得知死亡的誤差率在0.1左右,而生存的誤差率是0.3左右,也就是說,更容易判斷這個乘客是否死亡。

5.2分析因子重要係數

對因子的重要係數進行分析:

###獲取重要係數nimportance <- importance(rf_mode)nvarImportance <- data.frame(variables=row.names(importance),Importance=round(importance[,MeanDecreaseGini],2))n###對於變數根據重要係數進行排列nlibrary(dplyr)nrankImportance <- varImportance %>% mutate(Ranke= paste0(#,dense_rank(desc(Importance))))n###使用ggplot繪製重要變數相關係圖nggplot(rankImportance,aes(x=reorder(variables,Importance),y=Importance,fill=Importance))+n geom_bar(stat=identity)+n geom_text(aes(x=variables,y=0.5,label=Ranke),hjust=0,vjust=0.55,size=4,colour=red)+n labs(x=Variables)+n coord_flip()+theme_few()+ggtitle(The Importance of Variables)n

結果顯示,佔比前三重要的因子是頭銜、性別、票價。

最後是對測試集進行預測:

###基於測試集進行預測nprediction <- predict(rf_mode,test)n####將結果保存為數據框nsolution <- data.frame(PassengerId=test$PassengerId,Survived=prediction)n

六、保存結果

最後對結果進行保存:

###保存結果nwrite.csv(solution,file=solution,row.names=F)n

總結:這次的結果參考了知乎上的其他小夥伴關於Titanic的分析案例,在學習其他的案例的同時,一邊思考為什麼這麼做,一邊思考這些代碼是代表什麼意思,總共花了一星期才把代碼敲好,上傳到kaggle看排名的時候,一開始1236名,後面進行了模型因子的篩選後,排名為403。


推薦閱讀:

乾貨 | 這是一份你急需的數據分析的職業規劃
你值5K還是15K?實戰案例,測測你的分析功力
七周成為數據分析師:看完後,別再說自己不懂用戶畫像了
花6000賺48,數據分析師的另一面
結構思維——用結構化思考讓數據分析到達問題的底層

TAG:数据分析 | 大数据分析 | 数据分析师 |