Kaggle泰坦尼克号之灾1--数据分析

本文是参考寒小阳大神的博客:http://blog.csdn.net/han_xiaoyang/article/details/49797143
中的实现所做的记录,想通过这个例子学习学习拿到数据后怎样进行分析,整个分析和分类的流程是什么样的。

泰坦尼克号之灾主要是一个二分类问题。

因为感觉光看不动手写一写只知道个原理,结果还是不知道怎么写。因此我又按照那篇博文撸了一遍代码。

整个过程分两部分:第一步是先对原始数据进行分析;第二步才是进行学习建模。

该篇记录先来进行第一部分,也就是数据分析的部分。拿到一组数据后,我们首先要做的是对这些数据进行初步的分析,看看哪些数据值得我们需要。

当然首先要做的就是加载数据来看一看,这里用pandas库,一个非常好的数据分析库:

# 首先引入需要用的库

import pandas as pd # pandas专门用来进行数据分析,蛮有用的
import numpy as np
from pandas import Series,DataFrame

# 加载数据,看看数据长什么样
data_train = pd.read_csv('Train.csv')
data_train.head()  # 打印头五个出来看看

可以看到如下输出:

泰坦尼克号数据表格

有哪些属性都一目了然。可以看到有10多个字段(并不是所有字段都是特征属性哦):

  • PassengerId:乘客ID
  • Survived:是否获救
  • Pclass:乘客等级
  • Name:乘客姓名
  • Sex:性别
  • Age:年龄
  • SibSp:堂兄弟妹个数
  • Parch:父母与小孩个数
  • Ticket:船票信息
  • Fare:票价
  • Cabin:客舱
  • Embarked:登船港口

接着看看这些数据的基本信息:

data_train.info()

打印如下:

基本信息

可以看到,RangeIndex是说总共有891个数据,列数有12列;并且能够看到每列数据的类型,而且能看出有些数据是不全的,比如Age只有714个数,Cabin只有204个数。

再来看看详细点的描述呢:

data_train.describe()

输出:


以上函数更能描述数据的一些事情。我们可以看到,上面的表格中将特征中数值型数据的一些属性计算了出来,可以一目了然的看到每类数值型特征的平均值,标准差,最小值等属性。比如Age一栏,看到乘客的平均年龄为29.6岁。

接下来继续分析数据。看完了每个数据单独的关系,现在应该结合我们最终的目的来看看数据间相互的关系了。我们最终是分类,也就是想找出哪些特征与最终是否获救有关。因此我们可以看看每个或多个属性和最后获救Survived数据有什么样的关系。

先来画画图吧:

import matplotlib.pyplot as plt

fig = plt.figure()
fig.set(alpha=0.2) # 设定图表颜色alpha参数

# 在一张大图里分列几个小图
plt.subplot2grid((2,3),(0,0))
data_train.Survived.value_counts().plot(kind='bar')
plt.title(u"获救情况(1为获救)")
plt.ylabel(u"人数")

plt.subplot2grid((2,3),(0,1))
data_train.Pclass.value_counts().plot(kind='bar')
plt.ylabel(u"人数")
plt.title(u"乘客等级分布")

plt.subplot2grid((2,3),(0,2))
plt.scatter(data_train.Survived,data_train.Age)
plt.ylabel(u"年龄")
plt.grid(b=True,which='major',axis='y')
plt.title(u"按年龄看获救分布(1为获救)")

plt.subplot2grid((2,3),(1,0),colspan=2)
data_train.Age[data_train.Pclass == 1].plot(kind='kde')
data_train.Age[data_train.Pclass == 2].plot(kind='kde')
data_train.Age[data_train.Pclass == 3].plot(kind='kde')
plt.xlabel(u"年龄")
plt.ylabel(u"密度")
plt.title(u"各等级的乘客年龄分布")
plt.legend((u'头等舱',u'2等舱',u'3等舱'),loc='best')

