# 导入相关库
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 city sex birth
name
Tom 18.0 BeiJing None 2000-02-10
Bob 30.0 ShangHai male 1988-10-17
Mary NaN GuangZhou female NaT
James 40.0 ShenZhen male 1978-08-08
Andy NaN NaN NaN NaT
Alice 30.0 unknown 1988-10-17
可以看到,用户 Tom 的性别为 None,用户 Mary 的年龄为 NAN,生日为 NaT。在 Pandas 的眼中,这些都属于缺失值,可以使用 isnull() 或 notnull() 方法来操作。
user_info.isnull()
------------------------
age city sex birth
name
Tom False False True False
Bob False False False False
Mary True False False True
James False False False False
Andy True True True True
Alice False False False False
user_info[user_info.age.notnull()]
-----------------------------
age city sex birth
name
Tom 18.0 BeiJing None 2000-02-10
Bob 30.0 ShangHai male 1988-10-17
James 40.0 ShenZhen male 1978-08-08
Alice 30.0 unknown 1988-10-17
user_info.age.dropna()
---------------------------
name
Tom 18.0
Bob 30.0
James 40.0
Alice 30.0
Name: age, dtype: float64
# 一行数据只要有一个字段存在空值即删除
user_info.dropna(axis=0, how="any")
------------------------------
age city sex birth
name
Bob 30.0 ShangHai male 1988-10-17
James 40.0 ShenZhen male 1978-08-08
Alice 30.0 unknown 1988-10-17
# 一行数据所有字段都为空值才删除
user_info.dropna(axis=0, how="all")
------------------------------
age city sex birth
name
Tom 18.0 BeiJing None 2000-02-10
Bob 30.0 ShangHai male 1988-10-17
Mary NaN GuangZhou female NaT
James 40.0 ShenZhen male 1978-08-08
Alice 30.0 unknown 1988-10-17
# 一行数据中只要 city 或 sex 存在空值即删除
user_info.dropna(axis=0, how="any", subset=["city", "sex"])
-------------------------------------
age city sex birth
name
Bob 30.0 ShangHai male 1988-10-17
Mary NaN GuangZhou female NaT
James 40.0 ShenZhen male 1978-08-08
Alice 30.0 unknown 1988-10-17
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
除了可以使用标量来填充之外,还可以使用前一个或后一个有效值来填充。
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
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
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
大家有没有想过一个问题:到底什么才是缺失值呢?你可能会奇怪说,前面不是已经说过了么,None、np.nan、NaT这些都是缺失值。但是我也说过了,这些在 Pandas 的眼中是缺失值,有时候在我们人类的眼中,某些异常值我们也会当做缺失值来处理。 例如,在我们的存储的用户信息中,假定我们限定用户都是青年,出现了年龄为 40 的,我们就可以认为这是一个异常值。再比如,我们都知道性别分为男性(male)和女性(female),在记录用户性别的时候,对于未知的用户性别都记为了 “unknown”,很明显,我们也可以认为“unknown”是缺失值。此外,有的时候会出现空白字符串,这些也可以认为是缺失值。
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
user_info.replace({"age": 40, "birth": pd.Timestamp("1978-08-08")}, np.nan)
---------------------------
age city sex birth
name
Tom 18.0 BeiJing None 2000-02-10
Bob 30.0 ShangHai male 1988-10-17
Mary NaN GuangZhou female NaT
James NaN ShenZhen male NaT
Andy NaN NaN NaN NaT
Alice 30.0 unknown 1988-10-17
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
除了我们自己手动丢弃、填充已经替换缺失值之外,我们还可以使用其他对象来填充。
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派 | 禹都一只猫整理,转载请注明。