Pandas缺失值處理 | 輕鬆玩轉Pandas(3)

王偉同學發表於2018-07-24

教你學會 Pandas 不是我的目的,教你輕鬆玩轉 Pandas 才是我的目的。我會通過一系列例項來帶入 Pandas 的知識點,讓你在學習 Pandas 的路上不再枯燥。

宣告:我所寫的輕鬆玩轉 Pandas 教程都是免費的,如果對你有幫助,你可以持續關注我。

Pandas缺失值處理 | 輕鬆玩轉Pandas(3)

Pandas基本功能詳解 | 輕鬆玩轉Pandas(2) 介紹了 Pandas 中常用的一些功能,使得我們對 Pandas 的使用有了基本的瞭解。這一章節我們來看下如何使用Pandas處理缺失值。

# 匯入相關庫
import numpy as np
import pandas as pd
複製程式碼

什麼是缺失值

在瞭解缺失值(也叫控制)如何處理之前,首先要知道的就是什麼是缺失值?直觀上理解,缺失值表示的是“缺失的資料”

可以思考一個問題:是什麼原因造成的缺失值呢?其實有很多原因,實際生活中可能由於有的資料不全所以導致資料缺失,也有可能由於誤操作導致資料缺失,又或者人為地造成資料缺失。

來看下我們的示例吧。

index = pd.Index(data=["Tom", "Bob", "Mary", "James", "Andy", "Alice"], name="name")

data = {
    "age": [18, 30, np.nan, 40, np.nan, 30],
    "city": ["BeiJing", "ShangHai", "GuangZhou", "ShenZhen", np.nan, " "],
    "sex": [None, "male", "female", "male", np.nan, "unknown"],
    "birth": ["2000-02-10", "1988-10-17", None, "1978-08-08", np.nan, "1988-10-17"]
}

user_info = pd.DataFrame(data=data, index=index)

# 將出生日期轉為時間戳
user_info["birth"] = pd.to_datetime(user_info.birth)
user_info
複製程式碼
age birth city sex
name
Tom 18.0 2000-02-10 BeiJing None
Bob 30.0 1988-10-17 ShangHai male
Mary NaN NaT GuangZhou female
James 40.0 1978-08-08 ShenZhen male
Andy NaN NaT NaN NaN
Alice 30.0 1988-10-17 unknown

可以看到,使用者 Tom 的性別為 None,使用者 Mary 的年齡為 NAN,生日為 NaT。在 Pandas 的眼中,這些都屬於缺失值,可以使用 isnull()notnull() 方法來操作。

user_info.isnull()
複製程式碼
age birth city sex
name
Tom False False False True
Bob False False False False
Mary True True False False
James False False False False
Andy True True True True
Alice False False False False

除了簡單的可以識別出哪些是缺失值或非缺失值外,最常用的就是過濾掉一些缺失的行。比如,我想過濾掉使用者年齡為空的使用者,如何操作呢?

user_info[user_info.age.notnull()]
複製程式碼
age birth city sex
name
Tom 18.0 2000-02-10 BeiJing None
Bob 30.0 1988-10-17 ShangHai male
James 40.0 1978-08-08 ShenZhen male
Alice 30.0 1988-10-17 unknown

丟棄缺失值

既然有缺失值了,常見的一種處理辦法就是丟棄缺失值。使用 dropna 方法可以丟棄缺失值。

user_info.age.dropna()
複製程式碼
name
Tom      18.0
Bob      30.0
James    40.0
Alice    30.0
Name: age, dtype: float64
複製程式碼

Seriese 使用 dropna 比較簡單,對於 DataFrame 來說,可以設定更多的引數。

axis 引數用於控制行或列,跟其他不一樣的是,axis=0 (預設)表示操作行,axis=1 表示操作列。

how 引數可選的值為 any(預設) 或者 allany 表示一行/列有任意元素為空時即丟棄,all 一行/列所有值都為空時才丟棄。

subset 參數列示刪除時只考慮的索引或列名。

thresh引數的型別為整數,它的作用是,比如 thresh=3,會在一行/列中至少有 3 個非空值時將其保留。

# 一行資料只要有一個欄位存在空值即刪除
user_info.dropna(axis=0, how="any")
複製程式碼
age birth city sex
name
Bob 30.0 1988-10-17 ShangHai male
James 40.0 1978-08-08 ShenZhen male
Alice 30.0 1988-10-17 unknown
# 一行資料所有欄位都為空值才刪除
user_info.dropna(axis=0, how="all")
複製程式碼
age birth city sex
name
Tom 18.0 2000-02-10 BeiJing None
Bob 30.0 1988-10-17 ShangHai male
Mary NaN NaT GuangZhou female
James 40.0 1978-08-08 ShenZhen male
Alice 30.0 1988-10-17 unknown
# 一行資料中只要 city 或 sex 存在空值即刪除
user_info.dropna(axis=0, how="any", subset=["city", "sex"])
複製程式碼
age birth city sex
name
Bob 30.0 1988-10-17 ShangHai male
Mary NaN NaT GuangZhou female
James 40.0 1978-08-08 ShenZhen male
Alice 30.0 1988-10-17 unknown

填充缺失值

除了可以丟棄缺失值外,也可以填充缺失值,最常見的是使用 fillna 完成填充。