plt.subplot2grid((2,3),(1,2))
data_train.Embarked.value_counts().plot(kind='bar')
plt.title(u"各登船口岸人数")
plt.ylabel(u"人数")

plt.show()

图如下:

由上面的图我们又可以看到一些情况,比如获救情况不容乐观,300多人,连一半都没到;
3等舱的人蛮多的;
从年龄来看,遇难和获救的人跨度都很广;

然后开始分析主要属性对获救的关系,先看看乘客等级:

# 再来看看各乘客等级的获救情况
fig = plt.figure()
fig.set(alpha=0.2)

Survived_0 = data_train.Pclass[data_train.Survived == 0].value_counts()
Survived_1 = data_train.Pclass[data_train.Survived == 1].value_counts()
df = pd.DataFrame({u'获救':Survived_1,u'未获救':Survived_0})
df.plot(kind='bar',stacked=True)
plt.title(u"各乘客等级的获救情况")
plt.xlabel(u"乘客等级")
plt.ylabel(u"人数")

plt.show()

图如下:

乘客等级的获救情况

可以看到在1等舱里面获救的几率就要大得多呢!果然有钱有权的就是好。

接着看港口位置:

fig = plt.figure()
fig.set(alpha=0.2)

Survived_E0 = data_train.Embarked[data_train.Survived == 0].value_counts()
Survived_E1 = data_train.Embarked[data_train.Survived == 1].value_counts()
df = pd.DataFrame({u"获救":Survived_E1,u"未获救":Survived_E0})
df.plot(kind='bar',stacked=True)
plt.title(u"各登陆港口乘客的获救情况")
plt.xlabel(u"登陆港口")
plt.ylabel(u"人数")

plt.show()
港口位置情况

好像并没有什么有价值的。

再来看性别:

fig = plt.figure()
fig.set(alpha=0.2)

Survived_sex0 = data_train.Sex[data_train.Survived == 0].value_counts()
Survived_sex1 = data_train.Sex[data_train.Survived == 1].value_counts()
df = pd.DataFrame({u'获救':Survived_sex1,u'未获救':Survived_sex0})
df.plot(kind='bar',stacked=True)
plt.title(u"按性别看获救情况")
plt.xlabel(u"性别")
plt.ylabel(u"人数")
plt.show()
性别分布

这幅图上明显可以看出,船上的人确实都蛮绅士的,贯彻落实副船长所说的“让小孩和女士先走”政策。

再来细些,看看每个舱里的性别情况呢?

fig=plt.figure()
fig.set(alpha=0.65) # 设置图像透明度,无所谓
plt.title(u"根据舱等级和性别的获救情况")

ax1 = fig.add_subplot(141)
data_train.Survived[data_train.Sex == 'female'][data_train.Pclass != 3].value_counts().plot(kind='bar',label='female highclass',color='#FA2479')
ax1.set_xticklabels([u"获救",u"未获救"],rotation=0)
ax1.legend([u"女性/高级舱"], loc='best')

ax2=fig.add_subplot(142, sharey=ax1)
data_train.Survived[data_train.Sex == 'female'][data_train.Pclass == 3].value_counts().plot(kind='bar', label='female, low class', color='pink')
ax2.set_xticklabels([u"未获救", u"获救"], rotation=0)
plt.legend([u"女性/低级舱"], loc='best')

ax3=fig.add_subplot(143, sharey=ax1)
data_train.Survived[data_train.Sex == 'male'][data_train.Pclass != 3].value_counts().plot(kind='bar', label='male, high class',color='lightblue')
ax3.set_xticklabels([u"未获救", u"获救"], rotation=0)
plt.legend([u"男性/高级舱"], loc='best')

ax4=fig.add_subplot(144, sharey=ax1)
data_train.Survived[data_train.Sex == 'male'][data_train.Pclass == 3].value_counts().plot(kind='bar', label='male low class', color='steelblue')
ax4.set_xticklabels([u"未获救", u"获救"], rotation=0)
plt.legend([u"男性/低级舱"], loc='best')

