【Kaggle入門級競賽top5%排名經驗分享】— 分析篇

做者:xiaoyupython

微信公衆號:Python數據科學微信

知乎:python數據分析師app


Kaggle做爲公認的數據挖掘競賽平臺,有不少公開的優秀項目,而其中做爲初學者入門的一個好的項目就是:泰坦尼克號生還者預測學習

可能這個項目好多朋友也據說過,可能不少朋友也作過。可是項目完成後,是否有很好的反思總結呢?不少朋友只是潦草的敷衍過去了,知道大概的套路了就沒再去看。其實,一個再簡單的項目,若是把它作好也能有巨大的收穫。測試

博主開始作的時候,也是通過反覆琢磨和嘗試,並從最初的20%到最好的2%,期間學習了不少,不得不說這個項目讓我很好的瞭解了數據挖掘。spa

本篇,博主將會從零開始介紹這個項目,教你如何一步一步的把這個
項目作好。因爲大部分星球的朋友們已經完成了分析部分的實戰練習,所以將這部份內容拿出來進行簡單的分享。3d

項目介紹

首先對這個項目進行一下介紹。code

數據探索

萬變不離其宗,拿到數據首先粗率的觀察。orm

"""
導入數據
"""
import pandas as pd
import numpy as np

data_train = pd.read_csv('train.csv')
data_test = pd.read_csv('test.csv')
df = data_train.append(data_test)

將訓練集和測試集進行合併,以便後續數據內容變換的統一處理。blog

df.info()
print('合併後一共{0}條數據。'.format(str(df.shape[0])))
print(pd.isnull(df).sum())

合併後一共1309條數據,並能夠看到:age,cabin,embarked,Fare 四個特徵有缺失值,其中cabin缺失比較嚴重。

df.describe()

異常值初始觀察(主要觀察一下最大與最小值):

  • Fare:船票價格平均值33.2,中位數14,平均值比中位數大不少,說明該特徵分佈是嚴重的右偏,又看到最大值512,因此512極可能是隱患的異常值。
  • Age:最小值爲0.17,最大值爲80,0.17是大概剛出生一個半月的意思,而80年齡有些過大,須要進一步排查。
  • SibSp與Parch:Sibsp最大爲8,多是異常,但又看到Parch最大值爲9。這兩個特徵同時出現大的數值,第一放映是這個數值是有可能的,咱們進步一觀察。

結論: 經過以上觀察和分析,咱們看到了一些可能的異常值,可是也不敢確定。這須要咱們進一步經過可視化來清楚的顯示並結合對業務的理解來肯定。

數據可視化

定類/定序特徵分析

import matplotlib.pyplot as plt
import seaborn as sns
%matplotlib inline

plt.style.use("bmh")
plt.rc('font', family='SimHei', size=13)
cat_list = ['Pclass','Name','Sex','SibSp','Embarked','Parch','Ticket','Cabin']
for n,i in enumerate(cat_list):  
    Cabin_cat_num = df[i].value_counts().index.shape[0]
    print('{0}. {1}特徵的類型數量是: {2}'.format(n+1,i,Cabin_cat_num))

結論

從上面各特徵值的類型數量來看:

  • 一些比較少數量的特徵如Pclass,Sex,SibSp,Embarked,Parch等可進行可視化分析。
  • 剩下特徵如Name(每一個人名字都不同),或者TicketCabin因爲分類太多對於可視化不是太方便,後續對這些特徵單獨分析。

所以,先對上面5種容易的分類進的特徵行可視化。

f, [ax1,ax2,ax3] = plt.subplots(1,3,figsize=(20,5))
sns.countplot(x='Sex', hue='Survived', data=data_train, ax=ax1)
sns.countplot(x='Pclass', hue='Survived', data=data_train, ax=ax2)
sns.countplot(x='Embarked', hue='Survived', data=data_train, ax=ax3)
ax1.set_title('Sex特徵分析')
ax2.set_title('Pclass特徵分析')
ax3.set_title('Embarked特徵分析')
f.suptitle('定類/定序數據類型特徵分析',size=20,y=1.1)

f, [ax1,ax2] = plt.subplots(1,2,figsize=(20,5))
sns.countplot(x='SibSp', hue='Survived', data=data_train, ax=ax1)
sns.countplot(x='Parch', hue='Survived', data=data_train, ax=ax2)
ax1.set_title('SibSp特徵分析')
ax2.set_title('Parch特徵分析')

plt.show()

