数据预处理包括对收集的数据进行数据缺失处理、检测和过滤异常值及移除重复数据等步骤。
5.5.1 数据缺失处理
数据缺失在大部分数据分析应用中都很常见,Pandas使用NaN(Not a number)表示浮点和非浮点数组中的缺失数据。处理缺失数据的方法有四种:dropna,fillna,isnull,notnull。
is(not) null,这一对方法对对象做元素级的应用,然后返回一个布尔型数组,一般可用于布尔型索引。示例代码:
import pandas as pd
s = pd.Series(['abcd', 'efgh', 'ijkl', 'mnop'])
print(s)
print('\n')
print(s.isnull())
运行结果
0 abcd
1 efgh
2 ijkl
3 mnop
dtype: object
0 False
1 False
2 False
3 False
dtype: bool
dropna,对于一个Series,dropna返回一个仅含非空数据和索引值的Series。示例代码:
import pandas as pd
from numpy import nan as NA
sdata = pd.Series([1, NA, 3.5, NA, 7])
print(sdata.dropna())
运行结果:
0 1.0
2 3.5
4 7.0
dtype: float64
对于DataFrame的处理方式,一旦使用drop命令,至少要弃掉一行或一列。解决的方法是通过一个额外的参数,形式如下:
dropna(axis=0, how='any', thresh=None)
axis轴参数可选值为0或1,默认值为0表示以列为标准删除缺失值,1则表示以行为标准删除。how参数可选的值为any或者all,all仅在切片元素全为NA时才抛弃该行(列)。thresh为整数类型,如thresh=3表示一行当中至少有三个NA值才将其保留。假设只想留一部分观察数据,可以用thresh参数实现此目的,示例代码:
import numpy as np
import pandas as pd
from numpy import nan as NA
dfdata = pd.DataFrame(np.random.randn(7,3))
dfdata.ix[:4, 1] = NA
dfdata.ix[:2, 2] = NA
print(dfdata)
print('\n')
print(dfdata.dropna(thresh=2))
运行结果:
0 1 2
0 0.555364 NaN NaN
1 -0.040936 NaN NaN
2 -0.213490 NaN NaN
3 1.142304 NaN 0.038245
4 1.888789 NaN 1.219606
5 1.300171 0.843961 -0.232480
6 -0.457737 0.298572 -0.105454
0 1 2
3 1.142304 NaN 0.038245
4 1.888789 NaN 1.219606
5 1.300171 0.843961 -0.232480
6 -0.457737 0.298572 -0.105454
如果不想滤除缺失的数据,而是通过其他方式填补“空洞”,fillna是最主要的函数。fillna表示对缺失数据进行设定填充,形式如下:
fillna(value=None, method=None, axis=0)
fillna会将缺失值替换为参数value设置的常数。示例代码:
print(dfdata.fillna(value=0))
运行结果:
0 1 2
0 0.555364 0.000000 0.000000
1 -0.040936 0.000000 0.000000
2 -0.213490 0.000000 0.000000
3 1.142304 0.000000 0.038245
4 1.888789 0.000000 1.219606
5 1.300171 0.843961 -0.232480
6 -0.457737 0.298572 -0.105454
而value参数除了基本类型外,还可以使用字典,这样可以实现对不同列填充不同的值。示例代码:
dfdata = pd.DataFrame(np.random.randn(7,3))
dfdata.ix[:4, 1] = NA
dfdata.ix[:2, 2] = NA
print(dfdata)
print('\n')
print(dfdata.fillna(value={1:111,2:222}))
运行结果:
0 1 2
0 0.819655 NaN NaN
1 -0.765497 NaN NaN
2 1.355599 NaN NaN
3 0.174048 NaN 1.496694
4 -1.966648 NaN -0.598936
5 -2.844108 1.175119 0.685596
6 -1.352572 0.575769 0.097997
0 1 2
0 0.819655 111.000000 222.000000
1 -0.765497 111.000000 222.000000
2 1.355599 111.000000 222.000000
3 0.174048 111.000000 1.496694
4 -1.966648 111.000000 -0.598936
5 -2.844108 1.175119 0.685596
6 -1.352572 0.575769 0.097997
除了填充设定的已有值,也可以利用fillna实现许多别的功能,比如可以传入Series的平均值或中位数,示例代码:
sdata = pd.Series([1.0, NA, 3.5, NA, 7])
print(sdata)
print('\n')
print(sdata.fillna(value=sdata.mean()))
print('\n')
print(sdata.fillna(value=sdata.median()))
运行结果:
0 1.0
1 NaN
2 3.5
3 NaN
4 7.0
dtype: float64
0 1.000000
1 3.833333
2 3.500000
3 3.833333
4 7.000000
dtype: float64
0 1.0
1 3.5
2 3.5
3 3.5
4 7.0
dtype: float64
5.5.2 检测和过滤异常值
异常值(outlier)的过滤或变换运算在很大程度上就是数组运算。如在形为(1000,4)的标准正态分布数组中,找出某一列中绝对值大小超过3的项,并做去除(drop)操作,示例代码:
data = pd.DataFrame(np.random.randn(1000,4))
print(data.describe())
print('\n')
col=data[3]
print(col[np.abs(col)>3])
运行结果:
0 1 2 3
count 1000.000000 1000.000000 1000.000000 1000.000000
mean -0.012398 0.004329 -0.044018 0.006960
std 1.019043 1.015391 1.035915 0.991017
min -3.026647 -2.816855 -3.509064 -2.926084
25% -0.702266 -0.688002 -0.768781 -0.694160
50% -0.026979 -0.033296 -0.074148 -0.005151
75% 0.643268 0.715220 0.657117 0.690144
max 3.386927 3.728271 3.336689 3.009779
964 3.009779
Name: 3, dtype: float64
以上结果是找出第3列绝对值大于3的行标索引。如果要找出任意列绝对值超过3的值的所有行标,示例代码:
print(data[(np.abs(data)>3).any(1)])
运行结果:
0 1 2 3
3 0.880152 -1.845595 -3.062386 -0.377484
170 0.330547 3.728271 1.038236 0.096751
175 -3.026647 -0.221601 0.488011 -1.296075
205 -1.889809 3.086899 0.240812 -0.819182
341 0.689361 -0.726927 3.336689 -0.399356
489 0.583099 -0.892590 -3.509064 -0.086007
565 -0.203513 -0.242532 -3.022158 1.225842
815 -0.172945 -1.968579 3.015868 0.528105
835 3.386927 0.144197 -0.515101 -1.268720
964 0.652401 1.830282 -1.054405 3.009779
通过DataFrame的drop()方法,可以对异常值进行删除操作,示例代码:
data.drop(data[np.abs(data)>3])
5.5.3
DataFrame的duplicated()方法返回一个布尔型Series,表示各行是否是重复行。示例代码:
data = pd.DataFrame({'k1':['one']*3+['two']*4, 'k2':[1, 1, 2, 2, 3, 3, 4]})
print(data)
print('\n')
print(data.duplicated())
运行结果:
k1 k2
0 one 1
1 one 1
2 one 2
3 two 2
4 two 3
5 two 3
6 two 4
0 False
1 True
2 False
3 False
4 False
5 True
6 False
dtype: bool
与此相关的还有一个drop_duplicates()方法,它用于返回一个移除了重复行的DataFrame,示例代码:
data = pd.DataFrame({'k1':['one']*3+['two']*4, 'k2':[1, 1, 2, 2, 3, 3, 4]})
print(data)
print('\n')
print(data.drop_duplicates())
运行结果:
k1 k2
0 one 1
1 one 1
2 one 2
3 two 2
4 two 3
5 two 3
6 two 4
k1 k2
0 one 1
2 one 2
3 two 2
4 two 3
6 two 4
上面的两个方法会默认判断全部列,也可以指定部分列进行重复项判断,假设还有一列值,而只希望根据k1列过滤重复项。示例代码:
data = pd.DataFrame({'k1':['one']*3+['two']*4, 'k2':[1, 1, 2, 2, 3, 3, 4]})
data['v1']=range(7)
print(data)
print('\n')
print(data.drop_duplicates(['k1']))
运行结果:
k1 k2 v1
0 one 1 0
1 one 1 1
2 one 2 2
3 two 2 3
4 two 3 4
5 two 3 5
6 two 4 6
k1 k2 v1
0 one 1 0
3 two 2 3
duplicated和drop_duplicates默认保留第一个出现的值的组合。传入take_last=True则保留最后一个,示例代码:
data = pd.DataFrame({'k1':['one']*3+['two']*4, 'k2':[1, 1, 2, 2, 3, 3, 4]})
data['v1']=range(7)
print(data)
print('\n')
print(data.drop_duplicates(['k1','k2'], take_last=True))
运行结果:
k1 k2 v1
0 one 1 0
1 one 1 1
2 one 2 2
3 two 2 3
4 two 3 4
5 two 3 5
6 two 4 6
k1 k2 v1
1 one 1 1
2 one 2 2
3 two 2 3
5 two 3 5
6 two 4 6