文科生學(xué)Python系列16:泰坦尼克數(shù)據(jù)2(缺失值處理)

第八課:案例分析 - 泰坦尼克數(shù)據(jù)

本節(jié)課將重點(diǎn)分析泰坦尼克號(hào)沉船事故,我們將探索是什么因素決定了最后是否生還

我們將將前面課程所學(xué)過(guò)的知識(shí)點(diǎn)融會(huì)貫通,舉一反三

新增知識(shí)點(diǎn):

? ? ? ?缺失值處理:pandas中的fillna()方法

? ? ? ?數(shù)據(jù)透視表:pandas中的pivot_table函數(shù)

我們上一篇文章用以前的知識(shí)將泰坦尼克案例的前面數(shù)據(jù)簡(jiǎn)單操作了一番,剩下的內(nèi)容會(huì)有新的知識(shí)點(diǎn),不知道一篇文章裝不裝得下,來(lái)了?。≌模?/p>


2、缺失值處理

真實(shí)數(shù)據(jù)往往某些變量會(huì)有缺失值。

首先,我們用 info( ) 語(yǔ)句操作,看到整份數(shù)據(jù)的大概情況:

titanic_df.info()

從這份數(shù)據(jù)我們可以發(fā)現(xiàn),這里一共有 891 行數(shù)據(jù),所以在中間那一列數(shù)據(jù)中看到的不是 891 個(gè)數(shù)據(jù)的,都是有缺失值的。比如年齡Age這一列,有714個(gè)非空數(shù)值,就有 891-714=177 個(gè)缺失值。又比如船艙號(hào)碼 cabin,缺失值就更多了。登船碼頭的缺失值比較少,后面可以不用處理。

這些缺失值是怎么處理的呢?一般是三種處理方法:不處理/丟棄/填充。

這里,cabin有超過(guò)70%以上的缺失值,我們可以考慮直接丟掉這個(gè)變量。 -- 刪除某一列數(shù)據(jù)

像Age這樣的重要變量,有20%左右的缺失值,我們可以考慮用中位值來(lái)填補(bǔ)。-- 填補(bǔ)缺失值

我們一般不提倡去掉帶有缺失值的行,因?yàn)槠渌侨笔У淖兞靠赡芴峁┯杏玫男畔ⅰ?- 刪除帶缺失值的行

刪除帶缺失值的行(一般不建議):df.dropna( )

刪除某一列:df.drop('column_name', axis=1, inplace=True)

填充缺失值:df.column_name.fillna( )

axis=1,代表刪除的是一列的數(shù)據(jù),也就是 column_name 這一列。inplace=True,表示在 df 這個(gè)原始數(shù)據(jù)上面進(jìn)行修改。

其實(shí)我們這節(jié)課重點(diǎn)的是最后一個(gè):填充缺失值。fill 是填充,na 是缺失值的代稱。

我們?cè)?info( ) 這個(gè)運(yùn)行中可以看到 Age 的缺失值不少,下面將使用中位數(shù)來(lái)填充 缺失值。


填補(bǔ)年齡數(shù)據(jù)中的缺失值

直接使用所有人年齡的中位數(shù)來(lái)填補(bǔ)

為了方便后面的比較,我們首先用 describe 統(tǒng)計(jì)數(shù)據(jù)。

查看Age列的統(tǒng)計(jì)值

這份數(shù)據(jù)照樣是可以看到,非缺失值 count 是有 714,平均值 mean 是 29.6歲,標(biāo)準(zhǔn)差 std 是 14.5,這時(shí)可以注意一下 50% ?那個(gè)數(shù)據(jù):28。

中位數(shù)

為了防止數(shù)據(jù)有改動(dòng),我們?cè)陂_(kāi)始之前需要重新載入數(shù)據(jù)。

正確的中位數(shù)可以使用 median 的方法獲取,得到的數(shù)和上面的 50% 的數(shù)是一樣的。

填充年齡缺失值

把中位數(shù)賦值給 age_median1,這個(gè)操作體現(xiàn)在第二行代碼。我的理解是,要是這里不重新賦值的話,后面需要用到這個(gè)中位數(shù)的時(shí)候,就需要完整碼出 titanic_df.Age.median( ) 這一句,重新賦值就可以直接使用 age_median1 來(lái)代替稍微長(zhǎng)一點(diǎn)的句子了。