對於上面的定類和定序數據類型,咱們分別能夠觀察到各特徵值的分佈狀況,以及與目標變量之間的聯繫。

  • Sex: 對於女性而言,男性總人數雖多,可是獲救率明顯很低(先救婦女!!!);
  • Pclass: 社會等級爲3的總人數最多(也就是大多數人都是普通老百姓),可是獲救率很是低(社會價值高的人優先留下);
  • Embarked: 登錄港口S數量最多,可是獲救率也是最低的,C港口獲救率最高;
  • SibSp: 兄弟姐妹數量最低爲0的人數最多,可是獲救率最低,而爲1的獲救率相對較高,超過50%;
  • Parch: 狀況基本同SibSp同樣,後續能夠考慮將兩者合併;

就以上5個特徵來看,Sex和Pclass兩個特徵是其中很是有影響的兩個。

以上只是單獨特徵對是否生還的簡單分析,但實際上對目標變量的影響是由多個因素形成的,而不僅是單獨的影響。爲此,咱們須要知道在某個特定條件下的特徵的影響才更加能幫助咱們分析:

  • 好比咱們想看看Pclass是1的狀況下,男性和女性生還機率有何不一樣;
  • 更具體的好比咱們想看看Pclass是1且爲male的狀況下,Embarked特徵的影響是什麼樣的;

如下是用FaceGrid進行的具體分析:

# 在不一樣社會等級下,男性和女性在不一樣登錄港口下的數量對比
grid = sns.FacetGrid(df, col='Pclass', hue='Sex', palette='seismic', size=4)
grid.map(sns.countplot, 'Embarked', alpha=0.8)
grid.add_legend()

觀察結果

  • Pclass爲1和2的時候,Q港口數量幾乎爲零,而Pclass3的Q港口人數甚至比C港口多。這說明社會等級與港口有關聯,根據社會等級與港口的對應關係可推測S和C港口爲高級港口,而Q港口爲普通港口。
  • Pclass爲2的港口中,男性與女性在S和C港口的數量分佈呈現相反趨勢,與其餘Pclass等級大相徑庭,這說明Pclass2多是社會中某個共性羣體,這個羣體多爲女性,而男性不多。既然多爲女性,且女性生還機率還大,可推測Pclass2的C港口的生還機率也很高。
# 在不一樣社會等級下,男性和女性在不一樣登錄港口下的數量對比
grid = sns.FacetGrid(data_train, row='Sex', col='Pclass', hue='Survived', palette='seismic', size=4)
grid.map(sns.countplot, 'Embarked', alpha=0.8)
grid.add_legend()

定距/定比特徵分析

1. Age分佈和特徵分析

# kde分佈
f,ax = plt.subplots(figsize=(10,5))
sns.kdeplot(data_train.loc[(data_train['Survived'] == 0),'Age'] , color='gray',shade=True,label='not survived')
sns.kdeplot(data_train.loc[(data_train['Survived'] == 1),'Age'] , color='g',shade=True, label='survived')
plt.title('Age特徵分佈 - Surviver V.S. Not Survivors', fontsize = 15)
plt.xlabel("Age", fontsize = 15)
plt.ylabel('Frequency', fontsize = 15)

結論:

很明顯看到,以上Survived與Not Survived特徵分佈的主要區別在 0 ~15左右。小於15歲如下的乘客(也就是孩子)獲救率很是高,而大於15歲的乘客分佈無明顯區別。

# 箱型圖特徵分析
fig, [ax1,ax2] = plt.subplots(1,2,figsize=(20,6))
sns.boxplot(x="Pclass", y="Age", data=data_train, ax =ax1)
sns.swarmplot(x="Pclass", y="Age", data=data_train, ax =ax1)
sns.kdeplot(data_train.loc[(data_train['Pclass'] == 3),'Age'] , color='b',shade=True, label='Pcalss3',ax=ax2)
sns.kdeplot(data_train.loc[(data_train['Pclass'] == 1),'Age'] , color='g',shade=True, label='Pclass1',ax=ax2)
sns.kdeplot(data_train.loc[(data_train['Pclass'] == 2),'Age'] , color='r',shade=True, label='Pclass2',ax=ax2)
ax1.set_title('Age特徵在Pclass下的箱型圖', fontsize = 18)
ax2.set_title("Age特徵在Pclass下的kde圖", fontsize = 18)
fig.show()


結論:

不一樣Pclass下的年齡分佈也不一樣,三個分佈的中位數大小按 Pclass1 > Pclass2 > Pclass3 排列。這也符合實際狀況,Pclass1的乘客是社會上的擁有必定財富和地位的成功人士,年齡比較大,而Pclass3的人數最多,由於大多數人還都是普通人(有錢人畢竟少數),而且這些人可能是年輕人,年齡在20-30之間。

