1.活动背景
The Challenge
The sinking of the Titanic is one of the most infamous shipwrecks in history.
On April 15, 1912, during her maiden voyage, the widely considered “unsinkable” RMS Titanic sank after colliding with an iceberg. Unfortunately, there weren’t enough lifeboats for everyone onboard, resulting in the death of 1502 out of 2224 passengers and crew.
While there was some element of luck involved in surviving, it seems some groups of people were more likely to survive than others.
In this challenge, we ask you to build a predictive model that answers the question: “what sorts of people were more likely to survive?” using passenger data (ie name, age, gender, socio-economic class, etc).
泰坦尼克号(RMS Titanic),又译作铁达尼号,是英国白星航运公司下辖的一艘奥林匹克级游轮,排水量46000吨,是当时世界上体积最庞大、内部设施最豪华的客运轮船,有“永不沉没”的美誉 。在它的处女航行中,泰坦尼克号与一座冰山相撞,造成右舷船艏至船中部破裂,五间水密舱进水。1912年4月15日凌晨2时20分左右,泰坦尼克船体断裂成两截后沉入大西洋底3700米处。2224名船员及乘客中,1517人丧生,其中仅333具罹难者遗体被寻回。泰坦尼克号沉没事故为和平时期死伤人数最为惨重的一次海难,其残骸直至1985年才被再度发现,目前受到联合国教育、科学及文化组织的保护。
在英剧《Downton Abbey》中,Robert伯爵在听到Titanic沉没的消息时候说:“Every mountain is unclimbable until someone clime it, so every ship is unsinkable until it sinks.”(没有高不可攀的高峰,也没有永不翻沉的船)
2.详细代码解释
导入Python Packages
首先导入需要的python包
import numpy as np import pandas as pd import matplotlib.pyplot as plt from sklearn import metrics from sklearn.linear_model import LogisticRegression import seaborn as sns import warnings warnings.filterwarnings("ignore")
读入数据 Read-In Data
将train.csv和test.csv读入,读入数据进行建模
train = pd.read_csv('../data_files/1.Titantic_data/train.csv') test = pd.read_csv('../data_files/1.Titantic_data/test.csv') train.info() # 查看train.csv的总体 test.info() # 查看test.csv的总体
会出现以下结果,train有891条数据,test有418条数据,并且我们可以从数据中看出,在train和test中,有一些数据是有缺失值的,所以需要进行数据预处理
在这里也介绍一下数据的含义吧
数据介绍:
Survived 是否存活(label)
PassengerId (乘客ID)
Pclass(用户阶级):1 - 1st class,高等用户;2 - 2nd class,中等用户;3 - 3rd class,低等用户;
Name(名字)
Sex(性别)
Age(年龄)
SibSp:描述了泰坦尼克号上与乘客同行的兄弟姐妹(Siblings)和配偶(Spouse)数目;
Parch:描述了泰坦尼克号上与乘客同行的家长(Parents)和孩子(Children)数目;
Ticket(船票号)
Fare(乘客费用)
Cabin(船舱)
Embarked(港口):用户上船时的港口
缺失数据处理
从刚刚的总体情况可以看出,有一些数据是具有缺失值的,所以我们需要对缺失值进行一些处理
首先看看有哪些数据是缺失的
从数据可以看出来,缺失的比较多的是Age和Cabin,Embarked有少部分是缺失的
通常遇到缺值的情况,我们会有几种常见的处理方式
如果缺值的样本占总数比例极高,我们可能就直接舍弃了,作为特征加入的话,可能反倒带入noise,影响最后的结果了
如果缺值的样本适中,而该属性非连续值特征属性(比如说类目属性),那就把NaN作为一个新类别,加到类别特征中
如果缺值的样本适中,而该属性为连续值特征属性,有时候我们会考虑给定一个step(比如这里的age,我们可以考虑每隔2/3岁为一个步长),然后把它离散化,之后把NaN作为一个type加到属性类目中。
有些情况下,缺失的值个数并不是特别多,那我们也可以试着根据已有的值,拟合一下数据,补充上。
对缺失字段’Age’处理
我们可以看看Age的缺失率大概是多少
print('Percent of missing "Cabin" records is %.2f%%' %((train['Age'].isnull().sum()/train.shape[0])*100)) # Percent of missing "Cabin" records is 19.87%
从结果可以看出,大约是19.87%
sns.set() sns.set_style('ticks') # 缺失值处理:年龄Age字段 train_age=train[train['Age'].notnull()] # 年龄数据的分布情况 plt.figure(figsize=(12,8)) plt.subplot(121) train_age['Age'].hist(bins=80) plt.xlabel('Age') plt.ylabel('Num') plt.subplot(122) train_age.boxplot(column='Age',showfliers=True,showmeans=True) train_age['Age'].describe()
我们可以画出关于notnull的Age字段的直方图和箱线图
接着要对’Age‘字段的缺失值,这里我用的是将其他Age数据的平均值来填补缺失值
# 要对缺失值处理 train['Age']=train['Age'].fillna(train['Age'].mean()) train.info()
处理完以后,可以再看一眼train的数据
这时候Age字段的缺失值被填补完毕了
对缺失字段’Cabin’处理
我们可以看看’Cabin‘字段的缺失率
print('Percent of missing "Cabin" records is %.2f%%' %((train['Cabin'].isnull().sum()/train.shape[0])*100)) # Percent of missing "Cabin" records is 77.10%
它的缺失率居然高达77.1%,所以对于这样的字段,我打算在建模的时候,直接将其舍去,不以它作为变量
train.drop(['Cabin'],axis=1,inplace=True) # 删去Cabin的那一列数据
对缺失字段’Embarked’处理
继续看一看它的缺失率
print('Percent of missing "Embarked" records is %.2f%%' %((train_df['Embarked'].isnull().sum()/train_df.shape[0])*100)) # Percent of missing "Embarked" records is 0.22%
整个训练集,也只有2个数据是缺失的,然后我们再来看一看Embarked的分布
sns.countplot(x='Embarked',data=train,palette='Set1') plt.show() train['Embarked'].value_counts()
从数据可以看出来,Embarked只有三个值,其中S的值最多,所以我直接将S填充那缺失的两个值。
train.Embarked = train.Embarked.fillna('S')
缺失值处理
经过分析以后,进行缺失值处理,再看看处理后的数据
train['Age']=train['Age'].fillna(train['Age'].mean()) # 用平均值填充 train.drop(['Cabin'],axis=1,inplace=True) # 删去Cabin的那一列数据 train.Embarked = train.Embarked.fillna('S') # 用’S'填补缺失值 trian.info()
这时候就没有缺失值了,处理完毕
数据分析
对数据的认识是十分重要的,所以我们在这里进行对各个字段的分析,看看每个属性与最后的Survived有什么关系
首先可以总体粗略的看一下
train_survived=train[train['Survived'].notnull()] # 用seaborn绘制饼图,分析已知存活数据中的存活比例 sns.set_style('ticks') # 十字叉 plt.axis('equal') #行宽相同 train_survived['Survived'].value_counts().plot.pie(autopct='%1.2f%%')
在这次中,大约有38.38的人存活了下来
分析Sex
# 男性和女性存活情况 train[['Sex','Survived']].groupby('Sex').mean().plot.bar() survive_sex=train.groupby(['Sex','Survived'])['Survived'].count() print('女性存活率%.2f%%,男性存活率%.2f%%' % (survive_sex.loc['female',1]/survive_sex.loc['female'].sum()*100, survive_sex.loc['male',1]/survive_sex.loc['male'].sum()*100) )
# 查看survived 与 Sex的关系 Survived_Sex = train['Sex'].groupby(train['Survived']) print(Survived_Sex.value_counts().unstack()) Survived_Sex.value_counts().unstack().plot(kind = 'bar', stacked = True) plt.show()
从数据结果可以得出,女性比男性的存活率是更高的