網站首頁 編程語言 正文
今天分享一篇pandas缺失值處理的操作指南!
一、缺失值類型
在pandas
中,缺失數據顯示為NaN。缺失值有3種表示方法,np.nan
,none
,pd.NA
。
1、np.nan
缺失值有個特點(坑),它不等于任何值,連自己都不相等。如果用nan
和任何其它值比較都會返回nan
。
np.nan?==?np.nan >>?False
也正由于這個特點,在數據集讀入以后,不論列是什么類型的數據,默認的缺失值全為np.nan
。
因為nan
在Numpy
中的類型是浮點,因此整型列會轉為浮點;而字符型由于無法轉化為浮點型,只能歸并為object類型('O'),原來是浮點型的則類型不變。
type(np.nan) >>?float
pd.Series([1,2,3]).dtype >>?dtype('int64') pd.Series([1,np.nan,3]).dtype >>?dtype('float64')
初學者做數據處理遇見object類型會發懵,不知道這是個啥,明明是字符型,導入后就變了,其實是因為缺失值導致的。
除此之外,還要介紹一種針對時間序列的缺失值,它是單獨存在的,用NaT表示,是pandas
的內置類型,可以視為時間序列版的np.nan
,也是與自己不相等。
s_time?=?pd.Series([pd.Timestamp('20220101')]*3) s_time >>?0?2022-01-01 ???1?2022-01-01 ???2?2022-01-01 ???dtype:datetime64[ns] ----------------- s_time[2]?=?pd.NaT s_time >>?0?2022-01-01 ???1?2022-01-01 ???2?NaT ???dtype:datetime64[ns]
2、None
還有一種就是None
,它要比nan
好那么一點,因為它至少自己與自己相等。
None?==?None >>?True
在傳入數值類型后,會自動變為np.nan
。
type(pd.Series([1,None])[1]) >>?numpy.float64
只有當傳入object
類型時是不變的,因此可以認為如果不是人工命名為None
的話,它基本不會自動出現在pandas
中,所以None
大家基本也看不到。
type(pd.Series([1,None],dtype='O')[1]) >>?NoneType
3、NA標量
pandas1.0以后的版本中引入了一個專門表示缺失值的標量pd.NA,它代表空整數、空布爾值、空字符,這個功能目前處于實驗階段。
開發者也注意到了這點,對于不同數據類型采取不同的缺失值表示會很亂。pd.NA就是為了統一而存在的。pd.NA的目標是提供一個缺失值指示器,可以在各種數據類型中一致使用(而不是np.nan、None或者NaT分情況使用)。
s_new?=?pd.Series([1,?2],?dtype="Int64") s_new >>?0???1 ???1???2 ???dtype:?Int64 ----------------- s_new[1]?=?pd.NaT s_new >>?0????1 ???1??<NA> ???dtype:?Int64
同理,對于布爾型、字符型一樣不會改變原有數據類型,這樣就解決了原來動不動就變成object
類型的麻煩了。
下面是pd.NA的一些常用算術運算和比較運算的示例:
#####?算術運算 #?加法 pd.NA?+?1 >>?<NA> ----------- #?乘法 "a"?*?pd.NA >>?<NA> ----------- #?以下兩種其中結果為1 pd.NA?**?0 >>?1 ----------- 1?**?pd.NA >>?1 #####?比較運算 pd.NA?==?pd.NA >>?<NA> ----------- pd.NA?<?2.5 >>?<NA> ----------- np.log(pd.NA) >>?<NA> ----------- np.add(pd.NA,?1) >>?<NA>
二、缺失值判斷
了解了缺失值的幾種形式后,我們要知道如何判斷缺失值。對于一個dataframe
而言,判斷缺失的主要方法就是isnull()
或者isna()
,這兩個方法會直接返回True
和False
的布爾值。可以是對整個dataframe
或者某個列。
df?=?pd.DataFrame({ ??????'A':['a1','a1','a2','a3'], ??????'B':['b1',None,'b2','b3'], ??????'C':[1,2,3,4], ??????'D':[5,None,9,10]}) #?將無窮設置為缺失值?????? pd.options.mode.use_inf_as_na?=?True
1、對整個dataframe判斷缺失
df.isnull() >>?A?B?C?D 0?False?False?False?False 1?False?True?False?True 2?False?False?False?False 3?False?False?False?False
2、對某個列判斷缺失
df['C'].isnull() >>?0????False ???1????False ???2????False ???3????False Name:?C,?dtype:?bool
如果想取非缺失可以用notna()
,使用方法是一樣的,結果相反。
三、缺失值統計
1、列缺失
一般我們會對一個dataframe
的列進行缺失統計,查看每個列有多少缺失,如果缺失率過高再進行刪除或者插值等操作。那么直接在上面的isnull()
返回的結果上直接應用.sum()
即可,axis
默認等于0,0是列,1是行。
##?列缺失統計 isnull().sum(axis=0)
2、行缺失
但是很多情況下,我們也需要對行進行缺失值判斷。比如一行數據可能一個值都沒有,如果這個樣本進入模型,會造成很大的干擾。因此,行列兩個缺失率通常都要查看并統計。
操作很簡單,只需要在sum()
中設置axis=1
即可。
##?行缺失統計 isnull().sum(axis=1)
3、缺失率
有時我不僅想要知道缺失的數量,我更想知道缺失的比例,即缺失率。正常可能會想到用上面求得數值再比上總行數。但其實這里有個小技巧可以一步就實現。
##?缺失率 df.isnull().sum(axis=0)/df.shape[0] ##?缺失率(一步到位) isnull().mean()
四、缺失值篩選
篩選需要loc配合完成,對于行和列的缺失篩選如下:
#?篩選有缺失值的行 df.loc[df.isnull().any(1)] >>?A?B?C?D 1?a1?None?2?NaN ----------------- #?篩選有缺失值的列 df.loc[:,df.isnull().any()] >>?B?D 0?b1?5.0 1?None?NaN 2?b2?9.0 3?b3?10.0
如果要查詢沒有缺失值的行和列,可以對表達式用取反~
操作:
df.loc[~(df.isnull().any(1))] >>?A?B?C?D 0?a1?b1?1?5.0 2?a2?b2?3?9.0 3?a3?b3?4?10.0
上面使用了any
判斷只要有缺失就進行篩選,也可以用all
判斷是否全部缺失,同樣可以對行里進行判斷,如果整列或者整行都是缺失值,那么這個變量或者樣本就失去了分析的意義,可以考慮刪除。
五、缺失值填充
一般我們對缺失值有兩種處理方法,一種是直接刪除,另外一種是保留并填充。下面先介紹填充的方法fillna
。
#?將dataframe所有缺失值填充為0 df.fillna(0) >>?A?B?C?D 0?a1?b1?1?5.0 1?a1?0?2?0.0 2?a2?b2?3?9.0 3?a3?b3?4?10.0 -------------- #?將D列缺失值填充為-999 df.D.fillna('-999') >>?0???????5 ???1????-999 ???2???????9 ???3??????10 Name:?D,?dtype:?object
方法很簡單,但使用時需要注意一些參數。
inplace:可以設置
fillna(0, inplace=True)
來讓填充生效,原dataFrame被填充。methond:可以設置
methond
方法來實現向前或者向后填充,pad/ffill
為向前填充,bfill/backfill
為向后填充,比如df.fillna(methond='ffill')
,也可以簡寫為df.ffill()
。
df.ffill() >>?A?B?C?D 0?a1?b1?1?5.0 1?a1?b1?2?5.0 2?a2?b2?3?9.0 3?a3?b3?4?10.0
原缺失值都會按照前一個值來填充(B列1行,D列1行)。
除了用前后值來填充,也可以用整個列的均值來填充,比如對D列的其它非缺失值的平均值8來填充缺失值。
df.D.fillna(df.D.mean()) >>?0?????5.0 ???1?????8.0 ???2?????9.0 ???3????10.0 Name:?D,?dtype:?float64
六、缺失值刪除
刪除缺失值也非情況,比如是全刪除還是刪除比較高缺失率,這個要看自己的容忍程度,真實的數據必然會存在缺失的,這個無法避免。而且缺失在某些情況下也代表了一定的含義,要視情況而定。
1、全部直接刪除
#?全部直接刪除 df.dropna() >>?A?B?C?D 0?a1?b1?1?5.0 2?a2?b2?3?9.0 3?a3?b3?4?10.0
2、行缺失刪除
#?行缺失刪除 df.dropna(axis=0) >>?A?B?C?D 0?a1?b1?1?5.0 2?a2?b2?3?9.0 3?a3?b3?4?10.0
3、列缺失刪除
#?列缺失刪除 df.dropna(axis=1) >>?A?C 0?a1?1 1?a1?2 2?a2?3 3?a3?4 ------------- #?刪除指定列范圍內的缺失,因為C列無缺失,所以最后沒有變化 df.dropna(subset=['C']) >>?A?B?C?D 0?a1?b1?1?5.0 1?a1?None?2?NaN 2?a2?b2?3?9.0 3?a3?b3?4?10.0
4、按缺失率刪除
這個可以考慮用篩選的方法來實現,比如要刪除列缺失大于0.1的(即篩選小于0.1的)。
df.loc[:,df.isnull().mean(axis=0)?<?0.1] >>?A?C 0?a1?1 1?a1?2 2?a2?3 3?a3?4 ------------- #?刪除行缺失大于0.1的 df.loc[df.isnull().mean(axis=1)?<?0.1] >>?A?B?C?D 0?a1?b1?1?5.0 2?a2?b2?3?9.0 3?a3?b3?4?10.0
七、缺失值參與計算
如果不對缺失值處理,那么缺失值會按照什么邏輯進行計算呢?
下面我們一起看一下各種運算下缺失值的參與邏輯。
1、加法
df >>A?B?C?D 0?a1?b1?1?5.0 1?a1?None?2?NaN 2?a2?b2?3?9.0 3?a3?b3?4?10.0 --------------- #?對所有列求和 df.sum() >>?A????a1a1a2a3 ???C??????????10 ???D??????????24
可以看到,加法是會忽略缺失值的。
2、累加
#?對D列進行累加 df.D.cumsum() >>?0?????5.0 ???1?????NaN ???2????14.0 ???3????24.0 Name:?D,?dtype:?float64 --------------- df.D.cumsum(skipna=False) >>?0????5.0 ???1????NaN ???2????NaN ???3????NaN Name:?D,?dtype:?float64
cumsum
累加會忽略NA,但值會保留在列中,可以使用skipna=False
跳過有缺失值的計算并返回缺失值。
3、計數
#?對列計數 df.count() >>?A????4 ???B????3 ???C????4 ???D????3 dtype:?int64
缺失值不進入計數范圍里。
4、聚合分組
df.groupby('B').sum() >>?C?D B?? b1?1?5.0 b2?3?9.0 b3?4?10.0 --------------- df.groupby('B',dropna=False).sum() >>?C?D B?? b1?1?5.0 b2?3?9.0 b3?4?10.0 NaN?2?0.0
聚合時會默認忽略缺失值,如果要缺失值計入到分組里,可以設置dropna=False
。這個用法和其它比如value_counts
是一樣的,有的時候需要看缺失值的數量。
五、源碼
所有數據和代碼可在我的GitHub
獲取:
原文鏈接:https://mp.weixin.qq.com/s/tFD8CrsCd5O7cLyxxbSKdg
相關推薦
- 2022-08-10 讀取Go項目中的配置文件的方法_Golang
- 2022-12-07 python?yield迭代器詳解_python
- 2022-04-11 MVVMLight項目之雙向數據綁定_Android
- 2023-11-22 fatal: unable to access ‘https://github.com/xxxxx/
- 2022-04-26 Entity?Framework?Core實現Like查詢詳解_實用技巧
- 2022-06-01 關于nginx?反向代理?URL替換方案_nginx
- 2023-07-04 Guava 之 EventBus
- 2022-10-08 React中useState的使用方法及注意事項_React
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支