前言
在本章中,我将讨论用于缺失值、重复值、字符串操作和其他分析数据转换的工具。而这篇文章中主要介绍如何处理数据的缺失值。
一、处理缺失值
缺失数据会在很多数据分析应用中出现。pandas的目标之一就是尽可能无痛地处理缺失值。对于数据型数据,pandas使用浮点值NaN(Not a Number来表示缺失值)。我们称NaN为容易检测到的标识值:
import numpy as np
import pandas as pd
string_data = pd.Series(['Magnum', 'Boost', np.nan, 'Zombie'])
print(string_data)
-----------------------------------------------------------
0 Magnum
1 Boost
2 NaN
3 Zombie
dtype: object
a = string_data.isnull()
print(a)
-----------------------------------------------------------
0 False
1 False
2 True
3 False
dtype: bool
在统计学的应用中,NA数据可以是不存在的数据或是存在但不可以观察的数据(例如在数据收集过程中出现了问题)。当清洗数据用于分析时,对缺失数据本身进行分析以确定数据收集问题或数据丢失导致的数据偏差通常很重要。
而Python内建的None值在对象数组中也被当作NA处理:
string_data[0] = None
a = string_data.isnull()
print(a)
-----------------------------------------------------------
0 True
1 False
2 True
3 False
dtype: bool
而下表是处理缺失值的相关函数列表:
函数名 | 描述 |
---|---|
dropna | 根据每个标签的值是否是缺失数据来筛选轴标签,并根据允许丢失的数据量来确定阔值 |
fillna | 用某些值填充缺失的数据或使用插值方法(如‘ffill’或‘bfill’) |
isnull | 返回表明哪些值是缺失值的布尔值 |
notnull | 返回表明哪些值不是缺失值的布尔值 |
1.1 过滤缺失值
有多种过滤缺失值的方法,但这里推荐用dropna在过滤缺失值时是非常有用的。在Series上使用dropna,它会返回Series中所有的非空数据及其索引值:
from numpy import nan as NA
data = pd.Series([1, NA, 3.5, NA, 7])
a1 = data.dropna()
print(a1)
-----------------------------------------------------------
0 1.0
2 3.5
4 7.0
dtype: float64
而也可以使用pandas.notnull和布尔值索引手动地过滤缺失值:
a2 = data[data.notnull()]
print(a2)
-----------------------------------------------------------
0 1.0
2 3.5
4 7.0
dtype: float64
当处理DataFrame对象时,事情会稍微更复杂一点。你可能想要删除全部为NA或包含有NA的行或列。dropna默认情况下会删除包含缺失值的行:
data = pd.DataFrame([[1., 6.5, 3.], [1., NA, NA], [NA, NA, NA], [NA, 6.5, 3.]])
print(data)
a3 = data.dropna()
print(a3)
-----------------------------------------------------------
0 1 2
0 1.0 6.5 3.0
1 1.0 NaN NaN
2 NaN NaN NaN
3 NaN 6.5 3.0
0 1 2
0 1.0 6.5 3.0
传入how=‘all’时,将删除所有值均为NA的行:
a3 = data.dropna(how='all')
print(a3)
-----------------------------------------------------------
0 1 2
0 1.0 6.5 3.0
1 1.0 NaN NaN
3 NaN 6.5 3.0
如果要用同样的方式去删除列,传入参数axis = 1:
data[4] = NA
print(data)
a3 = data.dropna(axis=1, how='all')
print(a3)
-----------------------------------------------------------
0 1 2 4
0 1.0 6.5 3.0 NaN
1 1.0 NaN NaN NaN
2 NaN NaN NaN NaN
3 NaN 6.5 3.0 NaN
0 1 2
0 1.0 6.5 3.0
1 1.0 NaN NaN
2 NaN NaN NaN
3 NaN 6.5 3.0
过滤DataFrame的行的相关方法往往涉及时间序列数据。假设你只想保留包含一定数量的观察值的行。你可以用thresh参数来表示:
df = pd.DataFrame(np.random.randn(7, 3))
df.iloc[:4,1]=NA
df.iloc[:2,2]=NA
print(df)
a1 = df.dropna()
print(a1)
a1 = df.dropna(thresh=2)
print(a1)
-----------------------------------------------------------
0 1 2
0 0.720073 NaN NaN
1 0.767735 NaN NaN
2 -0.281442 NaN -0.296163
3 -1.132465 NaN -0.091511
4 1.839087 0.496217 0.854375
5 -0.283565 1.803889 1.011844
6 -1.226932 1.123181 0.540297
0 1 2
4 1.839087 0.496217 0.854375
5 -0.283565 1.803889 1.011844
6 -1.226932 1.123181 0.540297
0 1 2
2 -0.281442 NaN -0.296163
3 -1.132465 NaN -0.091511
4 1.839087 0.496217 0.854375
5 -0.283565 1.803889 1.011844
6 -1.226932 1.123181 0.540297
1.2 补全缺失值
有时可能需要以多种方式补全”漏洞“,而不是过滤缺失值(也可能丢失其他数据)。
而大多数情况下,主要使用fillna方法来补全缺失值。调用fillna时,你可以使用一个常熟来替代缺失值:
df = pd.DataFrame(np.random.randn(7, 3))
df.iloc[:4,1]=NA
df.iloc[:2,2]=NA
print(df)
a1 = df.fillna(0)
print(a1)
-----------------------------------------------------------
0 1 2
0 -0.329325 NaN NaN
1 0.317079 NaN NaN
2 0.681410 NaN -1.181260
3 -1.520181 NaN -1.147875
4 0.325974 -0.211536 -0.786885
5 -2.235934 -0.243977 -0.002898
6 -1.396350 0.434119 1.040336
0 1 2
0 -0.329325 0.000000 0.000000
1 0.317079 0.000000 0.000000
2 0.681410 0.000000 -1.181260
3 -1.520181 0.000000 -1.147875
4 0.325974 -0.211536 -0.786885
5 -2.235934 -0.243977 -0.002898
6 -1.396350 0.434119 1.040336
在调用fillna时使用字典,你可以为不同列设定不同的填充值:
a2 = df.fillna({1: 0.5, 2: 1})
print(a2)
-----------------------------------------------------------
0 1 2
0 -0.329325 0.500000 1.000000
1 0.317079 0.500000 1.000000
2 0.681410 0.500000 -1.181260
3 -1.520181 0.500000 -1.147875
4 0.325974 -0.211536 -0.786885
5 -2.235934 -0.243977 -0.002898
6 -1.396350 0.434119 1.040336
fillna返回的是一个新的对象,但你也可以修改已经存在的对象:
_ = df.fillna(0,inplace=True)
print(df)
-----------------------------------------------------------
0 1 2
0 -0.329325 0.000000 0.000000
1 0.317079 0.000000 0.000000
2 0.681410 0.000000 -1.181260
3 -1.520181 0.000000 -1.147875
4 0.325974 -0.211536 -0.786885
5 -2.235934 -0.243977 -0.002898
6 -1.396350 0.434119 1.040336
用于重建索引的相同的插值方法也可以用于fillna:
df1 = pd.DataFrame(np.random.randn(6,3))
df1.iloc[2:,1] = NA
df1.iloc[4:,1] = NA
print(df1)
a = df1.fillna(method='ffill')
print(a)
a1 = df1.fillna(method='ffill',limit=2)
print(a1)
-----------------------------------------------------------
0 1 2
0 -0.702226 1.056195 -0.270062
1 0.279172 -1.344906 -0.829725
2 1.465186 NaN -0.496893
3 1.251037 NaN -0.111011
4 -1.290758 NaN NaN
5 0.607567 NaN NaN
0 1 2
0 -0.702226 1.056195 -0.270062
1 0.279172 -1.344906 -0.829725
2 1.465186 -1.344906 -0.496893
3 1.251037 -1.344906 -0.111011
4 -1.290758 -1.344906 -0.111011
5 0.607567 -1.344906 -0.111011
0 1 2
0 -0.702226 1.056195 -0.270062
1 0.279172 -1.344906 -0.829725
2 1.465186 -1.344906 -0.496893
3 1.251037 -1.344906 -0.111011
4 -1.290758 NaN -0.111011
5 0.607567 NaN -0.111011
使用fillna你可以完成很多带有一点创造性的工作。例如,你可以将Series的平均值或中位数用于填充缺失值:
data = pd.Series([1.,NA,3.5,NA,7])
print(data)
a = data.fillna(data.mean())
print(a)
-----------------------------------------------------------
0 1.000000
1 3.833333
2 3.500000
3 3.833333
4 7.000000
dtype: float64
下表则是fillna函数参数参考表:
参数 | 描述 |
---|---|
value | 标量值或字典型对象用于填充缺失值 |
method | 插值方法,如果没有其他参数,默认是‘ffill’ |
axis | 需要填充的值,默认值axis = 0 |
inplace | 修改被调用的对象,而不是生成一个备份 |
limit | 用于前向或后向填充时最大填充范围 |
总结
以上就是今天要讲的内容,本文仅仅简单介绍了pandas中处理缺失值的方式:过滤填充值和填充缺失值。除此之外还有能够处理缺失值的 isnull和notnull方法。下班!!!