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