Pandas 缺失值的处理

1. 前言

通过前面几个小节的学习,我们掌握了 Pandas 解析数据和数据增删改查的基础操作,能有效对数据的量和内容进行处理,但我们在解析数据的时候经常会出现缺失值的情况,这些缺失数据的存在不仅影响数据的美观,还会影响到数据分析和挖掘的结果,那 Pandas 库中又是怎么解决缺失值这一问题的呢?

针对数据中的缺失值,Pandas 库提供了便捷的操作去检查缺失值,并对缺失值作出处理,本小节,我们将学习 Pandas 检测缺失值的方法,以及 Pandas 处理缺失值常见的两种方式。

2. 缺失值的检测

在学习进行缺失值处理之前,我们先来看一下什么是缺失值,为什么会出现缺失值?

缺失值 —— 是指粗糙数据中由于缺少信息而造成的数据的聚类、分组、删失或截断。它指的是现有数据集中某个或某些属性的值是不完全的。(来源:百度百科)

缺失值的出现是很正常的一种现象,首先我们要正视缺失值的存在,缺失值的出现一般来说有机械原因和人为原因,但在我们实际应用中,多说是我们人为的失误或错误的操作导致的缺失,缺失值的出现对于我们分析数据的过程不会产生过大的影响,但是对于数据分析的结果可能会产生致命的影响,影响数据的准确性和结果的可靠性。

在 Pandas 中,对于缺失值使用浮点值 NaN 进行表示,如下图我们将 Excel 数据文件中删除几个数据值,进行数据的解析:

图片描述

然后我通过 Pandas 库进行数据的解析,可以看到数据缺失值的表示 NaN:

图片描述

2.1 isnull () 函数

该函数用来检测缺失值,如果是缺失值 NaN 则数据返回的是 True,不是缺失值返回的是 False。

# 导入pandas包
import pandas as pd
data_path="C:/Users/13965/Documents/myFuture/IMOOC/pandasCourse-progress/data_source/第11小节/execl数据demo.xlsx"
# 解析数据
data = pd.read_excel(data_path)
print(data)

# --- 输出结果 ---
    编程语言   推出时间    价格            主要创始人
0    java    NaN  45.6               James Gosling
1  python  199167.0                         NaN
2     NaN  1972年   NaN  Dennis MacAlistair Ritchie
3      js    NaN   NaN                Brendan Eich
4     php  2012年   NaN              Rasmus Lerdorf
5     C++  198375.0           Bjarne Stroustrup

# 检查是否是缺失值
data.isnull()

# --- 输出结果 ---
   编程语言	  推出时间	价格	主要创始人
0	False	True	False	False
1	False	False	False	True
2	True	False	True	False
3	False	True	True	False
4	False	False	True	False
5	False	False	False	False

输出解析:通过结果可以看到,是缺失值 NaN 的数据,在该函数检查后,都返回了 True,否则则是 False。

2.2 notnull () 函数

该函数也能检测缺失值,但是和 isnull () 函数相反,对于缺失值 NaN 的数据返回 False,否则为 True。

# data 是上面从 Excel 中解析出来的数据
# 检查是否不是缺失值
data.notnull()

# --- 输出结果 ---
   编程语言	 推出时间   价格	主要创始人
0	True	False	True	True
1	True	True	True	False
2	False	True	False	True
3	True	False	False	True
4	True	True	False	True
5	True	True	True	True

输出解析:通过结果可以看到,不是缺失值 NaN 的数据,在该函数检查后,都返回了 True,否则则是 False。

3. 缺失值的处理

Pandas 提供了便捷的方法去检测缺失值,当然他还提供了对应的函数去处理缺失值,这里我们将学习缺失值的两种处理方式,一种是过滤缺失值,也就对存在缺失值的行或者列,进行过滤操作;另一种是我们对缺失的数据进行填充处理。

3.1 dropna () 函数

该函数用于过滤含有缺失值的数据行或者列,操作之后会返回一个新的数据集,该函数提供了丰富的参数设置,下面列举了该函数常用的几个参数:

