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閱讀 228,646評論 6 533
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,595評論 3 418
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,560評論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,035評論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,814評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,224評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,301評論 3 442
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,444評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,988評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,804評論 3 355
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,998評論 1 370
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,544評論 5 360
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,237評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,665評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,927評論 1 287
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,706評論 3 393
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,993評論 2 374

推薦閱讀更多精彩內容