03 -2 numpy與pandas中處理丟失資料的理解與例項
阿新 • • 發佈:2018-12-17
引入三劍客
import numpy as np
import pandas as pd
from pandas import Series,DataFrame
處理丟失資料
1.有兩種丟失資料:
- None: Python自帶的資料型別 不能參與到任何計算中
- np.nan(NaN): float型別 能參與計算,但結果總是NaN
np.nan + 9 結果為:nan
2. np.nan(NaN)
陣列直接運算會得到nan,但可以使用np.nan*()函式來計算nan,此時視nan為0。
ndarr1 = np.array([1,2,3,np.nan]) ndarr1 np.sum(ndarr1) 結果為: nan
np.nansum(ndarr1) # nan*()遇到nan會把nan當作0來處理
結果為:
6.0
Series和DataForm可以直接處理nan
s1 = Series([1,2,3,np.nan])
s1.sum() #Series 直接可以處理nan的情況
結果為:6.0
df1 = DataFrame([1,2,3,np.nan])
df1.sum() #DataFrame 直接可以處理nan的情況
結果為:
0 6.0
dtype: float64
3. pandas中的None與NaN
1) pandas中None與np.nan都視作np.nan
用randint建立一個5*5的DataFrame作為例子
Series 和 DataForm 如果遇到None 就會把 None 轉換成 numpy.nan
df1 = DataFrame(data=np.random.randint(0,20,size=(5,5)),columns=list("abcde"))
df1
a | b | c | d | e | |
---|---|---|---|---|---|
0 | 18 | 18 | 4 | 10 | 6 |
1 | 6 | 12 | 8 | 8 | 4 |
2 | 5 | 15 | 18 | 2 | 2 |
3 | 2 | 18 | 10 | 16 | 14 |
4 | 14 | 13 | 2 | 10 | 14 |
使用DataFrame行索引與列索引修改一下DataFrame資料(弄出來一些None和NaN)
df1["b"][1] = None df1["c"].iloc[2] = None df1.iloc[2].loc["d"] = np.nan # 自己顯式地去設定nan不太好 大家平時不要這麼做 df1
a | b | c | d | e | |
---|---|---|---|---|---|
0 | 18 | 18.0 | 4.0 | 10 | 6 |
1 | 6 | NaN | 8.0 | 8 | 4 |
2 | 5 | 15.0 | NaN | 2 | 2 |
3 | 2 | 18.0 | 10.0 | 16 | 14 |
4 | 14 | 13.0 | 2.0 | 10 | 14 |
2) pandas中None與np.nan的操作
isnull()
notnull()
dropna()
: 過濾丟失資料fillna()
: 填充丟失資料
(1)判斷函式
isnull()
notnull()
df1.isnull() # 返回一個同樣形狀的DataFrame 如果是空這個位置就是True 否則就是False
a | b | c | d | e | |
---|---|---|---|---|---|
0 | False | False | False | False | False |
1 | False | True | False | False | False |
2 | False | False | True | False | False |
3 | False | False | False | False | False |
4 | False | False | False | False | False |
df1.notnull() # 不是空值返回True 是空值就是False
a | b | c | d | e | |
---|---|---|---|---|---|
0 | True | True | True | True | True |
1 | True | False | True | True | True |
2 | True | True | False | True | True |
3 | True | True | True | True | True |
4 | True | True | True | True | True |
配合any使用,可以檢視每一行是否存在空值 可以控制axis來改變檢視方向
df1.isnull().any() # 預設看每一列 只要有True就是True
結果為:
a False
b True
c True
d False
e False
dtype: bool
如果想看每一行的中 有沒有空值 可以改變axis
df1.isnull().any(axis=0) # axis 預設是 0 是豎直方向
df1.isnull().any(axis=1) # 通過這種方式 可以找到有空值的樣本
結果為:
0 False
1 True
2 True
3 False
4 False
dtype: bool
(2) 過濾函式
dropna()
可以選擇過濾的是行還是列(預設為行)
df1.dropna() # 如果有空值 就把整行都幹掉
df1.dropna(axis=0) # 預設是對行進行處理
a | b | c | d | e | |
---|---|---|---|---|---|
0 | 18 | 18.0 | 4.0 | 10 | 6 |
3 | 2 | 18.0 | 10.0 | 16 | 14 |
4 | 14 | 13.0 | 2.0 | 10 | 14 |
# 如果不確定axis到底是橫還是豎 可以自己先建立一個假資料 試一試
df1.dropna(axis=1) # 對有空值的列進行處理
a | d | e | |
---|---|---|---|
0 | 18 | 10 | 6 |
1 | 6 | 8 | 4 |
2 | 5 | 2 | 2 |
3 | 2 | 16 | 14 |
4 | 14 | 10 | 14 |
也可以選擇過濾的方式 how = ‘all’
df1.dropna(how="any") # 只要有空值 就幹掉
a | b | c | d | e | |
---|---|---|---|---|---|
0 | 18 | 18.0 | 4.0 | 10 | 6 |
3 | 2 | 18.0 | 10.0 | 16 | 14 |
4 | 14 | 13.0 | 2.0 | 10 | 14 |
df1.dropna(how="all") # 這一行所有的值都是空值 才幹掉
a | b | c | d | e | |
---|---|---|---|---|---|
0 | 18 | 18.0 | 4.0 | 10 | 6 |
1 | 6 | NaN | 8.0 | 8 | 4 |
2 | 5 | 15.0 | NaN | 2 | 2 |
3 | 2 | 18.0 | 10.0 | 16 | 14 |
4 | 14 | 13.0 | 2.0 | 10 | 14 |
df1.iloc[2] = np.nan
df1
a | b | c | d | e | |
---|---|---|---|---|---|
0 | 18.0 | 18.0 | 4.0 | 10.0 | 6.0 |
1 | 6.0 | NaN | 8.0 | 8.0 | 4.0 |
2 | NaN | NaN | NaN | NaN | NaN |
3 | 2.0 | 18.0 | 10.0 | 16.0 | 14.0 |
4 | 14.0 | 13.0 | 2.0 | 10.0 | 14.0: |
df1.dropna(how="all")
a | b | c | d | e | |
---|---|---|---|---|---|
0 | 18.0 | 18.0 | 4.0 | 10.0 | 6.0 |
1 | 6.0 | NaN | 8.0 | 8.0 | 4.0 |
3 | 2.0 | 18.0 | 10.0 | 16.0 | 14.0 |
4 | 14.0 | 13.0 | 2.0 | 10.0 | 14.0 |
(3) 填充函式 Series/DataFrame
fillna()
可以指定value
df1.fillna(value=0) # 遇到空值 可以設定成我們制定的值
a | b | c | d | e | |
---|---|---|---|---|---|
0 | 18.0 | 18.0 | 4.0 | 10.0 | 6.0 |
1 | 6.0 | 0.0 | 8.0 | 8.0 | 4.0 |
2 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
3 | 2.0 | 18.0 | 10.0 | 16.0 | 14.0 |
4 | 14.0 | 13.0 | 2.0 | 10.0 | 14.0 |
df1.fillna(value=10)
a | b | c | d | e | |
---|---|---|---|---|---|
0 | 18.0 | 18.0 | 4.0 | 10.0 | 6.0 |
1 | 6.0 | 10.0 | 8.0 | 8.0 | 4.0 |
2 | 10.0 | 10.0 | 10.0 | 10.0 | 10.0 |
3 | 2.0 | 18.0 | 10.0 | 16.0 | 14.0 |
4 | 14.0 | 13.0 | 2.0 | 10.0 | 14.0 |
也可以選擇從前面找值來填充還是從後面找值來填充
pad / ffill 從前面找值來填充
backfill/ bfill 從後面找值來填充
df1.fillna(method="ffill")
a | b | c | d | e | |
---|---|---|---|---|---|
0 | 18.0 | 18.0 | 4.0 | 10.0 | 6.0 |
1 | 6.0 | 18.0 | 8.0 | 8.0 | 4.0 |
2 | 6.0 | 18.0 | 8.0 | 8.0 | 4.0 |
3 | 2.0 | 18.0 | 10.0 | 16.0 | 14.0 |
4 | 14.0 | 13.0 | 2.0 | 10.0 | 14.0 |
df1.fillna(method="bfill")
a | b | c | d | e | |
---|---|---|---|---|---|
0 | 18.0 | 18.0 | 4.0 | 10.0 | 6.0 |
1 | 6.0 | 18.0 | 8.0 | 8.0 | 4.0 |
2 | 2.0 | 18.0 | 10.0 | 16.0 | 14.0 |
3 | 2.0 | 18.0 | 10.0 | 16.0 | 14.0 |
4 | 14.0 | 13.0 | 2.0 | 10.0 | 14.0 |
雖然填充了值 但並不影響df1原先的值,
a | b | c | d | e | |
---|---|---|---|---|---|
0 | 18.0 | 18.0 | 4.0 | 10.0 | 6.0 |
1 | 6.0 | NaN | 8.0 | 8.0 | 4.0 |
2 | NaN | NaN | NaN | NaN | NaN |
3 | 2.0 | 18.0 | 10.0 | 16.0 | 14.0 |
4 | 14.0 | 13.0 | 2.0 | 10.0 | 14.0 |
還可以指定是在尋找值時候的軸線
df1.fillna(method="ffill",axis=0) # axis 預設是0 豎直找 前面已做過
df1.fillna(method="ffill",axis=1) # axis 1 水平找
a | b | c | d | e | |
---|---|---|---|---|---|
0 | 18.0 | 18.0 | 4.0 | 10.0 | 6.0 |
1 | 6.0 | 6.0 | 8.0 | 8.0 | 4.0 |
2 | NaN | NaN | NaN | NaN | NaN |
3 | 2.0 | 18.0 | 10.0 | 16.0 | 14.0 |
4 | 14.0 | 13.0 | 2.0 | 10.0 | 14.0 |
還可以限定最多往前(往後)填充幾個NaN
df1["c"].iloc[1]=np.nan
df1
a | b | c | d | e | |
---|---|---|---|---|---|
0 | 18.0 | 18.0 | 4.0 | 10.0 | 6.0 |
1 | 6.0 | NaN | NaN | 8.0 | 4.0 |
2 | NaN | NaN | NaN | NaN | NaN |
3 | 2.0 | 18.0 | 10.0 | 16.0 | 14.0 |
4 | 14.0 | 13.0 | 2.0 | 10.0 | 14.0 |
df1.fillna(method="ffill",limit=2) # 限制往前找幾個
a | b | c | d | e | |
---|---|---|---|---|---|
0 | 18.0 | 18.0 | 4.0 | 10.0 | 6.0 |
1 | 6.0 | 18.0 | 4.0 | 8.0 | 4.0 |
2 | 6.0 | 18.0 | 4.0 | 8.0 | 4.0 |
3 | 2.0 | 18.0 | 10.0 | 16.0 | 14.0 |
4 | 14.0 | 13.0 | 2.0 | 10.0 | 14.0 |
對於DataFrame來說,還要選擇填充的軸axis。記住,對於DataFrame來說:
- axis=0:index/行
- axis=1:columns/列
使用limit來限定往後找幾個
axis 指定是橫著找還是豎著找
method 指定找前面還是找後面
注意:value引數是不能跟method引數共用的
df.fillna(method='bfill',axis=1,limit=1)
a | b | c | d | e | |
---|---|---|---|---|---|
0 | 18.0 | 18.0 | 4.0 | 10.0 | 6.0 |
1 | 6.0 | NaN | 8.0 | 8.0 | 4.0 |
2 | NaN | NaN | NaN | NaN | NaN |
3 | 2.0 | 18.0 | 10.0 | 16.0 | 14.0 |
4 | 14.0 | 13.0 | 2.0 | 10.0 | 14.0 |
============================================
練習7:
- 簡述None與NaN的區別
- 假設張三李四參加模擬考試,但張三因為突然想明白人生放棄了英語考試,因此記為None,請據此建立一個DataFrame,命名為df3
- 老師決定根據用數學的分數填充張三的英語成績,如何實現? 用李四的英語成績填充張三的英語成績?
============================================