Pandas 缺失值的處理
1. 前言
通過前面幾個小節(jié)的學(xué)習(xí),我們掌握了 Pandas 解析數(shù)據(jù)和數(shù)據(jù)增刪改查的基礎(chǔ)操作,能有效對數(shù)據(jù)的量和內(nèi)容進行處理,但我們在解析數(shù)據(jù)的時候經(jīng)常會出現(xiàn)缺失值的情況,這些缺失數(shù)據(jù)的存在不僅影響數(shù)據(jù)的美觀,還會影響到數(shù)據(jù)分析和挖掘的結(jié)果,那 Pandas 庫中又是怎么解決缺失值這一問題的呢?
針對數(shù)據(jù)中的缺失值,Pandas 庫提供了便捷的操作去檢查缺失值,并對缺失值作出處理,本小節(jié),我們將學(xué)習(xí) Pandas 檢測缺失值的方法,以及 Pandas 處理缺失值常見的兩種方式。
2. 缺失值的檢測
在學(xué)習(xí)進行缺失值處理之前,我們先來看一下什么是缺失值,為什么會出現(xiàn)缺失值?
缺失值 —— 是指粗糙數(shù)據(jù)中由于缺少信息而造成的數(shù)據(jù)的聚類、分組、刪失或截斷。它指的是現(xiàn)有數(shù)據(jù)集中某個或某些屬性的值是不完全的。(來源:百度百科)
缺失值的出現(xiàn)是很正常的一種現(xiàn)象,首先我們要正視缺失值的存在,缺失值的出現(xiàn)一般來說有機械原因和人為原因,但在我們實際應(yīng)用中,多說是我們?nèi)藶榈氖д`或錯誤的操作導(dǎo)致的缺失,缺失值的出現(xiàn)對于我們分析數(shù)據(jù)的過程不會產(chǎn)生過大的影響,但是對于數(shù)據(jù)分析的結(jié)果可能會產(chǎn)生致命的影響,影響數(shù)據(jù)的準(zhǔn)確性和結(jié)果的可靠性。
在 Pandas 中,對于缺失值使用浮點值 NaN 進行表示,如下圖我們將 Excel 數(shù)據(jù)文件中刪除幾個數(shù)據(jù)值,進行數(shù)據(jù)的解析:
然后我通過 Pandas 庫進行數(shù)據(jù)的解析,可以看到數(shù)據(jù)缺失值的表示 NaN:
2.1 isnull () 函數(shù)
該函數(shù)用來檢測缺失值,如果是缺失值 NaN 則數(shù)據(jù)返回的是 True,不是缺失值返回的是 False。
# 導(dǎo)入pandas包
import pandas as pd
data_path="C:/Users/13965/Documents/myFuture/IMOOC/pandasCourse-progress/data_source/第11小節(jié)/execl數(shù)據(jù)demo.xlsx"
# 解析數(shù)據(jù)
data = pd.read_excel(data_path)
print(data)
# --- 輸出結(jié)果 ---
編程語言 推出時間 價格 主要創(chuàng)始人
0 java NaN 45.6 James Gosling
1 python 1991年 67.0 NaN
2 NaN 1972年 NaN Dennis MacAlistair Ritchie
3 js NaN NaN Brendan Eich
4 php 2012年 NaN Rasmus Lerdorf
5 C++ 1983年 75.0 Bjarne Stroustrup
# 檢查是否是缺失值
data.isnull()
# --- 輸出結(jié)果 ---
編程語言 推出時間 價格 主要創(chuàng)始人
0 False True False False
1 False False False True
2 True False True False
3 False True True False
4 False False True False
5 False False False False
輸出解析:通過結(jié)果可以看到,是缺失值 NaN 的數(shù)據(jù),在該函數(shù)檢查后,都返回了 True,否則則是 False。
2.2 notnull () 函數(shù)
該函數(shù)也能檢測缺失值,但是和 isnull () 函數(shù)相反,對于缺失值 NaN 的數(shù)據(jù)返回 False,否則為 True。
# data 是上面從 Excel 中解析出來的數(shù)據(jù)
# 檢查是否不是缺失值
data.notnull()
# --- 輸出結(jié)果 ---
編程語言 推出時間 價格 主要創(chuàng)始人
0 True False True True
1 True True True False
2 False True False True
3 True False False True
4 True True False True
5 True True True True
輸出解析:通過結(jié)果可以看到,不是缺失值 NaN 的數(shù)據(jù),在該函數(shù)檢查后,都返回了 True,否則則是 False。
3. 缺失值的處理
Pandas 提供了便捷的方法去檢測缺失值,當(dāng)然他還提供了對應(yīng)的函數(shù)去處理缺失值,這里我們將學(xué)習(xí)缺失值的兩種處理方式,一種是過濾缺失值,也就對存在缺失值的行或者列,進行過濾操作;另一種是我們對缺失的數(shù)據(jù)進行填充處理。
3.1 dropna () 函數(shù)
該函數(shù)用于過濾含有缺失值的數(shù)據(jù)行或者列,操作之后會返回一個新的數(shù)據(jù)集,該函數(shù)提供了豐富的參數(shù)設(shè)置,下面列舉了該函數(shù)常用的幾個參數(shù):
參數(shù)名 | 說明 |
---|---|
axis | 指定是行還是列的過濾( 0 指行,1 為列),默認(rèn) axis=0 |
how | 指定缺失值過濾的依據(jù),含有缺失值就過濾(how=“any” 默認(rèn))還是全是全是缺失值才過濾(how=“all”) |
thresh | 指保留至少含有多少個非缺失值的行或列(參數(shù)值為整數(shù)) |
subset | 指定特定的行或者列進行缺失值過濾 |
下面我們將通過實際程序操作,學(xué)習(xí)每個參數(shù)的使用方式:
# 導(dǎo)入pandas包
import pandas as pd
data_path="C:/Users/13965/Documents/myFuture/IMOOC/pandasCourse-progress/data_source/第11小節(jié)/execl數(shù)據(jù)demo.xlsx"
# 解析數(shù)據(jù)
data = pd.read_excel(data_path)
print(data)
# --- 輸出結(jié)果 ---
編程語言 推出時間 價格 主要創(chuàng)始人
0 java NaN 45.6 James Gosling
1 python 1991年 67.0 NaN
2 NaN 1972年 NaN Dennis MacAlistair Ritchie
3 js NaN NaN Brendan Eich
4 php 2012年 NaN Rasmus Lerdorf
5 C++ 1983年 75.0 Bjarne Stroustrup
###### dropna 過濾缺失值
# 1. axis=0 設(shè)置過濾行中有缺失值的數(shù)據(jù)
new_data= data.dropna(axis=0)
print(new_data)
# --- 輸出結(jié)果 ---
編程語言 推出時間 價格 主要創(chuàng)始人
5 C++ 1983年 75.0 Bjarne Stroustrup
# 結(jié)果解析:可以看到所有含 NaN 的數(shù)據(jù)行都被過濾掉,只剩下一行數(shù)據(jù)
# 2. axis=1 設(shè)置過濾行列中缺失值的數(shù)據(jù)
new_data= data.dropna(axis=1)
print(new_data)
# --- 輸出結(jié)果 ---
Empty DataFrame
Columns: []
Index: [0, 1, 2, 3, 4, 5]
# 結(jié)果解析:因為原數(shù)據(jù)中每一列都有 NaN 數(shù)據(jù)的存在,所以 axis=1 操作后,數(shù)據(jù)集為 Empty DataFrame
# 3. how="all" 設(shè)置所有值都為 NaN 的數(shù)據(jù)列才被過濾
new_data= data.dropna(axis=1,how="all")
print(new_data)
# --- 輸出結(jié)果 ---
編程語言 推出時間 價格 主要創(chuàng)始人
0 java NaN 45.6 James Gosling
1 python 1991年 67.0 NaN
2 NaN 1972年 NaN Dennis MacAlistair Ritchie
3 js NaN NaN Brendan Eich
4 php 2012年 NaN Rasmus Lerdorf
5 C++ 1983年 75.0 Bjarne Stroustrup
# 結(jié)果解析:通過設(shè)置 how="all" 因為原數(shù)據(jù)不存在全為 NaN 的數(shù)據(jù)列,因此并沒有進行數(shù)據(jù)的過濾,輸出為原數(shù)據(jù)集
# 4. thresh=4 只保留含有4個及4個以上的非缺失值的數(shù)據(jù)
new_data= data.dropna(axis=1,thresh=4)
print(new_data)
# --- 輸出結(jié)果 ---
編程語言 推出時間 主要創(chuàng)始人
0 java NaN James Gosling
1 python 1991年 NaN
2 NaN 1972年 Dennis MacAlistair Ritchie
3 js NaN Brendan Eich
4 php 2012年 Rasmus Lerdorf
5 C++ 1983年 Bjarne Stroustrup
# 結(jié)果解析:因為"價格"這一列只有3個非缺失值的數(shù)據(jù),因此設(shè)置 thresh=4,會將該列過濾掉。
# 5. subset 指定要過濾的數(shù)據(jù)列
new_data= data.dropna(axis=0,subset=["價格","主要創(chuàng)始人"])
print(new_data)
# --- 輸出結(jié)果 ---
編程語言 推出時間 價格 主要創(chuàng)始人
0 java NaN 45.6 James Gosling
5 C++ 1983年 75.0 Bjarne Stroustrup
# 結(jié)果解析:這里通過 subset 指定過濾"價格""主要創(chuàng)始人"列中存在 NaN 數(shù)據(jù)的行,通過結(jié)果可以看到,過濾掉了行索引為1,2,3,4的行。
3.2 fillna () 函數(shù)
該函數(shù)用于填充缺失值的操作,返回一個新的數(shù)據(jù)集,該函數(shù)提供了豐富的參數(shù)可供設(shè)置,下面列舉了常用的幾個參數(shù):
參數(shù)名 | 說明 |
---|---|
value | 指定用什么值去填充 |
method | 填充的方式,ffill 用前一個非缺失值填充這個缺失值,bfill 用下一個非缺失值填充這個缺失值,None 默認(rèn)的,指定一個缺失值去填充 |
axis | 修改填充的方向 ,默認(rèn)是 axis=0 在列的方向填充 |
limit | 指定填充的個數(shù),在某個方向如果存在多個連續(xù)的缺失值,指定填充的幾個 |
下面通代碼程序來看一個每個參數(shù)的具體使用方式:
# 導(dǎo)入pandas包
import pandas as pd
data_path="C:/Users/13965/Documents/myFuture/IMOOC/pandasCourse-progress/data_source/第11小節(jié)/execl數(shù)據(jù)demo.xlsx"
# 解析數(shù)據(jù)
data = pd.read_excel(data_path)
print(data)
# --- 輸出結(jié)果 ---
編程語言 推出時間 價格 主要創(chuàng)始人
0 java NaN 45.6 James Gosling
1 python 1991年 67.0 NaN
2 NaN 1972年 NaN Dennis MacAlistair Ritchie
3 js NaN NaN Brendan Eich
4 php 2012年 NaN Rasmus Lerdorf
5 C++ 1983年 75.0 Bjarne Stroustrup
# 1. 直接設(shè)置 value 指定填充的內(nèi)容
new_data= data.fillna("###")
print(new_data)
# --- 輸出結(jié)果 ---
編程語言 推出時間 價格 主要創(chuàng)始人
0 java ### 45.6 James Gosling
1 python 1991年 67 ###
2 ### 1972年 ### Dennis MacAlistair Ritchie
3 js ### ### Brendan Eich
4 php 2012年 ### Rasmus Lerdorf
5 C++ 1983年 75 Bjarne Stroustrup
# 結(jié)果解析:通過設(shè)置填充的值為 ### ,可以看到原數(shù)據(jù)集中的缺失值都被填充了該字符
# 2. 設(shè)置 method 填充的方向
new_data= data.fillna(method="bfill")
print(new_data)
# --- 輸出結(jié)果 ---
編程語言 推出時間 價格 主要創(chuàng)始人
0 java 1991年 45.6 James Gosling
1 python 1991年 67.0 Dennis MacAlistair Ritchie
2 js 1972年 75.0 Dennis MacAlistair Ritchie
3 js 2012年 75.0 Brendan Eich
4 php 2012年 75.0 Rasmus Lerdorf
5 C++ 1983年 75.0 Bjarne Stroustrup
# 結(jié)果解析:這里設(shè)置了填充的方式為 bfill ,默認(rèn)的 axis=0 是在列上,表示用這一列的下一行的非缺失值填充這個缺失值,通過輸出結(jié)果可看到,缺失值均被填上了內(nèi)容,這里要注意一點,如果下一個數(shù)據(jù)為 NaN,則會繼續(xù)往下找,直到找到一個非缺失值的數(shù)據(jù)來填充。
# 3. 設(shè)置 axis=1 在橫向上進行填充
new_data= data.fillna(axis=1,method="bfill")
print(new_data)
# --- 輸出結(jié)果 ---
編程語言 推出時間 價格 主要創(chuàng)始人
0 java 45.6 45.6 James Gosling
1 python 1991年 67 NaN
2 1972年 1972年 Dennis MacAlistair Ritchie Dennis MacAlistair Ritchie
3 js Brendan Eich Brendan Eich Brendan Eich
4 php 2012年 Rasmus Lerdorf Rasmus Lerdorf
5 C++ 1983年 75 Bjarne Stroustrup
# 結(jié)果解析:這里程序中設(shè)置了 axis 為橫向,method 為 bfill ,通過輸出結(jié)果可以看到為 NaN 的數(shù)據(jù),用他后面的非缺失值進行了填充,如果他后面沒有數(shù)據(jù),則不進行填充,仍然為 NaN。
# 4. limit 指定出現(xiàn)連續(xù)的缺失值,填充的數(shù)量
new_data= data.fillna(axis=0,method="bfill",limit=2)
print(new_data)
# --- 輸出結(jié)果 ---
編程語言 推出時間 價格 主要創(chuàng)始人
0 java 1991年 45.6 James Gosling
1 python 1991年 67.0 Dennis MacAlistair Ritchie
2 js 1972年 NaN Dennis MacAlistair Ritchie
3 js 2012年 75.0 Brendan Eich
4 php 2012年 75.0 Rasmus Lerdorf
5 C++ 1983年 75.0 Bjarne Stroustrup
# 結(jié)果解析:通過設(shè)置 limit=2 指定出現(xiàn)連續(xù)的缺失值只填充2個數(shù)據(jù),這里可以看到在"價格"列中原數(shù)據(jù)出現(xiàn)的連續(xù)三個 NaN 這里按列的方向,只填充了兩個數(shù)據(jù)。
3. 小結(jié)
本節(jié)課程我們主要學(xué)習(xí)了 Pandas 檢測數(shù)據(jù)集中存在缺失值的方法,同時學(xué)習(xí)了 Pandas 對缺失值的過濾操作和填充缺失值的方法。本節(jié)課程的重點如下:
- isnull () 函數(shù)和 notnull () 函數(shù)對缺失值的檢測操作和檢測返回結(jié)果;
- dropna () 函數(shù)對缺失值的過濾操作,以及其中常用參數(shù)的設(shè)置方式;
- fillna () 函數(shù)對缺失值的填充操作,以及其中常用參數(shù)的設(shè)置方式。