参数名 说明
axis 指定是行还是列的过滤( 0 指行,1 为列),默认 axis=0
how 指定缺失值过滤的依据,含有缺失值就过滤(how=“any” 默认)还是全是全是缺失值才过滤(how=“all”)
thresh 指保留至少含有多少个非缺失值的行或列(参数值为整数)
subset 指定特定的行或者列进行缺失值过滤

下面我们将通过实际程序操作,学习每个参数的使用方式:

# 导入pandas包
import pandas as pd
data_path="C:/Users/13965/Documents/myFuture/IMOOC/pandasCourse-progress/data_source/第11小节/execl数据demo.xlsx"
# 解析数据
data = pd.read_excel(data_path)
print(data)
# --- 输出结果 ---
     编程语言   推出时间    价格           主要创始人
0    java    NaN  45.6               James Gosling
1  python  199167.0                         NaN
2     NaN  1972年   NaN  Dennis MacAlistair Ritchie
3      js    NaN   NaN                Brendan Eich
4     php  2012年   NaN              Rasmus Lerdorf
5     C++  198375.0           Bjarne Stroustrup

###### dropna 过滤缺失值
# 1. axis=0 设置过滤行中有缺失值的数据
new_data= data.dropna(axis=0)
print(new_data)
# --- 输出结果 ---
  编程语言   推出时间    价格    主要创始人
5  C++    198375.0  Bjarne Stroustrup
# 结果解析:可以看到所有含 NaN 的数据行都被过滤掉,只剩下一行数据

# 2. axis=1 设置过滤行列中缺失值的数据
new_data= data.dropna(axis=1)
print(new_data)
# --- 输出结果 ---
Empty DataFrame
Columns: []
Index: [0, 1, 2, 3, 4, 5]
# 结果解析:因为原数据中每一列都有 NaN 数据的存在,所以 axis=1 操作后,数据集为 Empty DataFrame

# 3. how="all" 设置所有值都为 NaN 的数据列才被过滤
new_data= data.dropna(axis=1,how="all")
print(new_data)
# --- 输出结果 ---
    编程语言   推出时间    价格           主要创始人
0    java    NaN  45.6               James Gosling
1  python  199167.0                         NaN
2     NaN  1972年   NaN  Dennis MacAlistair Ritchie
3      js    NaN   NaN                Brendan Eich
4     php  2012年   NaN              Rasmus Lerdorf
5     C++  198375.0           Bjarne Stroustrup
# 结果解析:通过设置 how="all" 因为原数据不存在全为 NaN 的数据列,因此并没有进行数据的过滤,输出为原数据集

# 4. thresh=4 只保留含有4个及4个以上的非缺失值的数据
new_data= data.dropna(axis=1,thresh=4)
print(new_data)
# --- 输出结果 ---
     编程语言   推出时间           主要创始人
0    java    NaN               James Gosling
1  python  1991年                         NaN
2     NaN  1972年  Dennis MacAlistair Ritchie
3      js    NaN                Brendan Eich
4     php  2012年              Rasmus Lerdorf
5     C++  1983年           Bjarne Stroustrup
# 结果解析:因为"价格"这一列只有3个非缺失值的数据,因此设置 thresh=4,会将该列过滤掉。     

# 5. subset 指定要过滤的数据列
new_data= data.dropna(axis=0,subset=["价格","主要创始人"])
print(new_data)
# --- 输出结果 ---
   编程语言   推出时间    价格   主要创始人
0  java    NaN  45.6      James Gosling
5   C++  198375.0  Bjarne Stroustrup
# 结果解析:这里通过 subset 指定过滤"价格""主要创始人"列中存在 NaN 数据的行,通过结果可以看到,过滤掉了行索引为1,2,3,4的行。

3.2 fillna () 函数

该函数用于填充缺失值的操作,返回一个新的数据集,该函数提供了丰富的参数可供设置,下面列举了常用的几个参数:

参数名 说明
value 指定用什么值去填充
method 填充的方式,ffill 用前一个非缺失值填充这个缺失值,bfill 用下一个非缺失值填充这个缺失值,None 默认的,指定一个缺失值去填充
axis 修改填充的方向 ,默认是 axis=0 在列的方向填充
limit 指定填充的个数,在某个方向如果存在多个连续的缺失值,指定填充的几个

下面通代码程序来看一个每个参数的具体使用方式:

# 导入pandas包
import pandas as pd
data_path="C:/Users/13965/Documents/myFuture/IMOOC/pandasCourse-progress/data_source/第11小节/execl数据demo.xlsx"
# 解析数据
data = pd.read_excel(data_path)
print(data)
# --- 输出结果 ---
     编程语言   推出时间    价格          主要创始人
0    java    NaN  45.6               James Gosling
1  python  199167.0                         NaN
2     NaN  1972年   NaN  Dennis MacAlistair Ritchie
3      js    NaN   NaN                Brendan Eich
4     php  2012年   NaN              Rasmus Lerdorf
5     C++  198375.0           Bjarne Stroustrup

# 1. 直接设置 value 指定填充的内容
new_data= data.fillna("###")
print(new_data)
# --- 输出结果 ---
     编程语言   推出时间    价格           主要创始人
0    java    ###  45.6               James Gosling
1  python  199167                         ###
2     ###  1972年   ###  Dennis MacAlistair Ritchie
3      js    ###   ###                Brendan Eich
4     php  2012###              Rasmus Lerdorf
5     C++  198375           Bjarne Stroustrup
# 结果解析:通过设置填充的值为 ### ,可以看到原数据集中的缺失值都被填充了该字符

# 2. 设置 method 填充的方向
new_data= data.fillna(method="bfill")
print(new_data)
# --- 输出结果 ---
     编程语言   推出时间    价格           主要创始人
0    java  199145.6               James Gosling
1  python  199167.0  Dennis MacAlistair Ritchie
2      js  197275.0  Dennis MacAlistair Ritchie
3      js  201275.0                Brendan Eich
4     php  201275.0              Rasmus Lerdorf
5     C++  198375.0           Bjarne Stroustrup
# 结果解析:这里设置了填充的方式为 bfill ,默认的 axis=0 是在列上,表示用这一列的下一行的非缺失值填充这个缺失值,通过输出结果可看到,缺失值均被填上了内容,这里要注意一点,如果下一个数据为 NaN,则会继续往下找,直到找到一个非缺失值的数据来填充。

# 3. 设置 axis=1 在横向上进行填充
new_data= data.fillna(axis=1,method="bfill")
print(new_data)
# --- 输出结果 ---
     编程语言    推出时间                  价格                   主要创始人 
0    java          45.6                        45.6         James Gosling 
1  python         199167        NaN
2   19721972年  Dennis MacAlistair Ritchie        Dennis MacAlistair Ritchie  
3      js  Brendan Eich                Brendan Eich         Brendan Eich  
4     php         2012年              Rasmus Lerdorf        Rasmus Lerdorf
5     C++         198375        Bjarne Stroustrup  
# 结果解析:这里程序中设置了 axis 为横向,method 为 bfill ,通过输出结果可以看到为 NaN 的数据,用他后面的非缺失值进行了填充,如果他后面没有数据,则不进行填充,仍然为 NaN。

# 4. limit 指定出现连续的缺失值,填充的数量
new_data= data.fillna(axis=0,method="bfill",limit=2)
print(new_data)
# --- 输出结果 ---
     编程语言   推出时间    价格            主要创始人
0    java  199145.6               James Gosling
1  python  199167.0  Dennis MacAlistair Ritchie
2      js  1972年   NaN  Dennis MacAlistair Ritchie
3      js  201275.0                Brendan Eich
4     php  201275.0              Rasmus Lerdorf
5     C++  198375.0           Bjarne Stroustrup
# 结果解析:通过设置 limit=2 指定出现连续的缺失值只填充2个数据,这里可以看到在"价格"列中原数据出现的连续三个 NaN 这里按列的方向,只填充了两个数据。

3. 小结

本节课程我们主要学习了 Pandas 检测数据集中存在缺失值的方法,同时学习了 Pandas 对缺失值的过滤操作和填充缺失值的方法。本节课程的重点如下:

  • isnull () 函数和 notnull () 函数对缺失值的检测操作和检测返回结果;
  • dropna () 函数对缺失值的过滤操作,以及其中常用参数的设置方式;
  • fillna () 函数对缺失值的填充操作,以及其中常用参数的设置方式。

图片描述