• 数据来源: kaggle
  • 分析工具:Python 3.6 & jupyter notebook
  • 附上数据:链接: https://pan.baidu.com/s/1D7JNvHmqTIw0OoPXBWzWHA 提取码: hdtt
  • 本篇分析比较基础,集中于清洗和可视化,后续可能会慢慢修改,如果我能想起来的话,欢迎各路大神指正
#设置jupyter可以打印多条结果
from IPython.core.interactiveshell import InteractiveShell
InteractiveShell.ast_node_interactivity = \"all\"

#导入包
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

#导入数据
df=pd.read_csv(\'titanic_data.csv\')
df.head()

# passengerId:旅客 id;survived:0 代表遇难,1 代表存活;pclass:舱位,1-3 分别代表一二三等舱;
# name:旅客姓名;sex:旅客性别;age:年龄;
# sibsp:船上的同代亲属人数,如兄弟姐妹;parch:船上的非同代亲属人数,如父母子女;
# ticket:船票编号;fare:船票价格;cabin:客舱号;embarked:登船港口

猜测生存率跟以下因素有关

1.pclass:客舱等级,一等舱可能有大部分权贵
2.sex:性别,lady first
3.age:年龄,尊老爱幼,通用的道德规范
4.sibsp:同代亲属,可能亲属多的获救概率更大
5.parch:非同代亲属,可能会让父母子女先得救
6.fare:船票价格,反应经济能力和社会地位,跟客舱等级存在关联

# 数据量以及大小,缺失值
df.info()
df.shape

  • 结论:数据总量 891 条,12 列,age 列缺失 177 条数据,因为尊老爱幼也是一个通用的道德规范,因此考虑 age 对生存率会有影响,后续可能需要填充; cabin 舱号对生存考虑无影响,缺失影响不大
# 数据汇总统计
df.describe()

# 整体生存情况
survived=df[\'Survived\'].value_counts()
survived

# 可以看到,891 人中,只有342人存活
# 计算生存比例
survived_perc=survived / survived.sum()
survived_perc

# 绘制饼图
plt.rc(\'font\',family=\'Arial Unicode MS\',size=15)    #设置字体
fig=plt.figure(1,figsize=(7,7))      #设置画布
ax1=fig.add_subplot(1,1,1)       #生成子图
label=[\'遇难\',\'存活\']
color=[\'#C0C0C0\',\'#F5DEB3\']
explode=0.05,0.05      #扇区间隔
ax1.pie(survived_perc,labels=label,colors=color,startangle=90,autopct=\'%3.2f%%\',explode=explode,shadow=True)
ax1.set_ (\'整体生存情况\') 

# 性别与生存情况
sex=df.groupby([\'Survived\',\'Sex\']).size()
sex

# 转换为 data 
sex=sex.unstack(\'Sex\')
sex=sex.rename(index={0:\'遇难\',1:\'存活\'})
sex

# 计算生存比例
sex_perc=sex / sex.sum()
sex_perc

  • 从结果看,女性遇难 81 人,存活率约 75%,男性存活 109人,存活率不到 20%
# 绘制条形堆叠图
plt.rc(\'font\',family=\'Arial Unicode MS\',size=15)    #设置字体
fig=plt.figure(1,figsize=(7,7))      #设置画布
ax1=fig.add_subplot(1,1,1)       #生成子图
x=range(2)
a=sex_perc.loc[\'遇难\',:]
b=sex_perc.loc[\'存活\',:]
ax1.bar(x,a,label=\'遇难\',color=\'#C0C0C0\')
ax1.bar(x,b,bottom=a,label=\'存活\',color=\'#F5DEB3\')   #通过bottom参数绘制堆积柱状图
ax1.set_xticks(range(3))       #设置x轴刻度,之所以设置为3,是为了让图例显示在空白处
ax1.set_xticklabels([\'女性\',\'男性\'])         #设置x轴刻度标签名称
ax1.set_yticks([])
ax1.legend([\'遇难\',\'存活\'],loc=\'center right\')     #设置图例名称及位置
ax1.set_ (\'性别生存分布\')    #设置标题
#添加数据标签
for x,y,z in zip(range(2),a,b):
    ax1.text(x,y/2,\'{:.2%}\'.format(y))
    ax1.text(x,y+z/2,\'{:.2%}\'.format(z))

# 年龄分布
age_df=df.loc[:,[\'Survived\',\'Age\']] 
age_df.head() 

#对年龄分组,从前面的描述性统计可以看到,年龄的最小值是0.42岁,最大值是80岁
bins=[0,20,40,60,100] 
labels=[\'20岁及以下\',\'21-40岁\',\'41-60岁\',\'60岁以上\']
age_df[\'levels\']=pd.cut(age_df[\'Age\'],bins=bins,labels=labels)
age_df.head() 

# 遇难/存活人员的年龄分布
age_level=age_df.groupby([\'Survived\',\'levels\']).size()
age_level 

# 可以看到在遇难和存活的人中,都是21-40岁的人巨多
# 转为 data 
age_level=age_level.unstack() 
age_level=age_level.rename(index={0:\'遇难\',1:\'存活\'})
age_level 

# 计算比例
age_perc=age_level/age_level.sum() 
age_perc

  • 可以看到随着年龄的增加,存活比例逐渐降低,在天灾面前,大家还是会把生的希望更多的让给年轻人
plt.rc(\'font\',family=\'Arial Unicode MS\',size=15)    #设置字体
fig=plt.figure(1,figsize=(11,7))      #设置画布
ax1=fig.add_subplot(1,1,1)        #添加子图
x=range(4)
a=age_perc.loc[\'遇难\',:]
b=age_perc.loc[\'存活\',:]
ax1.bar(x,a,label=\'遇难\',width=0.5,color=\'#C0C0C0\')
ax1.bar(x,b,bottom=a,label=\'存活\',width=0.5,color=\'#F5DEB3\') 
ax1.set_xticks(range(5))     # x轴刻度
ax1.set_xticklabels([\'20岁及以下\',\'21-40岁\',\'41-60岁\',\'60岁以上\'])
ax1.set_yticks([]) 
ax1.legend([\'遇难\',\'存活\'],loc=\'upper right\')
ax1.set_ (\'存活年龄分布\')
for x,y,z in zip(range(4),a,b):
    ax1.text(x-0.1,y/2,\'{:,.1%}\'.format(y))
    ax1.text(x-0.1,y+z/2,\'{:,.1%}\'.format(z))

# 家庭人数分布
df[\'familysize\']=df[\'SibSp\']+df[\'Parch\']+1 
family_df=df.loc[:,[\'Survived\',\'familysize\']] 
family_df.head() 

# 按人数分箱
bins=[0,1,3,12]
labels=[\'small\',\'medium\',\'large\'] 
family_df[\'family_level\']=pd.cut(family_df[\'familysize\'],bins=bins,labels=labels)      #左开右闭
family_df.head() 

family_df=family_df.groupby([\'Survived\',\'family_level\']).size() 
family_df

family_df=family_df.unstack() 
family_df=family_df.rename(index={0:\'遇难\',1:\'存活\'}) 
family_df

family_perc=family_df/family_df.sum() 
family_perc

plt.rc(\'font\',family=\'Arial Unicode MS\',size=15) 
fig=plt.figure(figsize=(8,5))  
ax1=fig.add_subplot(1,1,1)
y=range(3) 
a=family_perc.loc[\'遇难\',:] 
b=family_perc.loc[\'存活\',:] 
ax1.barh(y,a,label=\'遇难\',height=0.5,color=\'#C0C0C0\') 
ax1.barh(y,b,left=a,label=\'存活\',height=0.5,color=\'#F5DEB3\')
ax1.set_yticks(range(4)) 
ax1.set_yticklabels([\'small\',\'medium\',\'large\'])
ax1.set_xticks([]) 
ax1.legend([\'遇难\',\'存活\'],loc=\'upper right\')
ax1.set_ (\'不同家庭规模存活分布\')
for x,y,z in zip(range(4),a,b):
    ax1.text(y/2,x,\'{:.1%}\'.format(y))
    ax1.text(y+z/2,x,\'{:.1%}\'.format(x)) 

  • 可以看到,船上亲属只有一个人,无其他亲属时,存活率最高,将近 70%
# 舱位等级分布
pclass_df=df.loc[:,[\'Survived\',\'Pclass\']]
pclass_df.head() 

pclass_df=pclass_df.groupby([\'Survived\',\'Pclass\']).size() 
pclass_df

pclass_df=pclass_df.unstack() 
pclass_df=pclass_df.rename({0:\'遇难\',1:\'存活\'},columns={1:\'一等舱\',2:\'二等舱\',3:\'三等舱\'})
pclass_df

pclass_perc=pclass_df/pclass_df.sum() 
pclass_perc

plt.rc(\'font\',family=\'Arial Unicode MS\',size=15) 
fig=plt.figure(figsize=(8,5)) 
ax1=fig.add_subplot(1,1,1) 
y=range(3) 
a=pclass_perc.loc[\'遇难\',:] 
b=pclass_perc.loc[\'存活\',:] 
ax1.barh(y,a,label=\'遇难\',height=0.5,color=\'#C0C0C0\')
ax1.barh(y,b,left=a,label=\'存活\',height=0.5,color=\'#F5DEB3\')
ax1.set_yticks(range(4)) 
ax1.set_yticklabels([\'一等舱\',\'二等舱\',\'三等舱\'])
ax1.set_xticks([]) 
ax1.legend([\'遇难\',\'存活\'],loc=\'upper right\')     
ax1.set_ (\'不同舱位等级存活分布\')
for x,y,z in zip(range(4),a,b):
    ax1.text(y/2,x,\'{:.1%}\'.format(y))
    ax1.text(y+z/2,x,\'{:.1%}\'.format(z)) 

  • 可以看到,舱位等级与存活率还是有很显著的关系,一等舱存活率63%,远大于三等舱存活率
# 船票价格存活分布,预计与舱位等级结果相似,不过注意到描述性统计里,价格最大为 512,最小为 0,存在很明显的异常值,还是做一下异常值处理
# 提取价格不为 0 的记录
fare_df=df.loc[df[\'Fare\']>0,[\'Survived\',\'Fare\']]
fare_df.head() 

# 平均票价
fare_df.groupby(\'Survived\')[\'Fare\'].mean() 

# 票价分箱
bins=[0,10,30,50,100,513] 
labels=[\'≤10\',\'10-30\',\'30-50\',\'50-100\',\'100以上\'] 
fare_df[\'level\']=pd.cut(fare_df[\'Fare\'],bins=bins,labels=labels)
fare_df.head() 

# 存活与否与票价分组
fare_df=fare_df.groupby([\'Survived\',\'level\']).size()
fare_df

# 转 data 
fare_df=fare_df.unstack()
fare_df=fare_df.rename(index={0:\'遇难\',1:\'存活\'})
fare_df

# 计算比例
fare_perc=fare_df/fare_df.sum()
fare_perc

plt.rc(\'font\',family=\'Arial Unicode MS\',size=15)
fig=plt.figure(figsize=(11,8))    #画布大小
ax1=fig.add_subplot(1,1,1)     #添加子图
y=range(5)
a=fare_perc.loc[\'遇难\',:]
b=fare_perc.loc[\'存活\',:]
ax1.barh(y,a,label=\'遇难\',height=0.5,color=\'#C0C0C0\')
ax1.barh(y,b,left=a,label=\'存活\',height=0.5,color=\'#F5DEB3\')          #left:柱状堆积图
ax1.set_yticks(range(6))
ax1.set_yticklabels([\'≤10\',\'10-30\',\'30-50\',\'50-100\',\'100以上\'])          #y轴刻度标签
ax1.set_xticks([])                #x轴刻度为空
ax1.legend([\'遇难\',\'存活\'],loc=\'upper right\')                  #图例名称及位置(upper/center/lower,left/center/right)
ax1.set_ (\'不同票价等级存活分布\')
#添加标签
for x,y,z in zip(range(5),a,b):
    ax1.text(y/2,x,\'{:.1%}\'.format(y))
    ax1.text(y+z/2,x,\'{:.1%}\'.format(z))

  • 可以看到,票价在 50 以上存活率超过65%,与前面舱位等级结果基本一致
# 从各个舱位等级的平均票价来看,一等舱存活率最高,其平均票价也是最高的,为 84
df.groupby(\'Pclass\')[\'Fare\'].mean() 

收藏 打印