Python与数据科学——基于Pandas的数据清洗
对于数据分析而言,数据是显而易见的核心。但是并不是所有的数据都是有用的,大多数数据是参差不齐的,概念层次不清的,数量级不同的,这就给后续的数据分析和数据挖掘带来了极大的麻烦,甚至导致错误的结论。所以有必要对数据进行预处理。
数据预处理( data preprocessing)是指在对数据进行数据挖掘以前,先对原始数据进行必要的清洗集成、转换、离散和归约等一系列的处理工作,以达到挖掘算法进行知识获取研究所要求的最低规范和标准。通常数据预处理包含四个部分:数据清洗、数据集成、数据变换和数据规约。今天我们就一起看看数据处理的第一步——数据清理的方法吧~~
目录
一、数据清洗简介
二、数据清洗模型——高端玩家
三、数据清洗基本方法——打怪必备技能
A 缺失数据处理 B 相似重复对象检测 C 异常数据处理 D 逻辑错误检测 E 不一致数据一、数据清洗简介
Brief introduction to data cleaning
数据清洗指的是填充缺失数据、消除噪声数据等操作,主要是通过分析“脏数据”的产生原因和存在形式,利用现有的数据挖掘手段和方法去清洗“脏数据”,将“脏数据”转化为满足数据质量要求或应用要求的数据,从而提高数据集的质量,满足现阶段数据分析的需求。
其处理过程如图所示:
二、数据清洗模型——高端玩家
Data cleaning model - high-end player
在数据清洗问题研究的过程中,人们总结并提出了一些数据清洗模型,用于企业和生产管理主要的数据清洗模型包括以下几类:
A. Trillium的过程模型。它是由 Harte Hanks Data Technologies的 Trillium Softwar System部门创建的企业范围的数据清洗工具。主要处理常见数据包括名称头衔、电话号码、身份证号码,自由文本等,它可接受多种方式格式化和编码的数据,具有可伸缩性,独立于平台并适合多种环境。此模型主要应用于专业的金融、保险等行业。
B AJAX的过程模型。该模型是逻辑层面的模型,以数据的业务逻辑流程作为主要的检测过程,通过数据映射、匹配、聚集操作、数据合并以及数据视图显示5个过程进行数据清洗。该模型从数据输入开始检测,直到数据输出结束检测,检测范围囊括了数据流的整个过程,主要应用在数据挖据方面。
这里简单介绍独热编码(One-Hot Encoding)
在很多机器学习任务中,特征并不总是连续值,而有可能是分类值。例如,考虑一下的三个特征:
["male", "female"]
["from Europe", "from US", "from Asia"]
["uses Firefox", "uses Chrome", "uses Safari", "uses Internet Explorer"]
如果将上述特征用数字表示,效率会高很多。例如:
["male", "from US", "uses Internet Explorer"]
表示为[0, 1, 3]
["female", "from Asia", "uses Chrome"]
表示为[1, 2, 1]
但是,即使转化为数字表示后,上述数据也不能直接用在我们的分类器中。因为,分类器往往默认数据数据是连续的,并且是有序的。但是,按照我们上述的表示,数字并不是有序的,而是随机分配的。
为了解决上述问题,其中一种可能的解决方法是采用独热编码(One-Hot Encoding)。
独热编码即 One-Hot 编码,又称一位有效编码,其方法是使用N位状态寄存器来对N个状态进行编码,每个状态都由他独立的寄存器位,并且在任意时候,其中只有一位有效。
例如:
自然状态码为:
000,001,010,011,100,101
独热编码为:000001,000010,000100,001000,010000,100000
可以这样理解,对于每一个特征,如果它有m个可能值,那么经过独热编码后,就变成了m个二元特征。并且,这些特征互斥,每次只有一个激活。因此,数据会变成稀疏的。
这样做的好处主要有:
○ 解决了分类器不好处理属性数据的问题
○ 在一定程度上也起到了扩充特征的作用
我们基于Python和Scikit-learn写一个简单的例子:
from sklearn import preprocessing enc = preprocessing.OneHotEncoder() enc.fit([[0, 0, 3], [1, 1, 0], [0, 2, 1], [1, 0, 2]]) enc.transform([[0, 1, 3]]).toarray()
输出结果:
array([[ 1., 0., 0., 1., 0., 0., 0., 0., 1.]])
处理离散型特征和连续型特征并存的情况,如何做归一化。参考博客进行了总结(后文联系作者认可):
https://www.quora.com/What-are-good-ways-to-handle-discrete-and-continuous-inputs-together
总结
总结如下:
1、拿到获取的原始特征,必须对每一特征分别进行归一化,比如,特征A的取值范围是[-1000,1000],特征B的取值范围是[-1,1].
如果使用logistic回归,w1*x1+w2*x2,因为x1的取值太大了,所以x2基本起不了作用。
所以,必须进行特征的归一化,每个特征都单独进行归一化。
2、连续型特征归一化的常用方法:
2.1:通过方程:x = (2x - max - min)/(max - min).线性放缩到[-1,1]
2.2:利用x = (x - u)/s.放缩到均值为0,方差为1
3、离散型特征的处理方法:
对于离散的特征基本就是按照one-hot编码,该离散特征有多少取值,就用多少维来表示该特征。
为什么使用one-hot编码来处理离散型特征,这是有理由的,不是随便拍脑袋想出来的!!!具体原因,分下面几点来阐述:
(1)Why do we binarize categorical features?
使用one-hot编码,将离散特征的取值扩展到了欧式空间,离散特征的某个取值就对应欧式空间的某个点。
(2)利于机器学习算法
.将离散特征通过one-hot编码映射到欧式空间,是因为,在回归,分类,聚类等机器学习算法中,特征之间距离的计算或相似度的计算是非常重要的,而我们常用的距离或相似度的计算都是在欧式空间的相似度计算,计算余弦相似性,基于的就是欧式空间。
(3)让特征之间的距离计算更加合理
比如,有一个离散型特征,代表工作类型,该离散型特征,共有三个取值,不使用one-hot编码,其表示分别是x_1 = (1), x_2 = (2), x_3 = (3)。两个工作之间的距离是,(x_1, x_2) = 1, d(x_2, x_3) = 1, d(x_1, x_3) = 2。那么x_1和x_3工作之间就越不相似吗?显然这样的表示,计算出来的特征的距离是不合理。那如果使用one-hot编码,则得到x_1 = (1, 0, 0), x_2 = (0, 1, 0), x_3 = (0, 0, 1),那么两个工作之间的距离就都是sqrt(2).即每两个工作之间的距离是一样的,显得更合理。
离散特征进行one-hot编码后,编码后的特征,其实每一维度的特征都可以看做是连续的特征。就可以跟对连续型特征的归一化方法一样,对每一维特征进行归一化。比如归一化到[-1,1]或归一化到均值为0,方差为1
三、数据清洗基本方法——打怪必备技能
the basic method of data cleaning
数据清洗是提高数据质量技术中的主要研究内容,主要针对实例层的数据进行清洗。清洗内容主要包括:缺失数据处理、相似重复对象检测、异常数据处理、逻辑错误检测和不一致数据等。
下面分别介绍这5种清洗思路:
A 缺失数据处理
Missing data processing
缺失值问题是真实数据集中一种普遍现象,一种处理缺失值的简单方法是忽略含有缺失值的实例或属性,但是浪费的数据可能相当多,且不完整的数据集可能带来统计分析的偏差。所以,需要根据数据间的关联性估计出准确的缺失值,并通过合适的方法对缺失值进行填充。可以采用人工填写空缺值法,即手工检测并填写属性值,对于有些不影响整体数据情况的空值可以采用忽略元组法。
在有些特殊情况中,也可以使用属性的平均值、中间值、最大值、最小值或更为复杂的概率统计函数值填充空缺值法。如果拥有合适的填补方法,则能得到高质量的数据,数据挖掘结果也会得到改善。
1.0找到缺失值所在位置
这里用到了一个函数——isnull,这一方法对对象元素应用后返回一个布尔型数组,它可以作为布尔型索引,方便下一步操作。
注:Pandas使用浮点值 not a number(NaN)表示浮点和非浮点数组中的缺失数据。同时,Python当中的None也会被当做NA处理。
编写如下使用到了isnull的程序:
from pandas import Series, DataFrameimport numpy as np# 利用pandas进行数据处理 s = Series([1, 3, 5, 7, 9, np.nan, None, ]) print(s.isnull())
结果:
0 False
1 False
2 False
3 False
4 False
5 True
6 True
dtype: bool
2.0对缺失值的处理
通过isnull找到了缺失值的位置,我们可以进行下一步的处理,处理缺失值的思路和方法有很多,比如直接丢弃,填充指定数据等方法。
①丢弃缺失值。
介绍函数——dropna()。对于一个series,它返回一个仅含非空数据和索引的series;对于一个DataFrame,事情变得复杂起来,因为DataFrame既有行又有列,drop时是扔掉行还是列呢?事实上,dropna方法当中有一些参数可以控制操作。
完整的方法调用为:dropna(axis=0, how=’any’, whresh=None),其中axis默认参数为0,表示行。how参数可选的值有any和all:all仅在切片元素全为NA时猜抛弃该行(列),thresh参数的作用是,比如,thresh=8,会在一行(列)中至少有8个非NA值时保留该行(列)。
Eg:
from pandas import Series, DataFrame import numpy as np # 利用pandas进行数据处理 s = Series([1, 3, 5, 7, 9, np.nan, None]) print ('serise类型删去空值:'+'\n'+str(s.dropna())+'\n') d = DataFrame(np.array(list(s)*3).reshape(7, 3)) print ('d DataFrame初始状态:') print (d); print('\n') print ('默认参数')print (d.dropna()); print ('\n') print ('删去列') print (d.dropna(1));print ('\n') print ('all参数') print (d.dropna(0, 'all'))
结果:
serise类型删去空值:
0 1.0
1 3.0
2 5.0
3 7.0
4 9.0
dtype: float64
d DataFrame初始状态:
0 1 2
0 1.0 3.0 5.0
1 7.0 9.0 NaN
2 NaN 1.0 3.0
3 5.0 7.0 9.0
4 NaN NaN 1.0
5 3.0 5.0 7.0
6 9.0 NaN NaN
默认参数
0 1 2
0 1.0 3.0 5.0
3 5.0 7.0 9.0
5 3.0 5.0 7.0
删去列
Empty DataFrame
Columns: []
Index: [0, 1, 2, 3, 4, 5, 6]
all参数
0 1 2
0 1.0 3.0 5.0
1 7.0 9.0 NaN
2 NaN 1.0 3.0
3 5.0 7.0 9.0
4 NaN NaN 1.0
5 3.0 5.0 7.0
6 9.0 NaN NaN
Process finished with exit code 0
②填入数据
对于大多数情况,我们并不想全部丢弃缺失值所在行(列)的全部数据,所以更普遍的情况是我们会采用填入数据的思路。在这种思路下,fillna为主要的方法。它可以实现在dataframe和series当中填入缺失值。
例如:d.fillna(0)
d.fillna(d.mean()) #传入d的平均值
d.dillna({1:0.5, 2:5.0, 4:6.4, 6:7.0 }) # 使用字典来对不同索引下的行的缺失值填充
print('d DataFrame初始状态:') print(d); print('\n') print(d.fillna(0)); print('\n') print(d.fillna(d.mean())) ; print('\n') #传入d的平均值 print(d.fillna({0: 1, 1: 0.5, 2: 5.0})); print('\n') # 使用字典来对不同索引下的行的缺失值填充
结果:
d DataFrame初始状态:
0 1 2
0 1.0 3.0 5.0
1 7.0 9.0 NaN
2 NaN 1.0 3.0
3 5.0 7.0 9.0
4 NaN NaN 1.0
5 3.0 5.0 7.0
6 9.0 NaN NaN
0 1 2
0 1.0 3.0 5.0
1 7.0 9.0 0.0
2 0.0 1.0 3.0
3 5.0 7.0 9.0
4 0.0 0.0 1.0
5 3.0 5.0 7.0
6 9.0 0.0 0.0
0 1 2
0 1.0 3.0 5.0
1 7.0 9.0 5.0
2 5.0 1.0 3.0
3 5.0 7.0 9.0
4 5.0 5.0 1.0
5 3.0 5.0 7.0
6 9.0 5.0 5.0
0 1 2
0 1.0 3.0 5.0
1 7.0 9.0 5.0
2 1.0 1.0 3.0
3 5.0 7.0 9.0
4 1.0 0.5 1.0
5 3.0 5.0 7.0
6 9.0 0.5 5.0
Process finished with exit code 0
B 相似重复数据检测
Similar duplicate data detection
对多数据源和单数据源数据进行集成时,多个记录代表同一实体的现象经常存在,这些记录称为重复记录,同时,有些记录并非完全重复,其个别字段存在一定差别,但表示的却是同一对象此类记录即为相似重复记录,相似重复记录检测是数据清洗研究的重要方面,在信息集成系统中,重复记录不仅导致数据冗余,浪费了网络带宽和存储空间,还提供给用户很多相似信息,起到误导作用。重复数据检测主要分为两个方面:基于字段和基于记录的重复检测。
高端一些的思路是基于算法实现的。比如说,基于字段的重复检测算法主要包括编辑距离(如 Smith Waterman、Jaro)算法、树编辑距离算法、 TI Similarity相似匹配算法、 Cosine相似度函数算法等。
排序邻居算法(SN)基于排序比较的思想,已得到广泛使用。利用依赖图的概念,计算数据表中的关键属性,根据关键属性值将记录集划分为小记录集,在每个小记录集中进行相似重复记录检测。分割法,将某一字符串分割成几个组成部分来处理,一定程度上能够解决同一对象多种表示形式的问题。
删除重复数据可以通过drop.duplicates()来完成,同时,通过向函数内传入参数可以达到更精准的coder想要的效果。
data = DataFrame({'学生姓名': ['smelly cat']+['JSnow']*2+['Pikachu']*2+['smelly cat'], '分数': [8, 10, 6, 5, 4, 8]}) print(data) print(data.drop_duplicates()) print(data.drop_duplicates(['学生姓名'])) print (‘大于8的数据'); print(data[data > 0.8].any(1))
结果:
学生姓名 分数
0 smelly cat 8
1 JSnow 10
2 JSnow 6
3 Pikachu 5
4 Pikachu 4
5 smelly cat 8
学生姓名 分数
0 smelly cat 8
1 JSnow 10
2 JSnow 6
3 Pikachu 5
4 Pikachu 4
学生姓名 分数
0 smelly cat 8
1 JSnow 10
3 Pikachu 5
Process finished with exit code 0
C 异常数据处理
Abnormal data processing
异常数据指数据库或数据仓库中不符合一般规律的数据对象,又称为孤立点。异常数据可由执行失误造成,也可能因设备故障导致。异常数据可能是去掉的噪声,也可能是含有重要信息的数据单元。异常数据的探测主要有基于统计学、基于距离和基于偏离3类方法。采用数据审时的方法可以实现异常数据的自动化检测,该方法也称为数据质量挖掘(DOQM)。DQM主要由2步构成:第一步,采用数理统计方法对数据分布进行概化描述,自动获得数据的总体分布特征;第二步针对特定的数据质量问题进行挖掘以发现数据异常。
from pandas import Series, DataFrame import numpy as np # 利用pandas进行数据处理 data = DataFrame(np.random.randn(5, 3)) print (data) print(data.describe()); print('\n') col_3 = data[2] print ('第三列当中大于0.8的数据'); print (col_3[col_3 > 0.8]); print ('\n') print ('全部范围内大于0.8的数据'); print (data[data > 0.8].any (1))
结果:
0 1 2
0 0.647887 -0.057782 1.306196
1 0.485350 -0.642165 -1.180494
2 -0.959784 0.493802 0.009916
3 -0.618638 -0.470694 0.109201
4 1.396253 -1.092738 1.261206
0 1 2
count 5.000000 5.000000 5.000000
mean 0.190214 -0.353915 0.301205
std 0.965380 0.601852 1.030626
min -0.959784 -1.092738 -1.180494
25% -0.618638 -0.642165 0.009916
50% 0.485350 -0.470694 0.109201
75% 0.647887 -0.057782 1.261206
max 1.396253 0.493802 1.306196
第三列当中大于0.8的数据
0 1.306196
4 1.261206
Name: 2, dtype: float64
全部范围内大于0.8的数据
0 True
1 False
2 False
3 False
4 True
dtype: bool
Process finished with exit code 0
D 逻辑错误检测
Logical error detection
数据逻辑错误指数据集中的属性值与实际值不符,或违背了业务规则或逻辑。在实际信息系统中,对于具体应用采用一定的方法解决数据逻辑错误问题,具有实际意义。不合法的属性值是一种常见的数据逻辑错误,如某人的出生日期为“1986/13/25”,超出了月份的最大值,通过瓶测字段中各属性值有效数值范围,可以判断该值是否正确。属性错误值检测主要包括统计法,类方法以及关联规则方法,这些方法都是以统计和总结规律的方式计算并查找错误值。Feli于1976年提出了一个严格的形式化模型— Fellegi-Hot模型。其主要思路是:在具体的应用领域根据相应领域知识制定约束规则,利用数学方法获得规则闭集,并自动判断字段值是否违反规则约束,该方法数学基础严密,自动生成规则,在审计和统计领域得到了广泛应用。
这一设计可以在数据库当中可以体现。
E 不一致数据
Inconsistent data
多数据源数据集成时,由于不同数据源对同一现实事物可能存在不一致的表示,从而产生不一致的数据。不一致数据一般通过手工或者自动化方式检查。
常见的不一致数据有:(1)包含大量空数据值的列,如个人对某些敏感信息回避,故意漏填部分信息;(2)包含过多或者过少的单状态的列,如一对一关系的列,或者仅包含一个值的列;(3)远离或超出某列正态分布的记录如出现负工资和课程零学时的问题;(4)不符合特定格式的行,如不同的日期格式;(5)同一记录的不同属性比较时,缺失意义的列,如客户选购某产品的日期早于该顾客的出生日期。目前,常用的消除数据不一致的方法有排序、融合和基于规则3种方法。
作者有话说:
今天我们的小介绍就到这里啦~
大家快去上机做练习吧!
本期作者:刘腾翔
本期编辑校对:李嘉楠