這個(gè)項(xiàng)目是kaggle上的練手項(xiàng)目袱蚓,實(shí)踐方面是參考于csdn上一位大佬的總結(jié)枚碗,自己對(duì)其進(jìn)行了實(shí)現(xiàn)和理解逾一,主要是為了解整個(gè)項(xiàng)目操作的流程,并且肮雨,由于篇幅過長遵堵,所以會(huì)分為兩部分記錄
數(shù)據(jù)導(dǎo)入
import re
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import warnings
warnings.filterwarnings('ignore')
- 注:這里加入
import warnings
warnings.filterwarnings('ignore')
主要就是為了美觀,如果不加的話怨规,warning一堆堆的陌宿,不怎么整潔
#導(dǎo)入數(shù)據(jù)
train_data = pd.read_csv('C:/Users/Youngy/Desktop/Titanic_dataset/train.csv')
test_data = pd.read_csv('C:/Users/Youngy/Desktop/Titanic_dataset/test.csv')
#查看前幾行的源數(shù)據(jù)
sns.set_style('whitegrid')#設(shè)定圖表的主題,其中whitegrid的主題比較簡(jiǎn)潔
train_data.head()
#查看所有的數(shù)據(jù)信息概況
train_data.info()
test_data.info()
- 看過數(shù)據(jù)的概況后椅亚,可以發(fā)現(xiàn)限番,訓(xùn)練集中的Age舱污,Cabin呀舔,Embarked,測(cè)試集中的Fare是有缺失值的
#繪制存活的比例
train_data['Survived'].value_counts().plot.pie(autopct = '%1.2f%%')
缺失值處理
- 如果數(shù)據(jù)集很大扩灯,缺失值只占極小的一部分媚赖,可以直接刪掉帶有缺失值的行
- 如果該特征對(duì)模型的學(xué)習(xí)來說不是很重要,則可以對(duì)缺失值填充均值or眾數(shù)珠插;比如‘在哪兒登船’的這個(gè)特征共有三個(gè)登船的地點(diǎn)惧磺,總的數(shù)據(jù)是891,而該特征是889捻撑,缺失兩個(gè)數(shù)值磨隘,就可以直接使用眾數(shù)進(jìn)行填充
#眾數(shù)
train_data.Embarked.dropna().mode().values
#將眾數(shù)賦值到源數(shù)據(jù)中
train_data.Embarked[train_data.Embarked.isnull()] = train_data.Embarked.dropna().mode().values
-
mode
是眾數(shù)缤底,train_data.Embarked.dropna()
是表示對(duì)刪去缺失值后的數(shù)據(jù),再加個(gè)mode
則表示刪去缺失值后番捂,數(shù)據(jù)的眾數(shù) - 對(duì)于標(biāo)稱屬性个唧,我們可以賦予一個(gè)代表缺失的值,比如‘U0’设预;因?yàn)槿笔П旧硪部赡艽碇恍╇[含信息徙歼,比如船艙號(hào)Cabin這個(gè)特征,缺失可能表示代表其沒有船艙鳖枕,也是有意義的
- 注:標(biāo)稱屬性(nominal attribute)意味著‘與名稱相關(guān)’魄梯,它的值是一些符號(hào)或事物的名稱。每個(gè)值代表某種類別宾符,編碼或狀態(tài)酿秸,因此標(biāo)稱屬性又被看作是分類的(categorical)
train_data['Cabin'] = train_data.Cabin.fillna('U0')
- 使用線性回歸、隨機(jī)森林等模型來預(yù)測(cè)缺失屬性的值吸奴;比如:Age是一個(gè)非常重要的特征允扇,我們需要保證缺失值填充的準(zhǔn)確率,這是非常重要的
- 一般來說则奥,會(huì)采用數(shù)據(jù)較完整的條目作為模型的訓(xùn)練集考润,以此來預(yù)測(cè)缺失值
#采用隨機(jī)森林來預(yù)測(cè)
from sklearn.ensemble import RandomForestRegressor
age_df = train_data[['Age','Survived','Fare', 'Parch', 'SibSp', 'Pclass']]#提取數(shù)據(jù)
age_df_notnull = age_df.loc[(train_data['Age'].notnull())]#訓(xùn)練集
age_df_isnull = age_df.loc[(train_data['Age'].isnull())]#測(cè)試集(即需要進(jìn)行缺失值填充的數(shù)據(jù))
X = age_df_notnull.values[:,1:]#訓(xùn)練集的輸入X
y = age_df_notnull.values[:,0]#訓(xùn)練集的輸出標(biāo)簽y
RFR = RandomForestRegressor(n_estimators=1000,n_jobs=-1)#調(diào)用隨機(jī)森林,進(jìn)行訓(xùn)練模型
RFR.fit(X,y)
predictAges = RFR.predict(age_df_isnull.values[:,1:])#預(yù)測(cè)
train_data.loc[train_data['Age'].isnull(),['Age']] = predictAges#將預(yù)測(cè)的結(jié)果賦值到源數(shù)據(jù)中
- 注意這種操作的順序读处,提取notnull和isnull別搞錯(cuò)了就行
- 對(duì)Series進(jìn)行切片糊治,一定要指定特征后加個(gè)values再進(jìn)行,不然會(huì)報(bào)錯(cuò)
#查看缺失值處理后的結(jié)果
train_data.info()
分析數(shù)據(jù)關(guān)系
分析數(shù)據(jù)之間的關(guān)系罚舱,也就是分析特征與特征之間的關(guān)系井辜,下面我們依次分析
性別與是否生存的關(guān)系
- 利用
groupy().count()
將sex和survived的數(shù)據(jù)統(tǒng)計(jì)出來
train_data.groupby(['Sex','Survived'])['Survived'].count()
train_data[['Sex','Survived']].groupby(['Sex']).mean().plot.bar()
train_data[['Sex','Survived']].groupby(['Sex']).mean()
Survived
Sex
female 0.742038
male 0.188908
- 而
train_data[['Sex','Survived']].groupby(['Survived']).mean()
并不可以統(tǒng)計(jì),原因是sex中的數(shù)據(jù)都是非數(shù)字(經(jīng)驗(yàn)證管闷,利用replace改成數(shù)字后就可以統(tǒng)計(jì)了)
除此之外粥脚,似乎pandas中的篩選數(shù)據(jù)的操作只能針對(duì)數(shù)字型的數(shù)據(jù),eg:a[a.Survived > 0]
才可以包个,a.Survived=0
和sex='male'
都不可以
基于以上的圖表刷允,可以發(fā)現(xiàn)這里性別之中,女性的生存率更高碧囊,所以有相當(dāng)大的關(guān)系
船艙等級(jí)和生存與否的關(guān)系
train_data.groupby(['Pclass','Survived'])['Pclass'].count()
train_data[['Pclass','Survived']].groupby(['Pclass']).mean().plot.bar()
- 這里的
mean
到底計(jì)算的是什么呢树灶?- 其實(shí)前面的
count
是統(tǒng)計(jì)總的量,而這里的mean
是要計(jì)算全部非NA量的平均值糯而,也就是Survived
屬性中的所有值都加在一起天通,然后除以這個(gè)屬性的值個(gè)數(shù),即
- 其實(shí)前面的
train_data[['Sex','Pclass','Survived']].groupby(['Pclass','Sex']).mean().plot.bar()
train_data.groupby(['Sex','Pclass','Survived'])['Survived'].count()
由上面的圖表可以看出熄驼,雖然每種船艙里都體現(xiàn)著女性優(yōu)先像寒,但最終烘豹,生存的情況和船艙等級(jí)有密不可分的聯(lián)系
年齡與存活與否的關(guān)系
fig,axes = plt.subplots(1,2,figsize = (10,5))
sns.violinplot(x = 'Pclass' , y = 'Age' , hue = 'Survived' , data = train_data , split = True , ax = axes[0])
axes[0].set_title('Pclass and Age vs Survived')
axes[0].set_yticks(range(0,110,10))
sns.violinplot(x = 'Sex' , y = 'Age' , hue = 'Survived' , data = train_data , split = True , ax = axes[1])
axes[1].set_title('Sex and Age vs Survived')
axes[1].set_yticks(range(0,110,10))
plt.show()
- 在寫這里時(shí)出了個(gè)問題,就是會(huì)顯示
matplotlib
里沒有subplots
屬性诺祸,這里是因?yàn)榍懊嬖趯?dǎo)入包的時(shí)候吴叶,導(dǎo)入的是import matplotlib as plt
,其實(shí)只要導(dǎo)入import matplotlib.pyplot as plt
就可以了
# 我們先用直方圖和箱線圖看一下所有人的年齡分布
plt.figure(figsize=(10,5))
plt.subplot(121)
train_data['Age'].hist(bins = 70)
plt.xlabel('Age')
plt.ylabel('Num')
plt.subplot(122)
train_data.boxplot(column='Age',showfliers=False)
plt.show()
-
plt.subplot(121)
表示一行兩列的圖像序臂,最后一個(gè)1表示顯示第一個(gè)位置
bins
是直方圖中的分類粒度大小蚌卤,值越大越細(xì)
showfliers
表示是否顯示異常值,而默認(rèn)是顯示的奥秆,所以這里showfliers = False
是讓箱線圖不顯示異常值
# 看一下不同年齡段的生存與否的分布情況
facet= sns.FacetGrid(train_data,hue = 'Survived',aspect=3)#aspect是關(guān)于圖像大小的參數(shù)
facet.map(sns.kdeplot,'Age',shade=True)
facet.set(xlim=(0,train_data['Age'].max()))
facet.add_legend()
-
FacetGrid
對(duì)象用于生成plot的網(wǎng)格布局逊彭,當(dāng)網(wǎng)格創(chuàng)建完畢后,可以使用FacetGrid
的map
方法來指定plot類型和需要繪制的屬性-
hue='Survived'
是分類參數(shù)构订,也可以使用col='Survived'
設(shè)定條件將數(shù)據(jù)分為多個(gè)子集侮叮,另外,aspect
是設(shè)置圖像大小的參數(shù) -
sns.kdeplot
是核密度曲線(Kernel Density Plot)悼瘾,其中shade=True
是顯示曲線的面積囊榜,可以方便觀察
-
# 再觀察一下不同年齡下的平均生存率
fig,axes1 = plt.subplots(1,1,figsize=(10,5))
train_data['Age_int'] = train_data['Age'].astype(int)#源數(shù)據(jù)里的Age是float64,現(xiàn)在轉(zhuǎn)換為int32亥宿,并且作為一個(gè)新的特征加入源數(shù)據(jù)
#做一個(gè)數(shù)據(jù)的聚合卸勺,將平均值mean的數(shù)值作為Survived屬性的新數(shù)據(jù),然后將Age_int和Survived特征放到新的數(shù)據(jù)集average_age中
average_age = train_data[['Age_int','Survived']].groupby(['Age_int'],as_index = False).mean()
sns.barplot(x='Age_int',y='Survived',data=average_age)
- 上面是先轉(zhuǎn)換數(shù)據(jù)烫扼,作為一個(gè)新特征加入源數(shù)據(jù)曙求,然后篩選屬性,做一個(gè)數(shù)據(jù)的聚合映企,將平均值mean的數(shù)值作為Survived屬性的新數(shù)據(jù)悟狱,然后將Age_int和Survived特征放到新的數(shù)據(jù)集average_age中
- 其中,
as_index=False
是保留原先的0~891的數(shù)字索引堰氓,而如果as_index=True
(該參數(shù)默認(rèn)為True),列Age_int會(huì)被默認(rèn)為索引列挤渐,新的dataframe中不再包含這列數(shù)據(jù)
- 其中,
# 觀察年齡統(tǒng)計(jì)
train_data['Age'].describe()
- 樣本有891,平均年齡約為30歲双絮,標(biāo)準(zhǔn)差13.5歲浴麻,最小年齡為0.42,最大年齡80.
- 根據(jù)年齡統(tǒng)計(jì)掷邦,我們可以將乘客劃分為兒童白胀,青少年椭赋,成年和老年抚岗,并進(jìn)一步分析四個(gè)群體的生還情況
bins = [0,12,18,65,100]
train_data['Age_group']= pd.cut(train_data['Age'],bins)
by_age = train_data.groupby('Age_group')['Survived'].mean()
by_age
-
pd.cut
是pandas自身的函數(shù),其可以對(duì)連續(xù)型變量進(jìn)行分類匯總- 其中哪怔,我們對(duì)
(0,12)
這樣的區(qū)間段可以加上label
eg:train_data['Age_group']= pd.cut(train_data['Age'],bins宣蔚,label=['兒童','青少年','成年','老年'])
- 其中哪怔,我們對(duì)
by_age.plot(kind = 'bar')
乘客姓名與存活與否的關(guān)系
train_data['Name'].head(5)
- 通過觀察名字?jǐn)?shù)據(jù)向抢,我們可以看出其中包括對(duì)乘客的稱呼,如:Mr胚委、Miss挟鸠、Mrs等,稱呼信息包含了乘客的年齡亩冬、性別艘希,同時(shí)也包含了如社會(huì)地位等的稱呼,如:Dr,硅急、Lady覆享、Major、Master等的稱呼
train_data['Title'] = test_data['Name'].str.extract(' ([A-Za-z]+)\.', expand=False)
pd.crosstab(train_data['Title'],train_data['Sex'])
- 這里是將姓名中的稱呼用字符串str的
str.extract()
函數(shù)+正則表達(dá)式提取出來营袜,然后利用交叉表crosstab將Title中的數(shù)據(jù)用sex特征進(jìn)行統(tǒng)計(jì)- 注1:注意書寫格式:要提取的部分正則表達(dá)式要用引號(hào)引起來撒顿。抽取多個(gè)數(shù)字或者字母的話要在后面加上'+'
- 注2:加入之后的數(shù)據(jù)并不是數(shù)值格式的(屬于字符串格式的),因此不能跟正常的數(shù)值一樣進(jìn)行運(yùn)算荚板,需要計(jì)算的時(shí)候要進(jìn)行格式的轉(zhuǎn)換
-
train_data['Title'].astype(float)
轉(zhuǎn)換為浮點(diǎn)型 -
train_data['Title'] = train_data['Title'].map(lambda x:float(x))
也可以用map和匿名函數(shù)轉(zhuǎn)換格式
-
- 注3:
.str
的功能是可以使用切片器的凤壁,eg:train_data['Title'].str[:7]
train_data[['Title','Survived']].groupby(['Title']).mean().plot.bar()[圖片上傳中...(image.png-cfdce2-1552632604968-0)]
fig,axis1 = plt.subplots(1,1,figsize = (10,5))
train_data['Name_length'] = train_data['Name'].apply(len)
name_length = train_data[['Name_length','Survived']].groupby(['Name_length'],as_index=False).mean()
sns.barplot(x='Name_length',y='Survived',data=name_length)
在計(jì)算名字的長度時(shí),我們用到了
pandas.apply
函數(shù)跪另,這個(gè)函數(shù)是所有函數(shù)中自由度最高的函數(shù)
-
DataFrame.apply(func, axis=0, broadcast=False, raw=False, reduce=None, args=(), **kwds)
-
func
是函數(shù)拧抖,相當(dāng)于c里的函數(shù)指針,而這個(gè)函數(shù)需要自己去實(shí)現(xiàn)免绿,因?yàn)楹瘮?shù)的傳入?yún)?shù)是根據(jù)axis
來確定的徙鱼,比如設(shè)置axis=1
,則會(huì)把一行的數(shù)據(jù)作為Series
的數(shù)據(jù)結(jié)構(gòu)傳入這個(gè)函數(shù)中针姿,此時(shí)我們可以在這個(gè)函數(shù)中實(shí)現(xiàn)對(duì)Series
的不同屬性之間的數(shù)值計(jì)算袱吆,并返回一個(gè)結(jié)果,而apply
函數(shù)則會(huì)自動(dòng)遍歷每一行的DataFrame
的數(shù)據(jù)距淫,最后將所有結(jié)果組合成一個(gè)Series
數(shù)據(jù)結(jié)構(gòu)返回;如果設(shè)置默認(rèn)绞绒,即axis=1
,則依然會(huì)一行一行的將數(shù)值參數(shù)傳入函數(shù)中榕暇,比如x+9
的簡(jiǎn)單函數(shù)蓬衡,如果傳入的數(shù)據(jù)中,一行有兩個(gè)屬性彤枢,則每個(gè)屬性值都會(huì)+9
狰晚,結(jié)果會(huì)返回一個(gè)所有數(shù)值都+9
的DateFrame
- 如果我們想給自己實(shí)現(xiàn)的函數(shù)傳遞參數(shù),就可以用的apply函數(shù)的
*args
和**kwds
參數(shù)缴啡,比如:func
的傳入?yún)?shù)是兩個(gè)壁晒,而DataFrame
只有一個(gè)數(shù)值,我們則可以用*args
和**kwds
參數(shù)傳入func
中
-
有無兄弟姐妹和存活與否的關(guān)系
# 我們先將數(shù)據(jù)分為有兄弟姐妹和沒兄弟姐妹兩組
sibsp_df = train_data[train_data['SibSp']!=0]
np_sibsp_df = train_data[train_data['SibSp']==0]
#再對(duì)兩組數(shù)據(jù)進(jìn)行可視化
plt.figure(figsize = (10,5))
plt.subplot(121)
sibsp_df['Survived'].value_counts().plot.pie(labels=['No Survived','Survived'],autopct= '%1.1f%%')
plt.xlabel('sibsp')
plt.subplot(122)
sibsp_df['Survived'].value_counts().plot.pie(labels=['No Survived','Survived'],autopct= '%1.1f%%')
plt.xlabel('no_sibsp')
plt.show()
有無父母子女和存活與否的關(guān)系
parch_df = train_data[train_data['Parch']!=0]
no_parch_df = train_data[train_data['Parch']==0]
plt.figure(figsize=(10,5))
plt.subplot(121)
parch_df['Survived'].value_counts().plot.pie(labels=['No Survived','Survived'],autopct= '%1.1f%%')
plt.xlabel('parch')
plt.subplot(122)
no_parch_df['Survived'].value_counts().plot.pie(labels=['No Survived','Survived'],autopct= '%1.1f%%')
plt.xlabel('no_parch')
plt.show()
親友的人數(shù)和存活與否的關(guān)系 SibSp & Parch
# 先看一下有兄弟姐妹业栅、有父母這兩個(gè)屬性與存活之間的數(shù)據(jù)統(tǒng)計(jì)
fig,ax=plt.subplots(1,2,figsize=(10,5))
train_data[['Parch','Survived']].groupby(['Parch']).mean().plot.bar(ax=ax[0])
ax[0].set_title('Parch and Survived')
train_data[['SibSp','Survived']].groupby(['SibSp']).mean().plot.bar(ax=ax[1])
ax[1].set_title('SibSp and Survived')
# 再看一下SibSp & Parch在一起后與存活之間的關(guān)系
train_data['Family_Size'] = train_data['Parch'] + train_data['SibSp'] + 1
train_data[['Family_Size','Survived']].groupby(['Family_Size']).mean().plot.bar()
- 從圖表中可以看出秒咐,若獨(dú)自一人谬晕,那么其存活率比較低;但是如果親友太多的話携取,存活率也會(huì)很低
票價(jià)分布和存活與否的關(guān)系 Fare
fig,axes = plt.subplots(1,2,figsize = (10,5))
train_data['Fare'].hist(bins=70,ax = axes[0])
train_data.boxplot(column='Fare',by='Pclass',showfliers=False,ax = axes[1])
plt.show()
train_data['Fare'].describe()
#繪制生存與否與票價(jià)均值和方差的關(guān)系
fare_not_survived = train_data['Fare'][train_data['Survived']==0]
fare_survived = train_data['Fare'][train_data['Survived']==1]
average_fare= pd.DataFrame([fare_not_survived.mean(),fare_survived.mean()])
std_fare = pd.DataFrame([fare_not_survived.std(),fare_survived.std()])
average_fare.plot(yerr=std_fare,kind='bar',legend=False)
plt.show()
- 其中攒钳,參數(shù)
yerr
是y error的簡(jiǎn)稱,可以畫出y的偏差雷滋,所以我們?cè)谶@里傳入了yerr=std_fare
船艙類型和存活與否的關(guān)系 Cabin
- 由于船艙的缺失值確實(shí)太多不撑,有效值僅僅有204個(gè),很難分析出不同的船艙和存活的關(guān)系晤斩,所以在做特征工程的時(shí)候燎孟,可以直接將該組特征丟棄
- 當(dāng)然,這里我們也可以對(duì)其進(jìn)行一下分析尸昧,將缺失的數(shù)據(jù)都分為一類揩页。
進(jìn)一步,我們可以簡(jiǎn)單地將數(shù)據(jù)分為是否有Cabin記錄來作為一個(gè)新的特征烹俗,讓其與生存與否進(jìn)行分析
#加入一個(gè)新的特征‘Has_Cabin’
train_data.loc[train_data.Cabin.isnull(),'Cabin'] = 'U0'
train_data['Has_Cabin'] = train_data['Cabin'].apply(lambda x: 0 if x=='U0' else 1)
train_data[['Has_Cabin','Survived']].groupby(['Has_Cabin']).mean().plot.bar()
#接著對(duì)不同類型的船艙進(jìn)行分析
train_data['CabinLetter'] = train_data['Cabin'].map(lambda x : re.compile('([a-zA-Z]+)').search(x).group())
train_data['CabinLetter'] = pd.factorize(train_data['CabinLetter'])[0]
train_data[['CabinLetter','Survived']].groupby(['CabinLetter']).mean().plot.bar()
可見爆侣,不同的船艙生存率也有不同,但是差別不大幢妄。所以在處理中兔仰,我們可以直接將特征刪除
港口和存活與否的關(guān)系 Embarked
- 泰坦尼克號(hào)從英國的南安普頓港出發(fā),途徑法國瑟堡和愛爾蘭昆士敦蕉鸳,那么在昆士敦之前上船的人乎赴,有可能在瑟堡或昆士敦下船,這些人將不會(huì)遇到海難
sns.countplot('Embarked',hue = 'Survived',data = train_data)
plt.title('Embarked and Survived')
sns.factorplot('Embarked','Survived',data=train_data,size=3,aspect=2)
plt.title('Embarked and survived rate')
- 由上可以看出潮尝,在不同的港口上船榕吼,生還率不同,C最高勉失,Q次之羹蚣,S最低
- 據(jù)了解,泰坦尼克號(hào)上共有2224名乘客乱凿。本訓(xùn)練數(shù)據(jù)只給出了891名乘客的信息顽素,如果該數(shù)據(jù)集是從總共的2224人中隨機(jī)選出的,根據(jù)中心極限定理徒蟆,該樣本的數(shù)據(jù)也足夠大胁出,那么我們的分析結(jié)果就具有代表性;但如果不是隨機(jī)選取段审,那么我們的分析結(jié)果就可能不太靠譜了全蝶。
其他可能和存活與否有關(guān)系的特征
- 對(duì)于數(shù)據(jù)集中沒有給出的特征信息,我們還可以聯(lián)想其他可能會(huì)對(duì)模型產(chǎn)生影響的特征因素。如:乘客的國籍裸诽、乘客的身高、乘客的體重型凳、乘客是否會(huì)游泳丈冬、乘客職業(yè)等等。
- 另外還有數(shù)據(jù)集中沒有分析的幾個(gè)特征:Ticket(船票號(hào))甘畅、Cabin(船艙號(hào)),這些因素的不同可能會(huì)影響乘客在船中的位置從而影響逃生的順序埂蕊。但是船艙號(hào)數(shù)據(jù)缺失,船票號(hào)類別大疏唾,難以分析規(guī)律蓄氧,所以在后期模型融合的時(shí)候,將這些因素交由模型來決定其重要性
變量轉(zhuǎn)換
- 變量轉(zhuǎn)換的目的是將數(shù)據(jù)轉(zhuǎn)換為適用于模型使用的數(shù)據(jù)槐脏,不同模型接受不同類型的數(shù)據(jù)喉童,Scikit-learn要求數(shù)據(jù)都是數(shù)字型numeric,所以我們要將一些非數(shù)字型的原始數(shù)據(jù)轉(zhuǎn)換為數(shù)字型numeric
- 所有的數(shù)據(jù)可以分為兩類:
- 定量(Quantitative)變量可以以某種方式排序顿天,Age就是一個(gè)很好的列子堂氯。
- 定性(Qualitative)變量描述了物體的某一(不能被數(shù)學(xué)表示的)方面,Embarked就是一個(gè)例子牌废。
定性轉(zhuǎn)換
Dummy Variables
- 定性變量的數(shù)據(jù)咽白,例如性別、民族等鸟缕,由于定性變量通常表示的是某種特征的有和無晶框,所以量化方法可采用取值為0,1懂从,2授段,3....等。這種變量稱作虛擬變量(Dummy Variable)番甩,用D表示畴蒲。它的作用是使定性數(shù)據(jù)能包括在統(tǒng)計(jì)模型中
- 當(dāng)qualitative variable(定性變量)是一些頻繁出現(xiàn)的幾個(gè)獨(dú)立變量時(shí),Dummy Variables比較適合使用对室。我們以Embarked為例模燥,Embarked只包含三個(gè)值’S’,‘C’,‘Q’,我們可以使用下面的代碼將其轉(zhuǎn)換為dummies
embark_dummies = pd.get_dummies(train_data['Embarked'])
train_data = train_data.join(embark_dummies)
train_data.drop(['Embarked'],axis=1,inplace=True)
-
get_dummies
是pandas里的一個(gè)函數(shù)掩宜,可以用來對(duì)定性變量進(jìn)行one-hot編碼
然后將編碼后的數(shù)據(jù)連接到源數(shù)據(jù)中,同時(shí)又刪去了‘Embarked’特征
embark_dummies = train_data[['S','C','Q']]
embark_dummies.head()
Factorizing
- dummy不好處理Cabin(船艙號(hào))這種標(biāo)稱屬性蔫骂,因?yàn)樗霈F(xiàn)的變量比較多。所以Pandas有一個(gè)方法叫做factorize()牺汤,它可以創(chuàng)建一些數(shù)字辽旋,來表示類別變量,對(duì)每一個(gè)類別映射一個(gè)ID,這種映射最后只生成一個(gè)特征补胚,不像dummy那樣生成多個(gè)特征
- 疑問:這樣的話會(huì)不會(huì)造成有序呢码耐?就是會(huì)不會(huì)出現(xiàn)one-hot編碼之前想去避免的情況呢
train_data['Cabin'][train_data.Cabin.isnull()] = 'U0'
train_data['CabinLetter'] = train_data['Cabin'].map(lambda x : re.compile("([a-zA-Z]+)").search(x).group())
train_data['CabinLetter'] = pd.factorize(train_data['CabinLetter'])[0]
train_data['CabinLetter'].head()
定量(Quantitative)轉(zhuǎn)換
scaling縮放
- Scaling可以將一個(gè)很大范圍的數(shù)值映射到一個(gè)很小的范圍(通常是-1 - 1,或則是0 - 1)溶其,很多情況下我們需要將數(shù)值做Scaling使其范圍大小一樣骚腥,否則大范圍數(shù)值特征將會(huì)由更高的權(quán)重。比如:Age的范圍可能只是0-100瓶逃,而income的范圍可能是0-10000000束铭,在某些對(duì)數(shù)組大小敏感的模型中會(huì)影響其結(jié)果
#對(duì)Age進(jìn)行縮放
from sklearn import preprocessing
assert np.size(train_data['Age']) == 891
scaler = preprocessing.StandardScaler()
train_data['Age_scaled'] = scaler.fit_transform(train_data['Age'].values.reshape(-1,1))
train_data['Age_scaled'].head()
Binning
- Binning通過觀察“鄰居”(即周圍的值)將連續(xù)數(shù)據(jù)離散化。存儲(chǔ)的值被分布到一些“桶”或“箱“”中厢绝,就像直方圖的bin將數(shù)據(jù)劃分成幾塊一樣契沫。下面的代碼對(duì)Fare進(jìn)行Binning
train_data['Fare_bin'] = pd.qcut(train_data['Fare'],5)
train_data['Fare_bin'].head()
pd.qcut
是根據(jù)這些值的頻率來選擇箱子的均勻間隔,即每個(gè)箱子中含有的數(shù)的數(shù)量是相同的pd.cut
將根據(jù)值本身來選擇箱子均勻間隔昔汉,即每個(gè)箱子的間距都是相同的
- 在將數(shù)據(jù)Bining化后懈万,要么將數(shù)據(jù)factorize化,要么dummies化
#factorize化
train_data['Fare_bin_id'] = pd.factorize(train_data['Fare_bin'])[0]
#dummies化
fare_bin_dummies_df = pd.get_dummies(train_data['Fare_bin']).rename(columns=lambda x: 'Fare_' + str(x))
train_data = pd.concat([train_data, fare_bin_dummies_df], axis=1)