titanic_df.Age.fillna(age_median1,inplace=True) 中,因?yàn)槭褂玫紸ge這列數(shù)據(jù),然后用 fillna 來(lái)實(shí)現(xiàn)填充,所以語(yǔ)句用 titanic_df.Age.fillna( ) 來(lái)表達(dá),括號(hào)里面需要填的參數(shù)就是需要填充的值,也就是里面的缺失值都是由剛剛賦值的 age_median1 來(lái)代替。逗號(hào)后面再加上inplace=True,表示在原來(lái)的 df 數(shù)據(jù)中進(jìn)行修改了,如果不加上這個(gè)參數(shù),就需要把填充后的值重新賦值給 Age 這一列,所以 inplace 這個(gè)動(dòng)作是為了簡(jiǎn)單起見(jiàn)。

再來(lái)看我們得到的結(jié)果,這個(gè)時(shí)候的非空缺失值已經(jīng)變成了891,平均值也從原本的29.7降到了29.4,因?yàn)槲覀儎倓偺畛涞闹形粩?shù)是28,比原來(lái)的平均值小,所以會(huì)有所新的平均值也會(huì)有所下降。

上面講的是所有人的年齡中位數(shù),現(xiàn)在我們進(jìn)一步來(lái)思考:性別因素,會(huì)怎么影響結(jié)果呢?


考慮性別因素,分別用男女乘客各自年齡的中位數(shù)來(lái)填補(bǔ)

由于上面的操作已經(jīng)對(duì)原始數(shù)據(jù)進(jìn)行修改了,所以要是我們需要重新分類,那就要重新載入原始數(shù)據(jù),不然后面的操作都會(huì)以上一步填充了所有年齡缺失值的基礎(chǔ)上操作的哦!這個(gè)虧我吃過(guò)。。。

性別的中位數(shù)

我們得到的女性中位數(shù)是 27,男性的是 29,還是有差距的吧!我們后面需要用到的是,用得出的中位數(shù)來(lái)填充男女的缺失值。

接下來(lái)的步驟,按照以前,通常的思路是用布爾型索引取到女性中缺失值的數(shù)據(jù),然后用 27 重新賦值;同理可求男性的操作。

但是我們這節(jié)課學(xué)了fillna 這個(gè)新的方法?。?/p>

不過(guò)剛剛我們使用 fillna 的時(shí)候,填充的只是一個(gè)數(shù)值,這里不止一個(gè)數(shù)值,就需要根據(jù)不同的情況來(lái)填充。此時(shí)可以用到 Pandas 中里的一個(gè)小技巧,Pandas 的值在運(yùn)算的過(guò)程中,會(huì)根據(jù)索引的值來(lái)進(jìn)行自動(dòng)的匹配。在這里我們可以看到這里的索引是 female 和 male 兩個(gè)值,如果原始數(shù)據(jù)也可以用性別來(lái)進(jìn)行索引的話,就可以用 fillna 自動(dòng)匹配相應(yīng)的索引形式進(jìn)行填充了。

fillna 進(jìn)行性別分類索引

所以這里要對(duì)原來(lái)的數(shù)值重新設(shè)置索引,一開(kāi)始是 0 1 2 這樣的數(shù)值,現(xiàn)在要把它設(shè)置成性別這一列數(shù)據(jù)。用 set_index 語(yǔ)句,用 Sex 來(lái)進(jìn)行索引,同時(shí)加入?yún)?shù) inplace=True,表示在原來(lái)的數(shù)據(jù)上進(jìn)行修改。

inplace=True的含義應(yīng)該講了第三遍了,其實(shí)我覺(jué)得要是不是很明白這個(gè)語(yǔ)句的用法時(shí),你可以先不加上這一句,跟著打代碼,然后到后面運(yùn)行的哪一步你發(fā)現(xiàn)和老師的代碼不一樣的時(shí)候,你就知道這個(gè)語(yǔ)句的重要性了。

我們可以看到這里的運(yùn)行結(jié)果 列索引變成了 Sex,列首索引是 male 和 female ,在行首 Sex 已經(jīng)不存在了。

填充性別分類的缺失值