plt.show()
舱等级性别情况

然后是堂兄妹等等:

# 再看看其他的获救情况
fig = plt.figure()
fig.set(alpha=0.2)

Survived_S0 = data_train.SibSp[data_train.Survived == 0].value_counts()
Survived_S1 = data_train.SibSp[data_train.Survived == 1].value_counts()
df = pd.DataFrame({u'获救':Survived_S1,u'未获救':Survived_S0})
df.plot(kind='bar',stacked=True)
plt.title(u"按堂兄妹看获救情况")
plt.xlabel(u"堂兄妹个数")
plt.ylabel(u"人数")
plt.show()
堂兄妹属性

简化版(Parch属性):

g = data_train.groupby(['Parch','Survived'])
df = pd.DataFrame(g.count()['PassengerId'])
df
Parch属性和获救的关系

好像并没啥关系吧。

好吧,数据里还有一些比如船票应该是1人1张的,和最后是否获救应该没啥关系,因此暂时不用看了。

还有就是有些数据不全的值,比如说Cabin,只有204个数据,这也是我们需要分析分析的,先来看看它的分布:

data_train.Cabin.value_counts()
打印出来的一部分。。。

这Cabin数据也是。。一眼看上去感觉很多又乱,而且每个就那么几个。。一个一个看也太麻烦了。。就先看看Cabin这个数据有或没有两种情况和获救的关系吧。

# Cabin值太分散了,很多都是只出现了1次,因此先看看这个值的有无,对于survival的分布状况
fig = plt.figure()
fig.set(alpha=0.2)

Survived_cabin = data_train.Survived[pd.notnull(data_train.Cabin)].value_counts()
Survived_nocabin = data_train.Survived[pd.isnull(data_train.Cabin)].value_counts()
df = pd.DataFrame({u"登记了船舱":Survived_cabin,u"没登记船舱":Survived_nocabin}).transpose()
df.plot(kind='bar',stacked=True)
plt.title(u"按Cabin有无看获救情况")
plt.xlabel(u"Cabin有无")
plt.ylabel(u"人数")

plt.show()
登记有无船舱

看样子好像有船舱记录的获救比例高些啊,那么就先这样把Cabin分成Yes和No吧,作为一个特征。

接下来还有一个拥有缺失值的属性Age年龄,其实这个属性应该还是有些关键的,因为副船长说过嘛,小孩也是优先级高的,因此Age或许是个比较大的影响因子。但是作为候选特征的Age数据却不全,这怎么办呢?

遇到缺值的情况,一般有几种常见的处理方式:

  1. 如果缺失值的样本占总数的比例极高,我们可能直接丢弃,因为它本来就没几个嘛,或许是噪点呢。
  2. 如果缺失值的样本适中,而且该属性不是连续值的特征(就像刚才的Cabin,可以看做类目属性),就可以把NaN作为一个新类别,加入到类别特征中去;(刚才是因为Cabin里类目太分散了,每个的数量又很稀少,因此就定了有和无两个类目)
  3. 如果缺失值的样本适中,而该属性又是连续型的,有时候就会考虑给定一个step(比如这里的age,我们可以考虑每隔2/3岁为一个步长),然后把它离散化,之后把NaN作为一个type加到属性类目中。
  4. 有些情况下,缺失的值个数并不是特别多,那我们也可以试着根据已有的值,拟合一下数据,补充上。

在Age值的处理上,这里可以采用拟合补全的方法。(比如用机器学习里面的回归):

from sklearn.ensemble import RandomForestRegressor

