在大多数的数据分析应用中,经常会遇到缺失值,常见的缺失值处理方式有过滤和填充。在 Python 中,pandas 使用浮点值 NaN 表示浮点数和非浮点数组中的缺失值,同时 Python 内置 None 值也会被当作缺失值。在处理缺失值之前,首先要判断缺失值是否存在,然后再对缺失值进行删除、填充或者不处理的操作。
判断缺失值的函数
在 pandas 中判断缺失值的函数如下。
1) isnull() 函数
isnull() 函数语法格式:isnull(obj)。其中,参数 obj 表示接收标量或数组,用于检查空值或缺失值的对象;如果有空值或缺失值则返回 True,否则返回 False。
2) notnull() 函数
notnull() 函数语法格式:notnull(obj)。其中,参数 obj 接收 ndarray 或对象值,用于检查不为空值或缺失值的对象;如果有空值或缺失值则返回 False,否则返回 True。
通过 isnull() 函数和 sum() 函数可以获得 Series 和 DataFrame 中缺失值的数量。
处理缺失值的方法
数据缺失值的处理方法有以下 3 种:
删除含有缺失值的记录;
进行数据插补;
不处理空值或缺失值。
1) 删除含有缺失值的记录
在数据分析中,如果数据集的样本很大,并且在删除含有缺失值的记录后,不会影响分析结果的客观性和准确性时,一般使用 dropna() 函数直接将空值或缺失值的数据删除。
dropna() 函数的语法格式如下。
DataFrame.dropna(axis=0,how='any',thresh=None,subset=None,inplace=False)
函数中的参数说明如下:
axis:指定删除方向,当 axis=0 按行删除,axis=1 按列删除,默认为 0;
how:取值为“all”表示这一行或列中的元素全部缺失(为 NaN)才删除这一行或列;取值为“any”表示这一行或列中只要有缺失值,就删除这一行或列;
thresh:一行或一列中至少出现了 thresh 个才删除;
subset:在某些列的子集中选择出现了缺失值的列删除,不在子集中的含有缺失值的列或行不会被删除;
inplace:筛选缺失值后,获得的新数据是存为副本还是直接在原数据上进行修改。
【例 1】导入 Excel 成绩表 grade.xls 中的 grade1 表,完成各种不同情况下删除缺失值的操作。
其示例代码 test1.py 如下。
# -*- coding: utf-8 -*-
import pandas as pd
#导入成绩数据
df = pd.read_excel('d:\data\grade.xls',sheet_name='grade1')
#所有值全为缺失值才删除
df1 = df.dropna(how='all')
#输出df1的前5行
print(df1.head())
#删除至少出现过两个缺失值的行
df1 = df.dropna(thresh=2,axis=0)
#输出df1的前10行
print(df1.head(10))
#删除subset中指定的列含有缺失值的行
df1 = df.dropna(subset=['exam'])
#输出df1的前5行
print(df1.head())
#删除含有缺失值的列
print(df.dropna(axis=1))
#只要有缺失值就删除,并且直接在原数据上进行修改
df1 = df.dropna(how='any',inplace=True)
print(df)
2) 数据插补法
在数据分析中,如果数据集的样本比较少或者由于删除含有缺失值的记录,会影响到数据分析结果的客观性和准确性,就需要根据数据插补的方法来选择填充值,然后再使用 fillna() 函数对空值或缺失值进行填充。
fillna() 函数的语法格式如下。
DataFrame.fillna(value=None,method=None,axis=None,
inplace=False,limit=None,downcast=None,**kwargs)
函数中的参数说明如下。
value:接收常数、dict、Series 或 DataFrame,表示填充缺失值的值。
method:表示填充缺失值的方法,method 的取值为{'pad','ffill','backfill','bfill',None}。pad/ffill:用前一个非缺失值去填充该缺失值。backfill/bfill:用下一个非缺失值去填充该缺失值。None:指定一个值去替换缺失值(缺省默认这种方式)。
axis:指定填充方向,当 axis=1 按列填充,axis=0 按行填充。
inplace:接收 True 或 False。True 表示直接修改原对象,False 表示创建一个副本,修改副本,原对象不变,默认为 False。
limit:表示限制填充的个数,如果 limit=2,则只填充两个缺失值。
downcast:默认为 None,如果需要将填充的值向下转换为适当的相等数据类型的数值,如将 float64 数据类型转换为 int64 数据类型时,则此参数的值为 'infer'。
注意:method 参数不能与 value 参数同时出现。
在选取填补缺失值的数据时,除了选择常量 0 或者通过指定 method 方式来选择填充缺失值的数据外,还可以根据数据插补方法来选择填充值。常用数据插补方法见表 1。
表 1:数据插补方法
插补方法
描述
均值/中位数/众数插补
根据属性值的类型,用该属性取值的均值/中位数/众数进行插补
使用固定值
将缺失值属性使用一个常量值替换
最近临插补
在记录中找到与缺失样本最接近的样本的该属性值插补
回归方法
对带有缺失值的变量,根据已有的数据和与其有关的其他变量(因变量)的数据建立拟合模型来预测缺失的属性值
插值法
插值法是利用已知点建立常用的插值函数 f(x),未知值由对应点 x 求岀的函数值 f(x) 近似替代
【例 2】导入 Excel 成绩表 grade.xls 中的grade1 表,完成以下操作。
1) 查看该表前 5 行的缺失值,分别用常数 0 和字典填充缺失值,但不修改原数据。
2) 分别指定不同的 method 参数,观察填充缺失值情况。
3) 将 Normal 属性的缺失值用中位数替换,exam 属性的缺失值用均值替换。
4) 用常数 0 填充缺失值,并修改原数据。
其示例代码 test2.py 如下。
# -*- coding: utf-8 -*-
import pandas as pd
#导入成绩数据
df = pd.read_excel('d:\data\grade.xls',sheet_name='grade1')
#1.查看前面5行
print(df.head())
#2.查看缺失值的数量
print(df.isnull().sum())
#3.用常量0填充
df1 = df.fillna(0)
print(df1.head())
#4.用字典填充
df2 = df.fillna({'Normal':60,'exam':40})
print(df2.head()) #修改副本
#观察原来数据df没有改变
print(df.head())
#5.指定method = 'ffill'/'pad':用前一个非缺失值去填充该缺失值
df2 = df.fillna(method='ffill')
print(df2.head())
#指定method = 'bfill'/'backfill':用下一个非缺失值填充该缺失值
df2 = df.fillna(method='bfill')
print(df2.head())
#6.将exam列的缺失值用均值替换
exa_mea = df['exam'].fillna(df['exam'].mean())
print(exa_mea.head())
#将Normal列的缺失值用中位数替换
Nor_med = df['Normal'].fillna(df['Normal'].median())
print(Nor_med.head())
#7.指定inplace参数为True
print(df.fillna(0,inplace=True))
#观察原来数据df发生改变
print(df.head())