我們將這里分類中位數(shù)賦值為 age_median2。填充的套路和上面也是一樣一樣的,根據(jù) Pandas 的自動(dòng)匹配,填充的時(shí)候會(huì)根據(jù)索引來(lái)匹配不同的值了。因?yàn)楹罄m(xù)需要用到 Sex 這一列,所以這里也需要重置索引,將索引變成它的列。這里使用 reset_index。

非空值是 891 時(shí)就說(shuō)明缺失值全部填充完畢了,這時(shí)候的均值是29.4。

所以到這里,我們把性別分類的缺失值也用各自的中位數(shù)填充完畢了。下一步要考慮的是,同時(shí)兩個(gè)因素的影響:


同時(shí)考慮性別和艙位因素

那我們首先來(lái)看一下,在不同年齡和不同艙位的中位數(shù),有什么變化呢?

groupby 分組的對(duì)象分別是 Pclass 艙位 和 Sex 性別,由于這里需要考量的有兩個(gè)因素:性別和艙位,所以這里需要使用到中括號(hào),后面加上用 Age.median 就可以得到分組的中位數(shù)了。

不同艙位男女年齡的中位數(shù)

這里就有兩個(gè)索引,分別是艙位和性別,我們可以看到,隨著艙位的下降,它的年齡也是在下降的。用我們的話理解就是,年輕人普遍比年長(zhǎng)的窮啊,年齡大一點(diǎn)的人積累的財(cái)富也多一點(diǎn)。

那接下來(lái)我們就用得出的中位數(shù)來(lái)各自重新賦值給艙位和性別。這時(shí)還是可以用 fillna 的,但是需要設(shè)置二重索引。

艙位和年齡的分類

套路還是一樣的,把這里得出的中位數(shù)賦值為 age_median3,然后對(duì)索引進(jìn)行重新的賦值,同樣的,這里有兩個(gè)因素,也是使用中括號(hào),用 set_index 的方法。

然后來(lái)看一下重置索引后的數(shù)據(jù)。看輸出我們是可以看到二重索引的,第一列的組合內(nèi)容一共有 3*2=6 種情況。在列上面,已經(jīng)沒(méi)有 Pclass 和 Sex 兩列數(shù)據(jù)了,因?yàn)榇丝趟鼈円呀?jīng)在索引上了。

現(xiàn)在按同樣的方法 fillna ,用索引值來(lái)匹配不同的中位數(shù)。

額。。。這兩張看起來(lái)和上面的一毛一樣啊,是我哪里錯(cuò)了嗎。。。?

為了還原這樣的索引,這里用 reset來(lái)重置

分類填充結(jié)果

這里的輸出可以看到非空數(shù)值已經(jīng)是891了,表示已經(jīng)填滿缺失值了。平均值下降到了29.1歲,因?yàn)槿扰摰娜藬?shù)比較多,而且年齡比較小,所以拉低了平均值。

我們總結(jié)一下,這里使用的 fillna 的方法,可以對(duì)總體的中位數(shù)進(jìn)行操作,或者分類之后對(duì)中位數(shù)進(jìn)行操作。分組之后由于有索引,所以同時(shí)也需要對(duì)原始數(shù)據(jù)進(jìn)行索引,對(duì)于相同索引值,可以用匹配來(lái)進(jìn)行填充。


在課堂答疑的時(shí)候,有同學(xué)問(wèn)為什么要用中位數(shù)來(lái)填充缺失值呢?

老師回答其實(shí)也是可以用平均值來(lái)填充的,這里的中位數(shù)和平均值相差不大,極端值不明顯。中位數(shù)在老師看來(lái)比較能夠表示人群的屬性,老師舉了我國(guó)的人均收入這個(gè)例子,是用均值還是中位數(shù)比較好呢?要是用均值的話,大家都在拖后腿了。。。

然后有同學(xué)問(wèn),設(shè)置索引有什么作用?

老師回答:設(shè)置索引有匹配的作用,在剛剛男性和女性的分類中,就可以通過(guò)男性的屬性來(lái)匹配男性的中位數(shù),女性的來(lái)匹配女性的中位數(shù)。通過(guò)第一個(gè)例子可以看到fillna 要是沒(méi)有索引的話,會(huì)給所有的數(shù)值都填充相同的一個(gè)值。


后面還有一大半內(nèi)容。。。老師說(shuō)了這節(jié)課是一個(gè)加量的全家桶,明天繼續(xù)更新后面的吧。。。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容