作者:xiaoyu
微信公眾號:Python資料科學
知乎:python資料分析師
Kaggle作為公認的資料探勘競賽平臺,有很多公開的優秀專案,而其中作為初學者入門的一個好的專案就是:泰坦尼克號生還者預測。
可能這個專案好多朋友也聽說過,可能很多朋友也做過。但是專案完成後,是否有很好的反思總結呢?很多朋友只是潦草的敷衍過去了,知道大概的套路了就沒再去看。其實,一個再簡單的專案,如果把它做好也能有巨大的收穫。
博主開始做的時候,也是經過反覆琢磨和嘗試,並從最初的20%到最好的2%,期間學習了很多,不得不說這個專案讓我很好的瞭解了資料探勘。
本篇,博主將會從零開始介紹這個專案,教你如何一步一步的把這個
專案做好。由於大部分星球的朋友們已經完成了分析部分的實戰練習,因此將這部分內容拿出來進行簡單的分享。
專案介紹
首先對這個專案進行一下介紹。
資料探索
萬變不離其宗,拿到資料首先粗率的觀察。
"""
匯入資料
"""
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)
複製程式碼
將訓練集和測試集進行合併,以便後續資料內容變換的統一處理。
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(每個人名字都不一樣),或者Ticket和Cabin由於分類太多對於視覺化不是太方便,後續對這些特徵單獨分析。
因此,先對上面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資料科學,檢視更多精彩內容。