生日悖论分析python_Python数据分析养成记4——预测泰坦尼克号生存概率
一、提出問題
泰坦尼克號是當時世界上體積最龐大、內部設施最豪華的客運輪船,有“永不沉沒”的美譽 。然而不幸的是,在它的處女航中,泰坦尼克號便遭厄運。本文準備預測泰坦尼克號中乘客的生存概率。
二、理解數據
言歸正傳,首先登陸kaggle官網:Titanic: Machine Learning from Disaster?www.kaggle.com
該文中有項目的詳細介紹,在這里可下載后面學習需要的數據:
#導入處理數據包
import numpy as np
import pandas as pd
#導入數據
#訓練數據集
train = pd.read_csv("./train.csv")
#測試數據集
test = pd.read_csv("./test.csv")
#這里要記住訓練數據集有891條數據
print ('訓練數據集:',train.shape,'測試數據集:',test.shape)
訓練數據(train.csv,用于訓練模型)總共891行×12列數據,含存活率Survived。
測試數據(test.csv,用于檢驗模型的準確性)總共418行×11列數據,較訓練數據少了Survive
d列。
#合并數據集,方便同時對兩個數據集進行清洗
full = train.append( test , ignore_index = True )
#查看數據
full.head()
數據中,各個英文指標含義如下:
print ('合并后的數據集:',full.shape)
三、數據清洗
# 查看每一列的數據類型,和數據總數
full.info()
我們發現數據總共有1309行。
其中數據類型列:年齡(Age)、船艙號(Cabin)里面有缺失數據:
(1)年齡(Age)里面數據總數是1046條,缺失了1309-1046=263條數據
(2)船票價格(Fare)里面數據總數是1308條,缺失了1條數據
字符串列:
(1)登船港口(Embarked)里面數據總數是1307,只缺失了2條數據,缺失比較少
(2)船艙號(Cabin)里面數據總數是295,缺失了1309-295=1014,缺失比較大
這為我們下一步數據清洗指明了方向,只有知道哪些數據缺失數據,我們才能有針對性的處理。
1、數據預處理
(1)缺失值處理
在前文理解數據階段,我們發現數據總共有1309行。 其中數據類型列:年齡(Age)、船票價格(Fare)里面有缺失數據。 字符串列:登船港口(Embarked)、船艙號(Cabin)里面有缺失數據。
這為我們下一步數據清洗指明了方向。
缺失值如果是數值類型,用平均值取代(年齡、船票價格)
#年齡(Age)
full['Age']=full['Age'].fillna( full['Age'].mean() )
#船票價格(Fare)
full['Fare'] = full['Fare'].fillna( full['Fare'].mean() )
print('處理后:')
full.info()
缺失值如果是分類數據,用最常見的類別取代(登船港口、客艙等級)
#用最常見的登船港口S來取代
full['Embarked'] = full['Embarked'].fillna( 'S' )
#缺失數據比較多,船艙號(Cabin)缺失值填充為U,表示未知(Unknow)
full['Cabin'] = full['Cabin'].fillna( 'U' )
#檢查數據處理是否正常
full.head()
#查看最終缺失值處理情況,記住生成情況(Survived)這里一列是我們的標簽,用來做機器學習預測的,不需要處理這一列
full.info()
2、特征提取
查看數據類型,分為3種數據類型:
(1)數值類型:
乘客編號(PassengerId),年齡(Age),船票價格(Fare),同代直系親屬人數(SibSp),不同代直系親屬人數(Parch)
(2)時間序列:無
(3)分類數據:
a、有直接類別的
乘客性別(Sex):男性male,女性female
登船港口(Embarked):出發地點S=英國南安普頓Southampton,途徑地點1:C=法國 瑟堡市Cherbourg,出發地點2:Q=愛爾蘭 昆士敦Queenstown
客艙等級(Pclass):1=1等艙,2=2等艙,3=3等艙
b、字符串類型:可能從這里面提取出特征來,也歸到分類數據中
乘客姓名(Name)
客艙號(Cabin)
船票編號(Ticket)
性別處理
'''將性別的值映射為數值男(male)對應數值1,女(female)對應數值0'''
sex_mapDict={'male':1,
'female':0}
#map函數:對Series每個數據應用自定義的函數計算
full['Sex']=full['Sex'].map(sex_mapDict)
full.head()
登船港口(Embarked)
'''登船港口(Embarked)的值是:出發地點:S=英國南安普頓Southampton途徑地點1:C=法國 瑟堡市Cherbourg途徑地點2:Q=愛爾蘭 昆士敦Queenstown'''
embarkedDf = pd.DataFrame()
'''使用get_dummies進行one-hot編碼,產生虛擬變量(dummy variables),列名前綴是Embarked'''
embarkedDf = pd.get_dummies( full['Embarked'] , prefix='Embarked' )
#添加one-hot編碼產生的虛擬變量(dummy variables)到泰坦尼克號數據集full
full = pd.concat([full,embarkedDf],axis=1)
'''因為已經使用登船港口(Embarked)進行了one-hot編碼產生了它的虛擬變量(dummy variables)所以這里把登船港口(Embarked)刪掉'''
full.drop('Embarked',axis=1,inplace=True)
full.head()
客艙等級(Pclass)
'''客艙等級(Pclass):1=1等艙,2=2等艙,3=3等艙'''
#存放提取后的特征
pclassDf = pd.DataFrame()
#使用get_dummies進行one-hot編碼,列名前綴是Pclass
pclassDf = pd.get_dummies( full['Pclass'] , prefix='Pclass' )
#添加one-hot編碼產生的虛擬變量(dummy variables)到泰坦尼克號數據集full
full = pd.concat([full,pclassDf],axis=1)
#刪掉客艙等級(Pclass)這一列
full.drop('Pclass',axis=1,inplace=True)
full.head()部分摘錄
(3)分類數據:字符串類型
字符串類型:可能從這里面提取出特征來,也歸到分類數據中,這里數據有:乘客姓名(Name)、客艙號(Cabin)、船票編號(Ticket)
從姓名中提取頭銜
'''注意到在乘客名字(Name)中,有一個非常顯著的特點:乘客頭銜每個名字當中都包含了具體的稱謂或者說是頭銜,將這部分信息提取出來后可以作為非常有用一個新變量,可以幫助我們進行預測。例如:Braund, Mr. Owen HarrisHeikkinen, Miss. LainaOliva y Ocana, Dona. FerminaPeter, Master. Michael J練習從字符串中提取頭銜,例如Mrsplit用于字符串分割,返回一個列表我們看到姓名中'Braund, Mr. Owen Harris',逗號前面的是“名”,逗號后面是‘頭銜. 姓’name1='Braund, Mr. Owen Harris'split用于字符串按分隔符分割,返回一個列表。這里按逗號分隔字符串也就是字符串'Braund, Mr. Owen Harris'被按分隔符,'拆分成兩部分[Braund,Mr. Owen Harris]你可以把返回的列表打印出來瞧瞧,這里獲取到列表中元素序號為1的元素,也就是獲取到頭銜所在的那部分,即Mr. Owen Harris這部分Mr. Owen Harrisstr1=name1.split( ',' )[1]str2=str1.split( '.' )[0]#strip() 方法用于移除字符串頭尾指定的字符(默認為空格)str3=str2.strip()'''
'''定義函數:從姓名中獲取頭銜'''
def getTitle(name):
str1=name.split( ',' )[1] #Mr. Owen Harris
str2=str1.split( '.' )[0]#Mr
#strip() 方法用于移除字符串頭尾指定的字符(默認為空格)
str3=str2.strip()
return str3
#存放提取后的特征
titleDf = pd.DataFrame()
#map函數:對Series每個數據應用自定義的函數計算
titleDf['Title'] = full['Name'].map(getTitle)
titleDf.head()
'''定義以下幾種頭銜類別:Officer政府官員Royalty王室(皇室)Mr已婚男士Mrs已婚婦女Miss年輕未婚女子Master有技能的人/教師'''
#姓名中頭銜字符串與定義頭銜類別的映射關系
title_mapDict = {
"Capt": "Officer",
"Col": "Officer",
"Major": "Officer",
"Jonkheer": "Royalty",
"Don": "Royalty",
"Sir" : "Royalty",
"Dr": "Officer",
"Rev": "Officer",
"the Countess":"Royalty",
"Dona": "Royalty",
"Mme": "Mrs",
"Mlle": "Miss",
"Ms": "Mrs",
"Mr" : "Mr",
"Mrs" : "Mrs",
"Miss" : "Miss",
"Master" : "Master",
"Lady" : "Royalty"
}
#map函數:對Series每個數據應用自定義的函數計算
titleDf['Title'] = titleDf['Title'].map(title_mapDict)
#使用get_dummies進行one-hot編碼
titleDf = pd.get_dummies(titleDf['Title'])
titleDf.head()
#添加one-hot編碼產生的虛擬變量(dummy variables)到泰坦尼克號數據集full
full = pd.concat([full,titleDf],axis=1)
#刪掉姓名這一列
full.drop('Name',axis=1,inplace=True)
從客艙號中提取客艙類別
'''補充知識:匿名函數python 使用 lambda 來創建匿名函數。所謂匿名,意即不再使用 def 語句這樣標準的形式定義一個函數,預防如下:lambda 參數1,參數2:函數體或者表達式# 定義匿名函數:對兩個數相加sum = lambda a,b: a + b# 調用sum函數print ("相加后的值為 : ", sum(10,20))'''
#客艙號的首字母是客艙的類別
#查看客艙號的內容
full['Cabin'].head()
#存放客艙號信息
cabinDf = pd.DataFrame()
'''客場號的類別值是首字母,例如:C85 類別映射為首字母C'''
full[ 'Cabin' ] = full[ 'Cabin' ].map( lambda c : c[0] )
##使用get_dummies進行one-hot編碼,列名前綴是Cabin
cabinDf = pd.get_dummies( full['Cabin'] , prefix = 'Cabin' )
cabinDf.head()
#添加one-hot編碼產生的虛擬變量(dummy variables)到泰坦尼克號數據集full
full = pd.concat([full,cabinDf],axis=1)
#刪掉客艙號這一列
full.drop('Cabin',axis=1,inplace=True)
full.head()
建立家庭人數和家庭類別
#存放家庭信息
familyDf = pd.DataFrame()
'''家庭人數=同代直系親屬數(Parch)+不同代直系親屬數(SibSp)+乘客自己(因為乘客自己也是家庭成員的一個,所以這里加1)'''
familyDf[ 'FamilySize' ] = full[ 'Parch' ] + full[ 'SibSp' ] + 1
'''家庭類別:小家庭Family_Single:家庭人數=1中等家庭Family_Small: 2<=家庭人數<=4大家庭Family_Large: 家庭人數>=5'''
#if 條件為真的時候返回if前面內容,否則返回0
familyDf[ 'Family_Single' ] = familyDf[ 'FamilySize' ].map( lambda s : 1 if s == 1 else 0 )
familyDf[ 'Family_Small' ] = familyDf[ 'FamilySize' ].map( lambda s : 1 if 2 <= s <= 4 else 0 )
familyDf[ 'Family_Large' ] = familyDf[ 'FamilySize' ].map( lambda s : 1 if 5 <= s else 0 )
#添加one-hot編碼產生的虛擬變量(dummy variables)到泰坦尼克號數據集full
full = pd.concat([full,familyDf],axis=1)
#到現在我們已經有了這么多個特征了
full.shape
(1309, 33)
3、特征選擇
相關系數法:計算各個特征的相關系數
#相關性矩陣
corrDf = full.corr()
'''查看各個特征與生成情況(Survived)的相關系數,ascending=False表示按降序排列'''
corrDf['Survived'].sort_values(ascending =False)
根據各個特征與生成情況(Survived)的相關系數大小,我們選擇了這幾個特征作為模型的輸入:頭銜(前面所在的數據集titleDf)、客艙等級(pclassDf)、家庭大小(familyDf)、船票價格(Fare)、船艙號(cabinDf)、登船港口(embarkedDf)、性別(Sex)
#特征選擇
full_X = pd.concat( [titleDf,#頭銜
pclassDf,#客艙等級
familyDf,#家庭大小
full['Fare'],#船票價格
cabinDf,#船艙號
embarkedDf,#登船港口
full['Sex']#性別
] , axis=1 )
full_X.shape
(5,27)
四、數據建模
1、建立訓練數據集和測試數據集
'''1)我們將Kaggle泰坦尼克號項目給我們的測試數據,叫做預測數據集(記為pred,也就是預測英文單詞predict的縮寫)。也就是我們使用機器學習模型來對其生存情況就那些預測。2)我們使用Kaggle泰坦尼克號項目給的訓練數據集,做為我們的原始數據集(記為source),從這個原始數據集中拆分出訓練數據集(記為train:用于模型訓練)和測試數據集(記為test:用于模型評估)。'''
#原始數據集有891行
sourceRow=891
'''sourceRow是我們在最開始合并數據前知道的,原始數據集有總共有891條數據從特征集合full_X中提取原始數據集提取前891行數據時,我們要減去1,因為行號是從0開始的。'''
#原始數據集:特征
source_X = full_X.loc[0:sourceRow-1,:]
#原始數據集:標簽
source_y = full.loc[0:sourceRow-1,'Survived']
#預測數據集:特征
pred_X = full_X.loc[sourceRow:,:]
'''從原始數據集(source)中拆分出訓練數據集(用于模型訓練train),測試數據集(用于模型評估test)train_test_split是交叉驗證中常用的函數,功能是從樣本中隨機的按比例選取train data和test data'''
from sklearn.model_selection import train_test_split
#建立模型用的訓練數據集和測試數據集
train_X, test_X, train_y, test_y = train_test_split(source_X ,
source_y,
train_size=.8,
test_size=.2)
#輸出數據集大小
print ('原始數據集特征:',source_X.shape,
'訓練數據集特征:',train_X.shape ,
'測試數據集特征:',test_X.shape)
print ('原始數據集標簽:',source_y.shape,
'訓練數據集標簽:',train_y.shape ,
'測試數據集標簽:',test_y.shape)
2、選擇機器學習算法
本文采用邏輯回歸法。
#第1步:導入算法
from sklearn.linear_model import LogisticRegression
#第2步:創建模型:邏輯回歸(logisic regression)
model = LogisticRegression()
#第3步:訓練模型
model.fit( train_X , train_y )
# 分類問題,score得到的是模型的正確率
model.score(test_X , test_y )
0.84357541899441346
五、模型預測
#使用機器學習模型,對預測數據集中的生存情況進行預測
pred_Y = model.predict(pred_X)
#乘客id
passenger_id = full.loc[sourceRow:,'PassengerId']
#數據框:乘客id,預測生存情況的值
predDf = pd.DataFrame(
{ 'PassengerId': passenger_id ,
'Survived': pred_Y } )
predDf.shape
predDf.head()
#保存結果
predDf.to_csv( 'titanic_pred.csv' , index = False )
這樣模型預測結果就輸出到文件 titanic_pred.csv 中,可提交至Kaggle查看預測結果的準確率。
六、小結
1、解決問題前,先不急于動手,先想清楚問題的整體解決思路。
2、文中不盡詳解之處,可對照《利用Python進行數據分析》第7章進行查看?!独肞ython進行數據分析·第2版》第1章 準備工作?www.jianshu.com
3、多思考,多復盤,多敲代碼。
總結
以上是生活随笔為你收集整理的生日悖论分析python_Python数据分析养成记4——预测泰坦尼克号生存概率的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Panabit存在命令执行漏洞
- 下一篇: PCI驱动程序实现