Titanic數據分析與可視化(上)
前言:跟Kaggle上大師們做的第一個項目,記錄下目前的心得體會,便於後續查閱。
泰坦尼克沉船事故已經過去多年,但是關於它的生存預測問題一直是數據分析與建模的經典案例,今天抽空把Chuck Talbert大師做的預測進行簡單翻譯和再現,並加入個人理解,原文鏈接:Titanic: A TidyCaret Approach - (0.8086)
開始數據分析與建模之前,我們一起看看Titanic數據集欄位介紹:
#PassengerId:乘客ID編號
#Survived:是否存活,0-未存活,1-存活
#Pclass:船艙號,共1,2,3類艙
#Name:乘客姓名
#Sex:乘客性別,Male,Female
#Age:乘客年齡
#SibSp:兄弟姐妹/配偶數量,0~8
#Parch:父母/子女數量,0~6
#Ticket:船票編號
#Fare:票價
#Cabin:艙位編號
#Embarked:登陸口岸,C、Q、S
原數據共12個欄位,分為train集和test集.
1、進行數據讀入工作,並簡要了解數據結構概況
setwd("E:/R/Kaggle/泰坦尼克")train <- read.csv("train.csv",stringsAsFactors = FALSE)#讀取訓練數據dim(train)#查看數據維度(行數x列數)#[1] 891 12test <- read.csv("test.csv",stringsAsFactors = FALSE)#讀取測試數據test$Survived <- NA#向test集新增欄位Survived並設置為空值titanicCombo<- rbind(train,test)#合併訓練集與測試集dim(titanicCombo)#查看數據維度(行數x列數)#[1] 1309 12str(titanicCombo)#查看合併數據結構data.frame: 1309 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 : chr "Braund, Mr. Owen Harris""Cumings, Mrs. John Bradley (Florence Briggs Thayer)""Heikkinen, Miss. Laina" "Futrelle, Mrs. Jacques Heath (Lily MayPeel)" ...$ Sex : chr "male" "female" "female""female" ...$ 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 : 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" ...
2、查看數據缺失情況
colSums(is.na(titanicCombo[1:891,]))#計算每列數據缺失個數# PassengerId Survived Pclass Name Sex Age# 0 0 0 0 0 177# SibSp Parch Ticket Fare Cabin Embarked# 0 0 0 0 687 2#計算每列數據缺失率,值保留3位小數round(colSums(100*(is.na(titanicCombo[1:891,])/nrow(titanicCombo[1:891,]))),3)# PassengerId Survived Pclass Name Sex Age# 0.000 0.000 0.000 0.000 0.000 19.865# SibSp Parch Ticket Fare Cabin Embarked# 0.000 0.000 0.000 0.000 77.104 0.224
3、數據預處理
將Survived、Pclass、Sex、Embarked 、Cabin等欄位轉為因子型,且更改Cabin值。
更改原理:如果Cabin為空,即無座乘客,將其Cabin值填充為0,否則填充1。
library(magrittr)#為了使用其中的管道行數%>%library(plyr)#為了使用mutate()函數titanicCombo <- titanicCombo %>%mutate(Survived =as.factor(Survived), Pclass = as.factor(Pclass), Sex = as.factor(Sex),Embarked = as.factor(Embarked), Cabin =as.factor(ifelse(nchar(Cabin)>0 ,1,0)))
註:mutate()函數用於對已有列進行數據運算並添加為新列與 base包的transform() 相似, 優勢在於可以在同一語句中對剛增加的列進行操作;
nchar(Cabin)>0則為有座乘客,nchar用於計算字元串長度。
4、初級可視化,數據探索
4.1觀察船艙等級(Pclass)與存活(Survived)是否有關係
library(ggplot2)g1 <- titanicCombo[1:891,] %>%ggplot() +geom_bar(aes(x = Pclass, fill =Survived))g2 <- titanicCombo[1:891,] %>%ggplot() +geom_bar(aes(x = Pclass, fill =Survived), position = "fill")library(gridExtra)#為使用grid.arrange()函數grid.arrange(g1,g2,nrow=2)
g1註:繪製柱狀圖,橫軸為船艙等級,按是否存活進行分類填充顏色;titanicCombo[1:891,] %>% 表示篩選titanicCombo數據集中前891行數據的所有列,即訓練數據集(train),通過管道函數%>%將數據傳給後續繪圖函數;gggplot默認為計數,統計各個船艙等級存活、未存活頻數。
g2註:titanicCombo[1:891,]%>% 表示篩選titanicCombo數據集中前891行數據的所有列,即訓練數據集(train),通過管道函數%>%將數據傳給後續繪圖函數;position = "fill"將每個柱狀體設置為百分制,顯示每個船艙等級下,存活、未存活比例。
其他註:grid.arrange()函數用於多個圖形排版,ncol=2表示繪製兩列圖形,即各個圖形按列分布,也可以設置nrow=2,表示圖形按行排列。
繪製圖形:
結論1:從圖形結果可以看出,1等艙存活人數最多且存活比例最高;其次為2等艙,3等艙存活比例最低,隨著艙位等級增加,存活率降低。
4.2增加性別欄位(Sex),判斷性別是否有存活優勢
library(stringr)#為使用其中str_c()函數titanicCombo[1:891,] %>%ggplot() +geom_bar(aes(x = Pclass, fill =str_c(Survived,Sex))) +scale_fill_discrete("Survived| Sex")
註:titanicCombo[1:891,]%>% 表示篩選titanicCombo數據集中前891行數據的所有列,即訓練數據集(train),通過管道函數%>%將數據傳給後續繪圖函數。
str_c() 把多個字元串拼接起來,str_c(Survived,Sex)運行結果為0female、0male、1female、1male。
0female表示沒有存活的女性人數,0male表示沒有存活的男性人數。
1female表示存活的女性人數,1male表示存活的男性人數。
fill = str_c(Survived,Sex)表示按照0female、0male、1female、1male四類進行顏色填充。
scale_fill_discrete("Survived| Sex")用於設置分類型(離散型)數據數據圖例名稱,具體為0female、0male、1female、1male,discrete意為離散的。
繪製圖形:
結論2:可以看出,各個船艙等級中,女性存活人數都比男性高。
4.3將性別(Sex)、船艙等級(Pclass)結合起來看看他們與存活率的關係
titanicCombo[1:891,] %>%ggplot() +geom_bar(aes(x = Pclass, fill =Survived), position = "fill") +facet_wrap(~Sex)
註:titanicCombo[1:891,]%>% 表示篩選titanicCombo數據集中前891行數據的所有列,即訓練數據集(train),通過管道函數%>%將數據傳給後續繪圖函數。
position ="fill"表示繪製百分比圖。
facet_wrap(~Sex)表示分面,主要用於分類型(離散型)變數,這裡按照性別分面,因為只有male、female兩種性別,因此會分成兩面,且默認為按照列分面,即兩個面之間為並列關係。如果facet_wrap(~colname)中colname有多個取值,且我們需要限定最大分面列數為3,可以設置facet_wrap(~colname,ncol=3)。後面還會用到另一個分面函數:facet_grid(),也是用於分類型(離散型)數據分面。
繪製圖形:
結論3:女性在各個船艙等級的存活率均高於男性,可見性別與存活與否有較強關係;另外女性船艙等級與存活率之間存在明顯關聯,船艙等級越高(1為高),存活率越高。男性群體中也顯示船艙等級與存活率之間存在明顯關聯,船艙等級越高(1為高),存活率越高。
4.4增加年齡(Age)欄位,判斷性別,船艙等級、年齡等3個欄位交互情況下生存率如何
titanicCombo[1:891,] %>%ggplot(aes(x = Age, y = Survived))+geom_jitter(aes(color = Sex)) +facet_wrap(~Pclass)#Warning message:#Removed 177 rows containing missing values (geom_point).#ggplot()在繪圖時,會自動將涉及欄位中存在缺失值的行刪除
註:titanicCombo[1:891,]%>% 表示篩選titanicCombo數據集中前891行數據的所有列,即訓練數據集(train),通過管道函數%>%將數據傳給後續繪圖函數。
geom_jitter()用於設置抖動點屬性,geom_jitter(aes(color= Sex)) 表示抖動點為性別,且不同性別填充不同顏色。設置抖動點可以讓原本重疊的點「探出頭」來,表示它存在。
facet_wrap(~Pclass)表示按船艙等級分面,共1~3個等級,因此分為3面,並列排列。
繪製圖形:
結論4:我們可以看出年齡小於20歲的乘客存活比例明顯高於其他年齡段乘客,且女性存活數量、存活比例均明顯高於男性,尤其是1、2等艙中,女性存活比例相當高。隨著船艙等級降低(1為最高),存活數量、存活比例均在下降。
4.5增加家庭成員數量(FamilySize)因素
繪製散點圖,展現不同船艙等級內,不同性別,擁有親屬數量與存活與否的關係
定義:家庭成員數量變數=兄弟姐妹/配偶數量+父母/子女數量
即:FamilySize=SibSp+Parch
titanicCombo[1:891,] %>%ggplot(aes(x = Age, y = Survived))+geom_jitter(aes(color =(as.factor(SibSp + Parch)), size = (as.factor(SibSp + Parch)))) +facet_grid(Pclass~Sex) +scale_color_discrete("FamilySize") +scale_size_discrete("FamilySize")
註:titanicCombo[1:891,]%>% 表示篩選titanicCombo數據集中前891行數據的所有列,即訓練數據集(train),通過管道函數%>%將數據傳給後續繪圖函數。
關於geom_jitter(aes(color= (as.factor(SibSp + Parch)), size = (as.factor(SibSp + Parch))))的注釋:
# 1)geom_jitter()用於繪製抖動點圖,盡量避免數據點重疊。
#2)SibSp + Parch用於計算家屬數量,然後as.factor(SibSp + Parch)將計算的數量值轉換為因子型。
#3)color =(as.factor(SibSp + Parch))表示按家屬數量分類填充顏色。
#4)size =(as.factor(SibSp + Parch))表示按家屬數量分類設置點的大小,家屬數量越多,數據點越大。
關於facet_grid(Pclass~Sex)的注釋:
#facet_grid()函數會嚴格按照用戶指定的方向分面。facet_grid(.x)表示橫向分面橫向分面,facet_grid(y.~)表示縱向分面,facet_grid(y~x)表示縱橫兩個維度的方向進行分面。
#scale_color_discrete("FamilySize")用於修改離散型數據(家屬數量)顏色圖例的名字為"FamilySize",默認為(as.factor(SibSp + Parch))
#scale_size_discrete("FamilySize")用於修改離散型數據(家屬數量)點大小圖例的名字為"FamilySize",默認為(as.factor(SibSp +Parch))
題外話:感興趣的朋友可以試試下面兩串代碼:
#1)不設置顏色圖例和數據點大小圖例
titanicCombo[1:891,] %>%ggplot(aes(x = Age, y = Survived))+geom_jitter(aes(color =(as.factor(SibSp + Parch)), size = (as.factor(SibSp + Parch)))) +facet_grid(Pclass~Sex)
#可以看到圖例處,名字為(as.factor(SibSp+ Parch)),顏色圖例與數據點大小圖例是合二為一的狀態,只是圖例名字美中不足,乍一看不太懂是什麼意思。
#2)設置顏色圖例名字為"FamilySize",不設置和數據點大小圖例名字
titanicCombo[1:891,] %>%ggplot(aes(x = Age, y = Survived))+geom_jitter(aes(color =(as.factor(SibSp + Parch)), size = (as.factor(SibSp + Parch)))) +facet_grid(Pclass~Sex)+scale_color_discrete("FamilySize")
#可見,圖形竟然有兩個圖例!上面的為顏色圖例,下面的為數據點大小圖例,且數據點大小圖例顏色全是黑色,並沒有與顏色進行結合,再者數據點大小圖例名稱為默認的(as.factor(SibSp + Parch)),生澀難懂。
通過以上兩組代碼對比,我們知道為什麼需要同時設置scale_color_discrete("FamilySize") +scale_size_discrete("FamilySize")了吧。
繪製圖形:
結論5:不論性別和船艙等級,家屬數量在3個及以下的乘客存活率更高;圖中還反映出一個特別的現象:第三船艙中,票價在55元以上的男性乘客存活率極低,我們可以細分該群體,看看原因。
4.6繪製家庭成員數量(FamilySize)與存活的關係圖
g1 <- titanicCombo[1:891,] %>%ggplot(aes(x = as.factor(SibSp +Parch))) +geom_bar(aes(fill =as.factor(SibSp + Parch))) +labs(x="FamilySize") +scale_fill_discrete(guide=FALSE)g2 <-titanicCombo[1:891,] %>%ggplot(aes(x = as.factor(SibSp +Parch))) +geom_bar(aes(fill =Survived),position = "fill")+labs(x="FamilySize") +scale_fill_discrete()grid.arrange(g1,g2)
g1註:圖g1為家庭成員數量與存活數量的柱狀圖。
titanicCombo[1:891,]%>% 表示篩選titanicCombo數據集中前891行數據的所有列,即訓練數據集(train),通過管道函數%>%將數據傳給後續繪圖函數。
ggplot(aes(x =as.factor(SibSp + Parch)))表示先計算家庭成員數量SibSp + Parch,然後將其因子化as.factor(SibSp +Parch),再將因子化結果賦值給x軸,關於y軸的值,ggplot默認進行計數。
geom_bar(aes(fill =as.factor(SibSp + Parch)))中geom_bar表示繪製柱狀圖,aes(fill = as.factor(SibSp +Parch))表示按照家庭成員數量進行填充顏色。
labs(x="FamilySize")中labs表示軸標籤設置,這裡只設置了x軸名字為FamilySize"
scale_fill_discrete(guide=FALSE)中scale_fill_discrete()函數用於設置離散型數據的圖例參數,guide=FALSE表示不顯示圖例。
g2註:圖g2為家庭成員數量與存活比例的百分比堆積柱狀圖。
titanicCombo[1:891,]%>% 表示篩選titanicCombo數據集中前891行數據的所有列,即訓練數據集(train),通過管道函數%>%將數據傳給後續繪圖函數。
ggplot(aes(x =as.factor(SibSp + Parch)))表示先計算家庭成員數量SibSp + Parch,然後將其因子化as.factor(SibSp +Parch),再將因子化結果賦值給x軸,關於y軸的值,ggplot默認進行計數。
geom_bar(aes(fill =Survived),position = "fill")中geom_bar表示繪製柱狀圖,aes(fill =Survived)表示按照是否存活進行分色填充,position = "fill"表示繪製百分比柱狀圖。
labs(x="FamilySize")中labs表示軸標籤設置,這裡只設置了x軸名字為FamilySize"
scale_fill_discrete()表示設置離散型數據圖例為默認選項,默認為y軸Survived數據。
繪製圖形:
結論6:通過繪製g1,得知家庭成員數量在0個的乘客存活數量最多,存活數量隨著家庭成員數量的增加在遞減。
通過繪製g2,得知家庭成員數量在3個的乘客,存活比例最高,整體而言,家庭成員數量低於3個的乘客存活比例較其他情況高。
鑒於知乎單篇文章篇幅限制,後續可視化部分將在下文更新。
推薦閱讀:
※《OurwayBI使用技巧之神奇的聯動與鑽取》精彩回顧
※在節點-鏈接圖中巧用坐標變換畫線
※菌叔:這5款可視化工具你可要收好咯~
※可視化辭典 Visual vocabulary
※全球百年地震數據可視化系統