问题背景:
泰坦尼克豪华游轮即将沉没,救生艇数量有限,无法人人都有,副船长‘女士小孩优先的指示下’,打破了随机获救的平衡。
分析过程:
1.流程设计:数据准备,数据清理,分析展示,建模评估
2.数据准备和观察
3.数据预处理:清理、变换、缺失值填补等
4.分析展示(一维分析、二维分析)
5.建模与评估
一:数据准备
1.1 导入数据
import numpy as np
import pandas as pd
import seaborn as sns
titanic_df=pd.read_csv('titanic-data.csv')
1.2. 观察数据
生还率为38.38%,超过75%的乘客没有父母子女,超过50%的乘客没有兄弟姐妹或配偶。
一共891条数据,Cabin缺失687个,Age缺失177个,Embarked缺失2个,Fare最小值为0,也可以看做缺失值。
sex、Cabin、Embarked 为字符型数据。
print (titanic_df.info())
##查看前5条记录
print (titanic_df.head(5))
print ('--------------')
##查看数值型数据的分布信息
print (titanic_df.describe())
二:数据预处理
2.1.数据清理
Fare有为0值的票价:显然不合理
I
##处理0值票价
titanic_df[titanic_df['Fare']==0]
import matplotlib.pyplot as plt
fig=plt.figure(figsize=(15,5))
titanic_df.Fare[titanic_df['Embarked']=='S'].plot(kind='kde')
plt.show()
##可知S等舱口的票价大部分分布于0-20
titanic_df[titanic_df['Embarked']=='S'].Fare.median()
##用中位数填补0值票价
titanic_df.loc[titanic_df['Fare']==0,'Fare']=13.0
2.2.缺失值填补
2.2.1 cabin客舱号码204个,缺失687(处理办法:丢失了77%,失去分析价值了,直接丢掉该变量)
####cabin客舱号码缺失值处理:删掉
titanic_df=titanic_df.drop('Cabin',axis=1)
2.2.2 embarked 登舱号889个,缺失2个(处理办法:相似对象填充)
#查看缺失embarked的两条数据,票价为80
titanic_df[titanic_df.Embarked.isnull()]
fig=plt.figure(figsize=(15,5))
df=titanic_df[titanic_df['Pclass']==1]
i=0
for x in ['S','C','Q']:
plt.subplot2grid((1,3),(0,i))
i=i+1
df.Fare[df.Embarked==x].plot(kind='box')
plt.legend((x))
plt.show()
##Embarked为C时,票价均值在80附近。用C来填充Embarked的空白
titanic_df['Embarked'][titanic_df.Embarked.isnull()]=['C']
2.2.3age只有714个,缺失了177个数据 (处理办法:随机数补充,选择Q1-Q3内的随机数)
###处理age变量缺失值,选择Q1-Q3内的随机数
Q1=titanic_df['Age'].describe()['25%']
Q3=titanic_df['Age'].describe()['75%']
num=titanic_df['Age'].isnull().sum()
random_ages=np.random.randint(Q1,Q3,size=num)
titanic_df['Age'][np.isnan(titanic_df['Age'])]=random_ages
2.3编码名义变量
def trans(data):
data.loc[data['Sex']=='male','Sex']=0
data.loc[data['Sex']=='female','Sex']=1
data.loc[data['Embarked']=='S','Embarked']=0
data.loc[data['Embarked']=='C','Embarked']=1
data.loc[data['Embarked']=='Q','Embarked']=2
trans(titanic_df)
三.分析与展示
3.1一维数据分析
3.1.1 Pclass 船票等级
一等舱人数216,生还人数136,生还率62.96%
二等舱人数184,生还人数87,生还率47.28%
三等舱人数491,生还人数119,生还率24.24%
并没有富人优先,但是生还率却按客舱等级成正比,可能与位置有关。一等舱位于游轮上层,利于逃生。
##按PClass分组求出生还人数及生还率
Pc_dsc=titanic_df.groupby(['Pclass']).describe()['Survived']
Pc_dsc['Survied']=Pc_dsc['count']*Pc_dsc['mean']
Pc_dsc
Pc_dsc['mean'].plot(kind='bar')
plt.title('Pclass_survived_rate')
plt.show()
3.1.2 性别
男士总人数577,生还109,生还率18.89%
女士总人数314,生还233,生还率74.20%
看来副船长的号召起作用了,女士的生还率明显高于客舱生还率,而与此对应的男士的生还率则低于客舱生还率。
##按Sex分组求出生还人数及生还率
Sex_dsc=titanic_df.groupby(['Sex']).describe()['Survived']
Sex_dsc['Survived']=Sex_dsc['count']*Sex_dsc['mean']
Sex_dsc
Sex_dsc['mean'].plot(kind='bar')
plt.title('Sex of survived')
plt.show()
3.1.3 年龄
儿童人数69,生还40人,生还率57.97%(儿童优先的体现)
青少年70人,生还30人,生还率42.86%
青壮年712人,生还260人,生还36.52%
老年40人,生还12人,生还率30%
##创建年龄阶段字段
'''
0-12儿童,12-18青少年,18-55青壮年,55-80老年
'''
titanic_df['Age_class']=pd.cut(titanic_df['Age'],bins=[0,12,18,55,80])
Age_dsc=titanic_df.groupby(['Age_class']).describe()['Survived']
Age_dsc['Survied']=Age_dsc['count']*Age_dsc['mean']
Age_dsc
Age_dsc['mean'].plot(kind='bar')
plt.title('Age of survived')
plt.show()
3.1.4Fare 票价与生还率的关系
按照四分位点将票价分为4个等级,从图中可以看到,随着票价的增长,生还率也随之生长。
##票价比较分散,查看一下分布
titanic_df.Fare.describe()
##创建票价分组字段 fare_class,依据上述四份位点(7.91,14.45,31)将人数均分在四组中
titanic_df['Fare_class']=pd.cut(titanic_df['Fare'],bins=[0,7.91,14.45,31,513])
##生还率:
fare_dsc=titanic_df.groupby(['Fare_class']).describe()['Survived']
fare_dsc
fare_dsc['mean'].plot(kind='bar')
plt.show()
3.2 二维数据分析
3.2.1 性别与客舱等级
性别与客舱等级都是生还率梯度较陡的指标,对两个因素综合分析,也许可以得到更清晰的观测结果
将1等舱、3等舱的男士女士分别组成:rich men、poor men、rich women、poor women
--------------
poor men的生还率不到20%,rich women的生还率接近100%。
fig=plt.figure(figsize=(15,5))
##rich men 生存情况
plt.subplot2grid((1,4),(0,0))
titanic_df.Survived[(titanic_df.Pclass==1)&(titanic_df.Sex==0)].value_counts(normalize=True).plot(kind='bar',alpha=0.5)##
plt.title('Rich Men survived')
##poor men 生存情况
plt.subplot2grid((1,4),(0,1))
titanic_df.Survived[(titanic_df.Pclass==3)&(titanic_df.Sex==0)].value_counts(normalize=True).plot(kind='bar',alpha=0.5)##
plt.title('Poor Men survived')
##rich Women 生存情况
plt.subplot2grid((1,4),(0,2))
titanic_df.Survived[(titanic_df.Pclass==1)&(titanic_df.Sex==1)].value_counts(normalize=True).plot(kind='bar',alpha=0.5)##
plt.title('Rich Womenn survived')
##poor Women 生存情况
plt.subplot2grid((1,4),(0,3))
titanic_df.Survived[(titanic_df.Pclass==3)&(titanic_df.Sex==1)].value_counts(normalize=True).plot(kind='bar',alpha=0.5,)##
plt.title('Poor Women survived')
plt.show()
3.2.2 客舱等级与年龄(阶段)
除了儿童年龄段,其他年龄段的生还率都是随着客舱等级的升高而增大。
而儿童的不符合这一规律。而一等舱的儿童总人数只有4人,不具有代表性。
fig=plt.figure(figsize=(15,5))
titanic_df.groupby(['Age_class','Pclass'])['Survived'].mean().unstack().plot(kind='bar')
plt.title('Pclass_age wrt Survived')
plt.show()
##分析儿童年龄段背离规律的原因
titanic_df[titanic_df.Age<=12].groupby('Pclass').describe()['Survived']
3.2.2 性别等级与年龄(阶段)
不论性别,儿童的生还率都很高。
但是对于非儿童的人,则‘女士优先’体现明显。
fig=plt.figure(figsize=(15,5))
titanic_df.groupby(['Age_class','Sex'])['Survived'].mean().unstack().plot(kind='bar')
plt.title('Sex_age wrt Survived')
plt.show()
3.3 从数据得到的初步结论
性别、年龄(儿童与非儿童)、客舱等级是主要影响生还率的因
四.建模与评估
典型的二分类,生还与否取决于多种因素,我选择用逻辑回归和决策树来建模。
4.1逻辑回归建模
首先进行交叉验证,将数据分为:训练集(train_set),评估集(valid_set),测试集(test_set)这三个部分,首先用训练集对分类器进行训练,再利用验证集来测试训练得到的模型(model),以此来做为评价分类器的性能指标。
from sklearn import cross_validation
from sklearn.linear_model import LogisticRegression
##初始化算法
alg=LogisticRegression(C=1.0,penalty='l2',tol=1e-6,random_state=1)
##选取対生成预测有影响的特征
titanic=titanic_df.ix[:,['Survived','Pclass','Sex','Fare','SibSp','Parch','Embarked','Age']]
##titanic=titanic_df.ix[:,['Survived','Pclass','Sex','Fare','SibSp','Parch','Embarked','Ca']]
X=titanic.as_matrix()[:,1:]
y=titanic.as_matrix()[:,0]
scores=cross_validation.cross_val_score(alg,X,y,cv=3)
scores.mean()