# Sex,Pclass分類條件下的 Age年齡對Survived的散點圖
grid = sns.FacetGrid(data_train, row='Sex', col='Pclass', hue='Survived', palette='seismic', size=3.5)
grid.map(plt.scatter, 'PassengerId', 'Age', alpha=0.8)
grid.add_legend()

結論:

從散點圖來分析:

  • Pclass1和Pclass2的女性幾乎都是Survived的,Pclass3中女性Survived則不是很明顯了;
  • Pclass1的男性生還率最高,Pclass2和Pclass3的生還率比較低,可是Pclass2中年齡小的乘客幾乎所有生存;

印證了那個原則:婦女和孩子優先營救。

# Sex,Embarked分類條件下的 Age年齡對Survived的散點圖
grid = sns.FacetGrid(data_train, col = "Embarked", row = "Sex", hue = "Survived", palette = 'seismic', size=3.5)
grid = grid.map(plt.scatter, "PassengerId", "Age")
grid.add_legend()
grid

# Sex,SibSp分類條件下的 Age年齡對Survived的散點圖
grid = sns.FacetGrid(data_train, col = "SibSp", row = "Sex", hue = "Survived", palette = 'seismic')
grid = grid.map(plt.scatter, "PassengerId", "Age")
grid.add_legend()
grid

# Sex,Parch分類條件下的 Age年齡對Survived的散點圖
grid = sns.FacetGrid(data_train, col = "Parch", row = "Sex", hue = "Survived", palette = 'seismic')
grid = grid.map(plt.scatter, "PassengerId", "Age")
grid.add_legend()
grid

2. Fare分佈和特徵分析

# 箱型圖特徵分析
fig, [ax1,ax2] = plt.subplots(1,2,figsize=(20,6))
sns.boxplot(x="Pclass", y="Fare", data=data_train, ax =ax1)
sns.swarmplot(x="Pclass", y="Fare", data=data_train, ax =ax1)
sns.kdeplot(data_train.loc[(data_train['Pclass'] == 3),'Fare'] , color='b',shade=True, label='Pcalss3',ax=ax2)
sns.kdeplot(data_train.loc[(data_train['Pclass'] == 1),'Fare'] , color='g',shade=True, label='Pclass1',ax=ax2)
sns.kdeplot(data_train.loc[(data_train['Pclass'] == 2),'Fare'] , color='r',shade=True, label='Pclass2',ax=ax2)
ax1.set_title('Fare特徵在Pclass下的箱型圖', fontsize = 18)
ax2.set_title("Fare特徵在Pclass下的kde圖", fontsize = 18)
fig.show()

結論:

觀察到Pclass1相對於2和3的Fare比較高,由於地位高,財富多。可是Pclass1中有幾個大於500的異常值存在,看一下這些異常數據。

df.loc[df['Fare']>500]

這些異常值中,有兩個名字同樣的Cardeza,又看到Parch都爲1,SibSp都爲0,Fare,Cabin,Embarked,Ticket都同樣,可推測二人是夫妻。 另外兩我的的Embarked,Ticket,Fare也都同樣,這說明這個大於500的Fare可能不是異常值。後面咱們會對這些進行特徵工程來特殊對待。

# Sex和Pclass狀況下Fare和Age的散點圖
grid = sns.FacetGrid(data_train, row='Sex', col='Pclass', hue='Survived', palette='seismic', size=3.5)
grid.map(plt.scatter, 'Age', 'Fare', alpha=0.8)
grid.add_legend()

g = sns.pairplot(data_train[[u'Survived', u'Pclass', u'Sex', u'Age', u'Parch', u'Fare', u'Embarked']], hue='Survived', palette = 'seismic',
                 size=4,diag_kind = 'kde',diag_kws=dict(shade=True),plot_kws=dict(s=50) )
g.set(xticklabels=[])

這是上述7個特徵的相互關聯圖的彙總,對角線爲特徵自身的kde分佈。對於不方即可視化的Name,Cabin,Ticket將在特徵工程中進一步進行處理並挖掘這些數據中到底有什麼信息是很是有價值的。

公衆號後臺回覆:泰坦尼克號,獲取源訓練集和測試集。下一篇將着重介紹特徵工程的內容,敬請期待。

關注微信公衆號:Python數據科學,查看更多精彩內容。

相關文章
相關標籤/搜索