4. 缺失值的处理¶
面对大量数据经常会出现残缺不全的情况,面对这样的数据我们需要对缺失值进行预先处理。
填充缺失值一般用两个值:
- None: 对象类型内容的默认缺失值
- NaN: 数值类型的默认缺失值,用numpy.nan表示
需要注意的是:
- 不同语言/工具可能对缺失值的默认处理方式不同,所以,如果拿到的是别的处理过的文件,可能需要对已经替换过的缺失值再进行替换一次。
- NaN的使用具有传染性,就是任何数据跟NaN进行操作,最终的结果都是NaN, 性质很像乘法中的0,所以在有的操作函数中,numpy提供了另外一套操作,对NaN缺失值自动过滤掉,而不是让他传染给所有结果
- None和NaN可以互换,或者可以认为这两个值在Pandas中等价
4.1. 对NaN不敏感的操作函数¶
有时候NaN的传染性并不是让人喜欢,他会导致我们的结果出现重大偏差甚至错误,所以在处理的时候我们还提供了另外一套对NaN不敏感的函数:
- np.nansum
- np.nanmin
- np.nanmax
# 创建带有NaN的数组
a = np.array([3, 2, 3, np.nan, 4])
print("a = \n", a)
print()
# 对于普通的函数操作,NaN具有传染性
print("np.sum = ", np.sum(a))
print("np.min = ", np.min(a))
print("np.max = ", np.max(a))b'
# 如果想避免NaN传染性带来的问题,需要使用相应NaN非敏感函数
print("np.nansum = ", np.nansum(a))
print("np.nanmin = ", np.nanmin(a))
print("np.nanmax = ", np.nanmax(a))
a =
[ 3. 2. 3. nan 4.]
np.sum = nan
np.min = nan
np.max = nan
np.nansum = 12.0
np.nanmin = 2.0
np.nanmax = 4.0
/Users/augs/anaconda3/lib/python3.7/site-packages/numpy/core/fromnumeric.py:83: RuntimeWarning: invalid value encountered in reduce
return ufunc.reduce(obj, axis, dtype, out, **passkwargs)
4.2. 缺失值的发现¶
发现缺失值可以使用两个函数:
- isnull
- notnull
每个函数都返回布尔类型的掩码数据。
# 准备的实验数据
data = pd.Series([23, np.nan, "hahaha", "two", 23, None])
print("data = \n ", data)
data =
0 23
1 NaN
2 hahaha
3 two
4 23
5 None
dtype: object
# isnull用来判断是否是空
# isnull返回的是布尔值
print("\n data.isnull = \n", data.isnull())
# notnull返回的是布尔值
print("\n data.notnull = \n", data.notnull())
# 可以使用这个作为掩码操作
print("\n data[data.notnull()] = \n", data[data.notnull()])
data.isnull =
0 False
1 True
2 False
3 False
4 False
5 True
dtype: bool
data.notnull =
0 True
1 False
2 True
3 True
4 True
5 False
dtype: bool
data[data.notnull()] =
0 23
2 hahaha
3 two
4 23
dtype: object
4.3. 剔除缺失值¶
对于缺失值的处理一般是剔除或者用一个特殊的值来进行填充:
- dropna: 剔除缺失值,常用的两个参数:
- axis: 控制剔除行或者列
- thresh:如果有效数据数量低于这个值,则对应的行或列将被剔除
- fillna: 缺失值用别的值进行填充
# 剔除缺失值
# 剔除后只留下原来的真正的值
print("\n data.dropna = \n", data.dropna())
data.dropna =
0 23
2 hahaha
3 two
4 23
dtype: object
# 需要注意的是,如果是二维数据,剔除后需要把整行都剔除,不仅仅是把NaN的一个值剔除
df = pd.DataFrame([[1, np.nan, 3],
[2, 4, 9],
[np.nan, np.nan, 9]])
print("\n df.dropna = \n", df.dropna())
df.dropna =
0 1 2
1 2.0 4.0 9
# 如果改变剔除的默认行为,比如剔除包含NaN的行,则需要axis参数
print("\n df.dropna(axis='columns') = \n", df.dropna(axis='columns'))
df.dropna(axis='columns') =
2
0 3
1 9
2 9
# thresh参数
# 数据列中,低于thresh=2的列被剔除
print("\n df.dropna(axis='columns') = \n", df.dropna(axis='columns', thresh=2))
df.dropna(axis='columns') =
0 2
0 1.0 3
1 2.0 9
2 NaN 9
4.4. 填充缺失值¶
对于缺失值一般使用换一个特定的值进行填充就可以。填充的时候可以使用一些特定的值,比如0,-1等,也可以使用一些处理后的值,比如填充(imputation)或者转换(interpolation)之后的数据。
填充函数是fillna,常用参数为:
- axis: 坐标轴,行或者列
- method: 填充方式
- ffill: forward-fill, 从前向后填充
- bfill: backward-fill, 从后向前填充
# 准备数据
df = pd.DataFrame([[1, np.nan, 3],
[2, 4, 9],
[np.nan, np.nan, 9]])
print("\n df = \n", df)
df =
0 1 2
0 1.0 NaN 3
1 2.0 4.0 9
2 NaN NaN 9
# 使用某一个值进行填充
print("df.fillna = \n", df.fillna(-1))
df.fillna =
0 1 2
0 1.0 -1.0 3
1 2.0 4.0 9
2 -1.0 -1.0 9
# forward-fill
print("df.fillna(ffill) = \n", df.fillna( method="ffill"))
df.fillna(ffill) =
0 1 2
0 1.0 NaN 3
1 2.0 4.0 9
2 2.0 4.0 9
# backward-fill
print("df.fillna(bfill) = \n", df.fillna(axis=1, method="bfill"))
df.fillna(bfill) =
0 1 2
0 1.0 3.0 3.0
1 2.0 4.0 9.0
2 9.0 9.0 9.0