fillna 這名字一看就是用來填充缺失值的。

填充缺失值時,常見的一種方式是使用一個標量來填充。例如,這裡我樣有缺失的年齡都填充為 0。

user_info.age.fillna(0)
複製程式碼
name
Tom      18.0
Bob      30.0
Mary      0.0
James    40.0
Andy      0.0
Alice    30.0
Name: age, dtype: float64
複製程式碼

除了可以使用標量來填充之外,還可以使用前一個或後一個有效值來填充。

設定引數 method='pad'method='ffill' 可以使用前一個有效值來填充。

user_info.age.fillna(method="ffill")
複製程式碼
name
Tom      18.0
Bob      30.0
Mary     30.0
James    40.0
Andy     40.0
Alice    30.0
Name: age, dtype: float64
複製程式碼

設定引數 method='bfill'method='backfill' 可以使用後一個有效值來填充。

user_info.age.fillna(method="backfill")
複製程式碼
name
Tom      18.0
Bob      30.0
Mary     40.0
James    40.0
Andy     30.0
Alice    30.0
Name: age, dtype: float64
複製程式碼

除了通過 fillna 方法來填充缺失值外,還可以通過 interpolate 方法來填充。預設情況下使用線性差值,可以是設定 method 引數來改變方式。

user_info.age.interpolate()
複製程式碼
name
Tom      18.0
Bob      30.0
Mary     35.0
James    40.0
Andy     35.0
Alice    30.0
Name: age, dtype: float64
複製程式碼

替換缺失值

大家有沒有想過一個問題:到底什麼才是缺失值呢?你可能會奇怪說,前面不是已經說過了麼,Nonenp.nanNaT 這些都是缺失值。但是我也說過了,這些在 Pandas 的眼中是缺失值,有時候在我們人類的眼中,某些異常值我們也會當做缺失值來處理。

例如,在我們的儲存的使用者資訊中,假定我們限定使用者都是青年,出現了年齡為 40 的,我們就可以認為這是一個異常值。再比如,我們都知道性別分為男性(male)和女性(female),在記錄使用者性別的時候,對於未知的使用者性別都記為了 “unknown”,很明顯,我們也可以認為“unknown”是缺失值。此外,有的時候會出現空白字串,這些也可以認為是缺失值。

對於上面的這種情況,我們可以使用 replace 方法來替換缺失值。

user_info.age.replace(40, np.nan)
複製程式碼
name
Tom      18.0
Bob      30.0
Mary      NaN
James     NaN
Andy      NaN
Alice    30.0
Name: age, dtype: float64
複製程式碼

也可以指定一個對映字典。

user_info.age.replace({40: np.nan})
複製程式碼
name
Tom      18.0
Bob      30.0
Mary      NaN
James     NaN
Andy      NaN
Alice    30.0
Name: age, dtype: float64
複製程式碼

對於 DataFrame,可以指定每列要替換的值。

user_info.replace({"age": 40, "birth": pd.Timestamp("1978-08-08")}, np.nan)
複製程式碼
age birth city sex
name
Tom 18.0 2000-02-10 BeiJing None
Bob 30.0 1988-10-17 ShangHai male
Mary NaN NaT GuangZhou female
James NaN NaT ShenZhen male
Andy NaN NaT NaN NaN
Alice 30.0 1988-10-17 unknown

類似地,我們可以將特定字串進行替換,如:將 "unknown" 進行替換。

user_info.sex.replace("unknown", np.nan)
複製程式碼
name
Tom        None
Bob        male
Mary     female
James      male
Andy        NaN
Alice       NaN
Name: sex, dtype: object
複製程式碼

除了可以替換特定的值之外,還可以使用正規表示式來替換,如:將空白字串替換成空值。

user_info.city.replace(r'\s+', np.nan, regex=True)
複製程式碼
name
Tom        BeiJing
Bob       ShangHai
Mary     GuangZhou
James     ShenZhen
Andy           NaN
Alice          NaN
Name: city, dtype: object
複製程式碼

使用其他物件填充

除了我們自己手動丟棄、填充已經替換缺失值之外,我們還可以使用其他物件來填充。

例如有兩個關於使用者年齡的 Series,其中一個有缺失值,另一個沒有,我們可以將沒有的缺失值的 Series 中的元素傳給有缺失值的。

age_new = user_info.age.copy()
age_new.fillna(20, inplace=True)
age_new
複製程式碼
name
Tom      18.0
Bob      30.0
Mary     20.0
James    40.0
Andy     20.0
Alice    30.0
Name: age, dtype: float64
複製程式碼
user_info.age.combine_first(age_new)
複製程式碼
name
Tom      18.0
Bob      30.0
Mary     20.0
James    40.0
Andy     20.0
Alice    30.0
Name: age, dtype: float64
複製程式碼

可以看到,使用者資訊中關於年齡的缺失值都使用 age_new 這個 Series 填充了。


想要學習更多關於人工智慧的知識,請關注公眾號:AI派

qrcode_for_gh_60cef389e81c_258.jpg

這裡我將整篇文章的內容整理成了pdf,想要pdf檔案的可以在公眾號後臺回覆關鍵字:pandas03

更多Pandas知識見:輕鬆玩轉Pandas

相關文章