資料科學庫pandas筆記3
缺失資料的處理
1. 缺失資料的表現
對於一些資料,可能某些值是空的,是缺失的。pandas中可以有多種處理缺失資料的方式。在pandas中,缺失資料的表現是NaN(Not a Number)
,可以使用isnull()
函式檢測出是否有資料缺失。
In [4]: data = pd.Series(['aaa','bbb',np.nan,'ddd']) In [5]: data Out[5]: 0aaa 1bbb 2NaN 3ddd dtype: object In [6]: data.isnull() Out[6]: 0False 1False 2True 3False dtype: bool
isnull返回一個布林型的物件,這些布林值表示哪些值是缺失值NaN,該物件返回的型別和原型別一樣。
處理缺失資料的方式有多種,常見為刪除缺失資料與填充缺失資料。
2. 丟棄缺失資料
pandas的dropna方法可以有效的刪除掉缺失資料,對於Series來說,dropna方法返回一個僅含非空資料和索引值的Series:
In [7]: data Out[7]: 0aaa 1bbb 2NaN 3ddd dtype: object In [8]: data.dropna() Out[8]: 0aaa 1bbb 3ddd dtype: object
對於DataFrame,dropna可以刪除所有含有空值的行或列,也可以根據個人刪除指定的行或列,dropna預設會刪除所有含有NaN的行:
In [17]: df Out[17]: nameage area 0aa18北京 1NaN18廣州 2cc20NaN In [18]: df.dropna() Out[18]: nameage area 0aa18北京
傳入how='all',那麼dropna只會刪除一行全是缺失值的行:
In [19]: df.loc[3]=[np.nan,np.nan,np.nan] In [20]: df Out[20]: nameage area 0aa18.0北京 1NaN18.0廣州 2cc20.0NaN 3NaNNaNNaN In [21]: df.dropna(how='all') Out[21]: nameage area 0aa18.0北京 1NaN18.0廣州 2cc20.0NaN
如果要刪除有缺失值的一列,只需要傳入axis=1:
In [25]: df['avg'] = [20,30,40,50] In [26]: df Out[26]: nameage areaavg 0aa18.0北京20 1NaN18.0廣州30 2cc20.0NaN40 3NaNNaNNaN50 In [27]: df.dropna(axis=1) Out[27]: avg 020 130 240 350
同樣,dropna(axis=1,how='all')
只會刪除整列都是缺失值的那一列。
如果想留下部分含有缺失值的資料作為觀察,或者說只想刪除部分資料,那麼就需要使用thresh引數了,保留至少有n個非NaN資料的行/列:
In [52]: df Out[52]: nameage areaavg 0aa18.0北京20 # 這一行4個值都不是NaN值,非NaN值為4 1NaN18.0廣州30 # 有1個NaN值,非NaN值為3 2cc20.0NaN40 # 有1個NaN值,非NaN值為3 3NaNNaNNaN50 # 有3個NaN值,非NaN值為1 In [53]: df.dropna(thresh=4) # 選取非空值至少有4個的行 Out[53]: nameage areaavg 0aa18.0北京20 In [54]: df.dropna(thresh=2) Out[54]: nameage areaavg 0aa18.0北京20 1NaN18.0廣州30 2cc20.0NaN40 In [55]: df.dropna(thresh=4,axis=1) # 選取非空值至少有4個的列 Out[55]: avg 020 130 240 350
3. 填充缺失資料
對於缺失資料不想丟棄而想填充新的資料,fillna()
方法也許是首要選擇。通過一個常數呼叫fillna就會將缺失值替換為那個常數值:
In [62]: df Out[62]: nameage areaavg 0aa18.0北京20 1NaN18.0廣州30 2cc20.0NaN40 3NaNNaNNaN50 In [64]: df.fillna(0) Out[64]: nameage areaavg 0aa18.0北京20 1018.0廣州30 2cc20.0040 300.0050
若是通過一個字典呼叫fillna,就可以實現對不同的列填充不同的值:
In [61]: df.fillna({'name':'dd','age':22,'area':'深圳'}) Out[61]: nameage areaavg 0aa18.0北京20 1dd18.0廣州30 2cc20.0深圳40 3dd22.0深圳50
fillna預設會返回新物件,但也可以對現有物件進行就地修改:
In [65]: df.fillna(0,inplace=True) In [66]: df Out[66]: nameage areaavg 0aa18.0北京20 1018.0廣州30 2cc20.0040 300.0050
資料去重
資料中也有可能出現多行資料重複的情況,DataFrame的duplicated方法返回一個布林型的物件,表示各行是否是重複的行,它每次都會對比前面出現的行,如果出現與前面出現的行一樣的行,那麼這一行就是重複行:
In [68]: data Out[68]: k1k2 0one1 1two1 2one2 3two3 4one3 5two4 6two4 # 這一行與前一行重複,由於這一行在第5行後,所以會被判斷為重複行 In [69]: data.duplicated() Out[69]: 0False 1False 2False 3False 4False 5False 6True dtype: bool
而drop_duplicates方法
,它會返回一個DataFrame,重複的陣列會標為False並且刪除:
In [70]: data.drop_duplicates() Out[70]: k1k2 0one1 1two1 2one2 3two3 4one3 5two4
上面兩個方法預設會判斷全部列,如果只想根據一列進行重複值判斷,可以傳入包含列索引的列表:
In [75]: data Out[75]: k1k2v1 0one10 1two11 2one22 3two33 4one34 5two45 6two46 In [76]: data.drop_duplicates(['k1']) Out[76]: k1k2v1 0one10 1two11
duplicated和drop_duplicates預設保留的是第一個出現的值組合。傳入keep='last'則保留最後一個:
In [51]: data.drop_duplicates(['k1', 'k2'], keep='last') Out[51]: k1k2v1 0one10 1two11 2one22 3two33 4one34 6two46
資料替換
有的時候需求是將資料框的某個值替換掉,pandas提供了replace方法,注意它與字串的replace方法不一樣。
pandas的replace方法操作的物件是DataFrame的值。
In [83]: data Out[83]: age name 0-20小明 120老王 223蘋果 In [84]: data.replace(-20,0) # 將-20替換為0 Out[84]: age name 00小明 120老王 223蘋果
如果要讓替換值有不同的值,要傳入一個列表
In [88]: data.replace(['小明','老王'],['獼猴桃','西瓜']) Out[88]: age name 0-20獼猴桃 120西瓜 223蘋果
替換多個值:
In [90]: data.replace(['小明','老王'],'蘋果') Out[90]: age name 0-20蘋果 120蘋果 223蘋果