# 使用RandomForestRegressor填补缺失的年龄属性
def set_missing_ages(df):
    # 把已有的数值型特征取出丢进RandomForestRegressor中
    age_df = df[['Age','Fare','Parch','SibSp','Pclass']]
    
    known_age = age_df[age_df.Age.notnull()].as_matrix()
    unknown_age = age_df[age_df.Age.isnull()].as_matrix()
    
    y = known_age[:,0]
    
    X = known_age[:,1:]
    
    # fit到RandomForestRegressor中
    rfr = RandomForestRegressor(random_state=0,n_estimators=2000,n_jobs=-1)
    rfr.fit(X,y)
    
    # 用模型进行未知年龄结果预测
    predictedAges = rfr.predict(unknown_age[:,1::])
    
    # 用预测结果补全原缺失数据
    df.loc[(df.Age.isnull()),'Age'] = predictedAges
    
    return df,rfr

def set_Cabin_type(df):
    df.loc[(df.Cabin.notnull()),'Cabin'] = 'Yes'
    df.loc[(df.Cabin.isnull()),'Cabin'] = 'No'
    return df

data_train,rfr = set_missing_ages(data_train)
data_train = set_Cabin_type(data_train)
data_train
打印部分数据

训练出来了,现在没有缺失值了,看看:

data_train.info()
info

可以看到已经没有缺失值了,当然那个Embarked少了两个,可以直接忽略。。

那么特征分析的差不多了,要开始进行学习分类了。但还有一步需要做做。在这些特征中,有些特征是类目型特征并不是数值,而我们通常机器学习是需要用到的是数值型的特征,那么我们就该把对应的类目型特征转换为数值型特征。怎么做呢?

一般来说可以因子化/one-hot编码。

而且pandas里面有个get_dummies函数可以干这个事哦。

# Cabin,原本是一个属性,取值为['Yes','No'],现在因子化后,就变成两个属性’Cabin_yes‘和’Cabin_No‘
# 原本Cabin取值为yes的,在此处的'Cabin_yes'下取值为1,在'Cabin_no'下取值为0;反之亦然
# 其它类目型同理

dummies_Cabin = pd.get_dummies(data_train['Cabin'],prefix='Cabin')

dummies_Embarked = pd.get_dummies(data_train['Embarked'],prefix='Embarked')

dummies_Sex = pd.get_dummies(data_train['Sex'],prefix='Sex')

dummies_Pclass = pd.get_dummies(data_train['Pclass'],prefix='Pclass')

df = pd.concat([data_train,dummies_Cabin,dummies_Embarked,dummies_Sex,dummies_Pclass],axis=1)
# 丢掉一些不需要的值了
df.drop(['Pclass','Name','Sex','Ticket','Cabin','Embarked'],axis=1,inplace=True)
df

现在可以看到特征全是数值型的,并且都是我们需要的特征了。

# 再次打印数据描述来看看
df.describe()
有较多,这里没展示完

我们可以看到Age和Fare的范围跨度有点大啊,分别是0.4280,0512。这应该要处理一下了,不然会影响到收敛速度的,因此需要对这两个数进行所说的归一化。话说还有PassengerId呢,这属性一看就是个id,不是特征,就不管了。

# 数据分析完,就开始对数据进行预处理了,比如归一化。
import sklearn.preprocessing as preprocessing

scaler = preprocessing.StandardScaler()

age_scale_param = scaler.fit(df['Age'])

df['Age_scaled'] = scaler.fit_transform(df['Age'],age_scale_param)

fare_scale_param = scaler.fit(df['Fare'])

df['Fare_scaled'] = scaler.fit_transform(df['Fare'],fare_scale_param)
df

数据预处理的处理完了,接下来就可以进行相应的建模了。一般就使用sklearn来进行建模了。

泰坦尼克号的初步数据分析基本到这就完成了,下一篇就根据以上处理过的数据进行分类模型的建立以及后续的分析。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,185评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,445评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,684评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,564评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,681评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,874评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,025评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,761评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,217评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,545评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,694评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,351评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,988评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,778评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,007评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,427评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,580评论 2 349

推荐阅读更多精彩内容