本次分享的項目來自 Kaggle 的經典賽題:泰坦尼克號生還者預測。分爲數據分析和數據挖掘兩部分介紹。本篇爲數據分析篇。html
RMS 泰坦尼克號的沉沒是歷史上最爲人熟知的海難事件之一。 1912 年 4 月 15 日,在她的處女航中,泰坦尼克號在與冰山相撞後沉沒,在船上的 2224 名乘客和機組人員中,共形成 1502 人死亡。這場聳人聽聞的悲劇震驚了國際社會,從而促進了船舶安全規定的完善。python
形成海難失事的緣由之一是乘客和機組人員沒有足夠的救生艇。儘管在沉船事件中倖存下有一些運氣因素,但有些人比其餘人更容易存活下來,好比女人,孩子和上流社會。安全
在這個挑戰中,要求完成哪些人可能存活下來的分析。特別的,要求運用機器學習工具來預測哪些乘客可以倖免於悲劇。app
PassengerId
,將其相應的Survived
變量預測爲值 0 或 1(這裏 1 表示倖存,0 表示遇難)。首先,導入數據:機器學習
data_train = pd.read_csv('train.csv') data_test = pd.read_csv('test.csv')
數據須要進行轉換可以做爲模型輸入。咱們對訓練集data_train
進行變換,一樣須要對測試集data_test
進行變換,保證模型輸入的一致性。工具
合併在一塊兒能夠進行統一變換,變換後再拆分。也可以使用以前沒有通過變換的data_train
。對數據集進行以下處理:學習
# 將目標變量 Survived 單獨提取,從特徵變量中移除目標變量 Survived df_target = data_train['Survived'] data_train_feature = data_train.drop(['Survived'], axis=1) # 合併 train 和 test 數據集,以方便數據處理對兩個數據集同時進行 df = data_train_feature.append(data_test)
合併後的數據集以下圖所示:測試
咱們看到,共有 11 個特徵:spa
以上就是對比賽和數據意義的解讀,下面咱們對數據進行探索,來達到最終目標。3d
特徵分析
咱們已經在上一步查看了有哪些特徵,接下來要作的是:
1. 查看哪些特徵存在缺失值
查看 train
和 test
合併後的數據:
df.info()
查看哪些特徵存在缺失值,缺失程度是否嚴重:
print(pd.isnull(df).sum())
能夠看出 age,cabin,embarked 和 Fare 四個特徵有缺失值,其中 cabin 的值缺失較嚴重。
2. 判斷哪些特徵存在異常值
對數值型特徵進行簡單的描述性統計,包括均值,中位數,標準差,最大值,最小值等,從而判斷哪些特徵存在異常值。
df.describe()
觀察上述值,其中 Age 的最小值爲 0.17,表示的應該是嬰兒的年齡,最大值爲 80,年齡有些偏大。Fare 表示船票價格,它的平均值爲 33.2,中位數 14,平均值比中位數大不少,說明該特徵分佈是嚴重的右偏,又有最大值約 512,因此這個值極可能是一個異常值。在 SibSp 和 Parch 中,Sibsp 最大值爲 8,有多是異常值,但 Parch 最大值也爲 9。這兩個特徵同時出現相近的較大的數值,而又由兩者所表示的含義,說明這個數值是有可能的,須要進一步的觀察。
由上所述,咱們看到了一些可能的異常值,但還不能肯定。須要咱們進一步經過可視化來清楚的顯示,並結合對業務的理解來肯定。
3. 判斷特徵的數據類型
根據以上對各個特徵數據類型的判斷,選擇合適的可視化方法完成可視化。經過可視化能夠:
4. 數據可視化分析
首先,定製畫布風格:
plt.style.use("bmh")
解決中文亂碼問題:
plt.rcParams['font.sans-serif'] = ['SimHei'] # 或者用 plt.rc('font', family='SimHei', size=13)
定類 / 定序特徵分析
cat_list = ['Pclass','Name','Sex','Embarked','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,Embarked 等可進行可視化分析。剩下特徵如 Ticket 和 Cabin 分類較多,進行可視化分析達不到想要效果,難以獲得有用的結論。
先對上面 3 種容易的分類進的特徵行可視化,而對於 Name,Ticket,Cabin 等到後續進行進一步分析。
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) plt.show()
經過分別觀察各特徵值的分佈狀況和與目標變量之間的關係,得出如下結論:
其中,Sex 和 Pclass 兩個特徵影響力較大。
以上是針對單獨特徵對生還與否的簡單分析,但在實際問題中,每每是由多個因素共同決定對目標變量的影響。所以,咱們須要知道在某個特定條件下的特徵的影響(如 Pclass 是 1 的狀況下男性和女性生還機率有何不一樣)才更加能幫助咱們分析,即在數據集的子集內可視化變量的分佈或多個變量之間的關係。這時就須要用到FacetGrid
子集數據。
在不一樣社會等級下,男性和女性在不一樣登錄港口下的數量對比:
grid = sns.FacetGrid(df, col='Pclass', hue='Sex', palette='seismic', size=4) grid.map(sns.countplot, 'Embarked', alpha=0.8) grid.add_legend()
觀察獲得:
定距/定比特徵分析
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特徵分佈', fontsize = 15) plt.xlabel("Age", fontsize = 15) plt.ylabel('Frequency', fontsize = 15)
根據 Age 特徵獲得不一樣性別生還與否的分佈:
def plot_distribution( df , var , target , **kwargs ): row = kwargs.get( 'row' , None ) col = kwargs.get( 'col' , None ) facet = sns.FacetGrid( df , hue=target , aspect=4 , row = row , col = col ) facet.map( sns.kdeplot , var , shade= True ) facet.set( xlim=( 0 , df[ var ].max() ) ) facet.add_legend()
plot_distribution( data_train , var = 'Age' , target = 'Survived' , row = 'Sex' )
總體觀察獲得,0 到十幾歲的孩子生還率最高,20 歲到 30 歲左右的生還率較低,其餘年齡段沒有太大的區別。而對於男性來講,0 到十幾歲的乘客生還率明顯較高,20 歲到 30 歲左右的生還率較低;而對女性來講,反而是 30 歲到 40 歲的年齡段生還率相對較高,0 到十幾歲生還率並不高,其它各年齡段的生還率沒有較大差異。
Fare 特徵:
# 填充缺失值 data_test["Fare"].fillna(data_test["Fare"].median(), inplace=True) data_train['Fare'] = data_train['Fare'].astype(int) data_test['Fare'] = data_test['Fare'].astype(int) # 分別得到生還和遇難乘客的 Fare fare_not_survived = data_train["Fare"][data_train["Survived"] == 0] fare_survived = data_train["Fare"][data_train["Survived"] == 1] # 獲得 Fare 的均值和方差 avgerage_fare = pd.DataFrame([fare_not_survived.mean(), fare_survived.mean()]) std_fare = pd.DataFrame([fare_not_survived.std(), fare_survived.std()]) data_train['Fare'].plot(kind='hist', figsize=(15,3),bins=100, xlim=(0,50)) avgerage_fare.index.names = std_fare.index.names = ["Survived"] avgerage_fare.plot(yerr=std_fare,kind='bar',legend=False)
容易觀察獲得 Fare 低的數量多,而 Fare 高的數量少,但生還率明顯要比 Fare 低的高不少。這也符合實際狀況,買得起高票價的有錢人居多,社會地位可能相對較高,更容易獲救。
SibSp 和 Parch 特徵:
data_train['Family'] = data_train["Parch"] + data_train["SibSp"] data_train['Family'].loc[data_train['Family'] > 0] = 1 data_train['Family'].loc[data_train['Family'] == 0] = 0 data_test['Family'] = data_test["Parch"] + data_test["SibSp"] data_test['Family'].loc[data_test['Family'] > 0] = 1 data_test['Family'].loc[data_test['Family'] == 0] = 0 # 刪除 Parch 和 SibSp data_train = data_train.drop(['SibSp','Parch'], axis=1) data_test = data_test.drop(['SibSp','Parch'], axis=1) # 繪圖 fig, (axis1,axis2) = plt.subplots(1,2,sharex=True,figsize=(10,5)) sns.countplot(x='Family', data=data_train, order=[1,0], ax=axis1) # 分爲和家人一塊兒、獨自乘船兩種狀況 family_perc = data_train[["Family", "Survived"]].groupby(['Family'],as_index=False).mean() sns.barplot(x='Family', y='Survived', data=family_perc, order=[1,0], ax=axis2) axis1.set_xticklabels(["With Family","Alone"], rotation=0)
咱們將 SibSp 和 Parch 這兩個特徵合併爲了一個 Family 特徵,表示該乘客是否有和家人一塊兒乘船,來判斷是否會增長生還率。
能夠明顯的看出獨自乘船的乘客人數大於和家人一塊兒的乘客人數,但倖存人數相對而言較少。
5. 總結
將上述 6 個特徵的相互關聯圖進行彙總,對角線爲特徵自身的 kde 分佈,以下圖所示:
g = sns.pairplot(data_train[[u'Survived', u'Pclass', u'Sex', u'Age', u'Family', 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=[])
數據分析部分就是這樣了,根據我的的不一樣理解還能夠有不少種不一樣的可視化方法,但最終目標都是爲了幫助咱們理解數據,進行挖掘分析。關於特徵工程和建模的部分將在下一篇的數據挖掘中來介紹。
參考連接:
【Kaggle入門級競賽top5%排名經驗分享】— 分析篇
樣式美化matplotlib.pyplot.style.use定製畫布風格
mac下python matplotlib中文亂碼解決方案
Seaborn(sns)官方文檔學習筆記(第六章 繪製數據網格)
不足之處,歡迎指正。