Titanic数据分析与可视化

同步转载至个人公众号:R语言学习

同步转载至个人知乎专栏:R语言可视化进阶

泰坦尼克沉船事故已经过去多年,但是关于它的生存预测问题一直是数据分析与建模的经典案例,今天抽空把Chuck
Talbert大师做的预测进行简单翻译和再现,并加入个人理解,原文链接: [ Titanic: A TidyCaret Approach -
(0.8086)

](https://link.zhihu.com/?target=https%3A//www.kaggle.com/chucktalbert/titanic-
a-tidy-caret-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  12
    test <- read.csv("test.csv",stringsAsFactors = FALSE)#读取测试数据
    test$Survived <- NA#向test集新增字段Survived并设置为空值
    titanicCombo<- rbind(train,test)#合并训练集与测试集
    dim(titanicCombo)#查看数据维度(行数x列数)
    #[1] 1309   12
    str(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,表示图形按行排列。

绘制图形:

Titanic数据分析与可视化

结论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意为离散的。

绘制图形:

Titanic数据分析与可视化

结论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(),也是用于分类型(离散型)数据分面。

绘制图形:

Titanic数据分析与可视化

结论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)表示按船舱等级分面,共13个等级,因此分为3面,并列排列。

绘制图形:

Titanic数据分析与可视化

结论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(yx)表示纵横两个维度的方向进行分面。

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")了吧。

绘制图形:

Titanic数据分析与可视化

结论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数据。

绘制图形:

Titanic数据分析与可视化

结论6:通过绘制g1,得知家庭成员数量在0个的乘客存活数量最多,存活数量随着家庭成员数量的增加在递减。

通过绘制g2,得知家庭成员数量在3个的乘客,存活比例最高,整体而言,家庭成员数量低于3个的乘客存活比例较其他情况高。

4.7观察是否有座位(Cabin)与性别(Sex)、船舱等级(Pclass)的关系

绘制百分比堆积柱状图

    titanicCombo[1:891,] %>%
     ggplot(aes(x = Cabin)) +
     geom_bar(aes(fill = Survived),position= "fill") +
     facet_grid(Sex~Pclass)

注:titanicCombo[1:891,]%>%
表示筛选titanicCombo数据集中前891行数据的所有列,即训练数据集(train),通过管道函数%>%将数据传给后续绘图函数。

ggplot(aes(x =Cabin)) 表示横轴值为Cabin座位情况,0代表无座位乘客,1代表有座位乘客

geom_bar(aes(fill =Survived),position = "fill")中geom_bar表示绘制柱状图,设置position
="fill",表示百分比模式的柱状图,aes(fill = Survived)表示按照是否存活进行分类颜色填充。

facet_grid(SexPclass)中acet_grid为分面函数,SexPclass表示按照性别和船舱等级组合分面,性别共2个选项,船舱等级有3个选项,因此组合起来共6个情况,分为6面。

绘制图形:

Titanic数据分析与可视化

结论7:对于男性群体而言,有座位乘客存活率明显高于无座位乘客,不论船舱等级如何,均呈现该规律。

对于女性群体而言,女性存活率随着船舱等级降低(1为高,3为低),存活率也降低;在第1~2船舱等级中,无座位乘客存活率略高于有座位乘客,在第3船舱中有座位的女性乘客存活率明显高于无座女性乘客。

4.8观察船票价格(Fare)与是否存活(Survived)的关系

    titanicCombo[1:891,] %>%
     ggplot(aes(x = Fare, y =Survived)) +
     geom_jitter(aes(color =(as.factor(SibSp + Parch)), size = (as.factor(SibSp + Parch)))) +
     facet_grid(Sex~Pclass, scales ="free") +
    scale_color_discrete("FamilySize") +
    scale_size_discrete("FamilySize")

注:titanicCombo[1:891,]%>%
表示筛选titanicCombo数据集中前891行数据的所有列,即训练数据集(train),通过管道函数%>%将数据传给后续绘图函数。

ggplot(aes(x =Fare, y = Survived)) 表示横轴为票价,纵轴为是否存活。

geom_jitter(aes(color= (as.factor(SibSp + Parch)), size = (as.factor(SibSp +
Parch))))中geom_jitter表示绘制抖动点,以避免数据点重叠,aes(color = (as.factor(SibSp +
Parch))中SibSp+ Parch表示计数家庭成员数量,并用as.factor将其转换为因子型数据,最后按照家庭成员数量分类填色;size =
(as.factor(SibSp + Parch))表示按照家庭成员数量大小设置抖动点的行状大小;

scale_color_discrete("FamilySize")用于设置离散型数据颜色图例名字为FamilySize;scale_size_discrete("FamilySize")
用于设置离散型数据形状大小图例名字为FamilySize。

绘制图形:

Titanic数据分析与可视化

结论8:首先可以看到头等舱(Pclass=1)的票价明显高于2、3等船舱,不论性别差异;1、2、3等舱存活数量相差无几,但是存活比例头等舱明显更高。且3等舱中家庭成员数量在5人及以上的比例更大,大家庭乘客存活率较低。

特殊点:3等船舱中男性乘客,家庭成员数量小于1,且票价高于55元,这个群体,存活率明显高于同为3等船舱的其他男性。

鉴于4.8的结论,我们将3等船舱中男性乘客,家庭成员数量小于1,且票价高于55元的乘客信息单独调出。

    library(highr)#为了使用knitr包
    library(knitr)#为使用kable函数
    possibleGroup <- titanicCombo[1:891,] %>%subset(Pclass==3&Sex=="male"&Fare > 55&(SibSp + Parch)< 1)
    knitr::kable(possibleGroup, caption = 'Group of Interest')

| | PassengerId|Survived |Pclass|Name |Sex | Age| SibSp| Parch|Ticket |
Fare|Cabin |Embarked |

|:---|-----------

上一篇:【点宽专栏】期货多因子(二)——各因子描述


下一篇:cf Educational Codeforces Round 106 D. The Number of Pairs