二、数据预处理
2.1数据清洗
数据清洗主要是删除原始数据集中的无关数据、重复数据,平滑噪声数据,筛选掉与挖掘主题无关的数据,处理缺失值、异常值等。
2.1.1缺失值处理
处理缺失值的方法可分为3类:删除记录、数据插补和不处理
- 插补方法 均值/中位数/众数插补
根据属性值的类型,用该属性取值的平均数/中位数/众数进行插补
- 使用固定值
将缺失的属性值用一个常量替换。如广州一个工厂普通外来务工人员的“基本工资”属性的空缺值可以用2015年广州市普通外来务工人员工资标准1895元/月,该方法就是使用固定值
- 最近临插补法
在记录中找到与缺失样本最接近的样本的该属性值插补
- 同归方法
对带有缺失值的变量,根据已有数据和与其有关的其他变量(因变量)的数据建立拟合模型来预测缺失的属性值
- 插值法
利用已知点建立合适的插值函数f(x),未知值由对应点Xi求出的函数值f(Xi)近似代替
#拉格朗日插值代码
import pandas as pd #导入数据分析库Pandas
from scipy.interpolate import lagrange #导入拉格朗日插值函数
inputfile = '../data/catering_sale.xls' #销量数据路径
outputfile = '../tmp/sales.xls' #输出数据路径
data = pd.read_excel(inputfile) #读入数据
data[u'销量'][(data[u'销量'] < 400) | (data[u'销量'] > 5000)] = None #过滤异常值,将其变为空值
#自定义列向量插值函数
#s为列向量,n为被插值的位置,k为取前后的数据个数,默认为5
def ployinterp_column(s, n, k=5):
y = s[list(range(n-k, n)) + list(range(n+1, n+1+k))] #取数
y = y[y.notnull()] #剔除空值
return lagrange(y.index, list(y))(n) #插值并返回插值结果
#逐个元素判断是否需要插值
for i in data.columns:
for j in range(len(data)):
if (data[i].isnull())[j]: #如果为空即插值。
data[i][j] = ployinterp_column(data[i], j)
data.to_excel(outputfile) #输出结果,写入文件
2.1.2异常值处理
在数据预处理时,异常值是否剔除,需视具体情况而定,因为有些异常值可能蕴含着有用的信息
异常值处理方法
- 删除含有异常值的记录
直接将含有异常值的记录删除
- 视为缺失值
将异常值视为缺失值,利用缺失值处理的方法进行处理
- 平均值修正
可用前后两个观测值的平均值修正该异常值
- 不处理
直接在具有异常值的数据集上进行挖掘建模
将含有异常值的记录直接删除的方法简单易行,但缺点也很明显,在观测值很少的情况下,这种删除会造成样本量不足,可能会改变变量的原有分布,从而造成分析结果的不准确。视为缺失值处理的好处是可以利用现有变量的信息,对异常值(缺失值)进行填补。在很多情况下,要先分析异常值出现的可能原因,再判断异常值是否应该舍弃,如果是正确的数据,可以直接在具有异常值的数据集上进行挖掘建模
2.2数据集成
数据挖掘需要的数据往往分布在不同的数据源中,数据集成就是将多个数据源合并存放在一个一致的数据存储(如数据仓库)中的过程。 在数据集成时,来自多个数据源的现实世界实体的表达形式是不一样的,有可能不匹配,要考虑实体识别问题和属性冗余问题,从而将源数据在最低层上加以转换、提炼和集成
2.2.1实体识别
实体识别是指从不同数据源识别出现实世界的实体
(1)同名异义
(2)异名同义
(3)单位不统一
2.2.2冗余属性识别
数据集成往往导致数据冗余,例如:
1)同一属性多次出现
2)同一属性命名不一致导致重复
仔细整合不同源数据能减少甚至避免数据冗余与不一致,从而提高数据挖掘的速度和质量。对于冗余属性要先分析,检测到后再将其删除。
有些冗余属性可以用相关分析检测。给定两个数值型的属性A和B,根据其属性值,用相关系数度量一个属性在多大程度上蕴含另一个属性
2.3数据变换
数据变换主要是对数据进行规范化处理,将数据转换成“适当的”形式,以适用于挖掘任务及算法的需要
2.3.1简单的函数变换
简单函数变换是对原始数据进行某些数学函数变换,常用的变换包括平方、开方、取对数、差分运算等
简单的函数变换常用来将不具有正态分布的数据变换成具有正态分布的数据。在时间序列分析中,有时简单的对数变换或者差分运算就可以将非平稳序列转换成平稳序列。在数据挖掘中,简单的函数变换可能更有必要,比如个人年收入的取值范围为10000元到10亿元,这是一个很大的区间,使用对数变换对其进行压缩是常用的一种变换处理方法。
2.3.2规范化
数据规范化(归一化)处理是数据挖掘的一项基础工作。不同评价指标往往具有不同的量纲,数值间的差别可能很大,不进行处理可能会影响到数据分析的结果。为了消除指标之间的量纲和取值范围差异的影响,需要进行标准化处理,将数据按照比例进行缩放,使之落入一个特定的区域,便于进行综合分析。如将工资收入属性值映射到[-1,1]或者[0,1]内。
数据规范化对于基于距离的挖掘算法尤为重要。
(1)最小-最大规范化
最小-最大规范化也称为离差标准化,是对原始数据的线性变换,将数值值映射到[0,1] 之间.
保留了原来数据中存在的关系,是消除量纲和数据取值范围影响的最简单方法。
缺点:
这种处理方法的缺点是若数值集中且某个数值很大,则规范化后各值会接近于0,并且将会相差不大。若将来遇到超过目前属性[min,max]取值范围的时候,会引起系统出错,需要重新确定min和max。
(2)零-均值规范化
零-均值规范化也称标准差标准化,经过处理的数据的均值为0,标准差为1。
这是当前用得最多的数据标准化方法
(3)小数定标规范化
通过移动属性值的小数位数,将属性值映射到[-1,1]之间,移动的小数位数取决于属性值绝对值的最大值.
#数据规范化
import pandas as pd
import numpy as np
datafile = '../data/normalization_data.xls' #参数初始化
data = pd.read_excel(datafile, header = None) #读取数据
(data - data.min())/(data.max() - data.min()) #最小-最大规范化
"""
0 1 2 3
0 0.074380 0.937291 0.923520 1.000000
1 0.619835 0.000000 0.000000 0.850941
2 0.214876 0.119565 0.813322 0.000000
3 0.000000 1.000000 1.000000 0.563676
4 1.000000 0.942308 0.996711 0.804149
5 0.264463 0.838629 0.814967 0.909310
6 0.636364 0.846990 0.786184 0.929571
"""
(data - data.mean())/data.std() #零-均值规范化
"""
0 1 2 3
0 -0.905383 0.635863 0.464531 0.798149
1 0.604678 -1.587675 -2.193167 0.369390
2 -0.516428 -1.304030 0.147406 -2.078279
3 -1.111301 0.784628 0.684625 -0.456906
4 1.657146 0.647765 0.675159 0.234796
5 -0.379150 0.401807 0.152139 0.537286
6 0.650438 0.421642 0.069308 0.595564
"""
data/10**np.ceil(np.log10(data.abs().max())) #小数定标规范化
"""
0 1 2 3
0 0.078 0.521 0.602 0.2863
1 0.144 -0.600 -0.521 0.2245
2 0.095 -0.457 0.468 -0.1283
3 0.069 0.596 0.695 0.1054
4 0.190 0.527 0.691 0.2051
5 0.101 0.403 0.470 0.2487
6 0.146 0.413 0.435 0.2571
"""
2.3.3连续属性离散化
一些数据挖掘算法,特别是某些分类算法(如ID3算法、Apriori算法等),要求数据是分类属性形式。这样,常常需要将连续属性变换成分类属性,即连续属性离散化。
1.离散化的过程
连续属性的离散化就是在数据的取值范围内设定若干个离散的划分点,将取值范围划分为一些离散化的区间,最后用不同的符号或整数值代表落在每个子区间中的数据值。所以,离散化涉及两个子任务:确定分类数以及如何将连续属性值映射到这些分类值。
2.常用的离散化方法
常用的离散化方法有等宽法、等频法和(一维)聚类。
(1)等宽法
将属性的值域分成具有相同宽度的区间,区间的个数由数据本身的特点决定,或者由用户指定,类似于制作频率分布表。
(2)等频法
将相同数量的记录放进每个区间。 这两种方法简单,易于操作,但都需要人为地规定划分区间的个数。同时,等宽法的缺点在于它对离群点比较敏感,倾向于不均匀地把属性值分布到各个区间。有些区间包含许多数据,而另外一些区间的数据极少,这样会严重损坏建立的决策模型。等频法虽然避免了上述问题的产生,却可能将相同的数据值分到不同的区间以满足每个区间中固定的数据个数。
2.3.4属性构造
在数据挖掘的过程中,为了提取更有用的信息,挖掘更深层次的模式,提高挖掘结果的精度,我们需要利用已有的属性集构造出新的属性,并加入到现有的属性集合中。
比如,进行防窃漏电诊断建模时,已有的属性包括供入电量、供出电量(线路上各大用户用电量之和)。理论上供入电量和供出电量应该是相等的,但是由于在传输过程中存在电能损耗,使得供入电量略大于供出电量,如果该条线路上的一个或多个大用户存在窃漏电行为,会使得供入电量明显大于供出电量。
反过来,为了判断是否有大用户存在窃漏电行为,可以构造出一个新的指标一线损率,该过程就是构造属性。新构造的属性线损率按如下公式计算。 线损率=(供入电量-供出电量)/供入电量 × 100%
线损率的正常范围一般在3%~15%,如果远远超过该范围,就可以认为该条线路的大用户很可能存在窃漏电等用电异常行为
#线损率属性构造
import pandas as pd
#参数初始化
inputfile= '../data/electricity_data.xls' #供入供出电量数据
outputfile = '../tmp/electricity_data.xls' #属性构造后数据文件
data = pd.read_excel(inputfile) #读入数据
data[u'线损率'] = (data[u'供入电量'] - data[u'供出电量'])/data[u'供入电量']
data
"""
供入电量 供出电量 线损率
0 986 912 0.075051
1 1208 1083 0.103477
2 1108 975 0.120036
3 1082 934 0.136784
4 1285 1102 0.142412
"""
2.3.5小波变换
主要用于信号分析处理
2.4数据规约
在大数据集上进行复杂的数据分析和挖掘需要很长的时间,数据规约产生更小但保持原数据完整性的新数据集。在规约后的数据集上进行分析和挖掘将更有效率。
数据规约的意义在于:
降低无效、错误数据对建模的影响
提高建模的准确性
少量且具代表性的数据将大幅缩减数据挖掘所需的时间
降低储存数据的成本
2.4.1属性规约
属性规约通过属性合并来创建新属性维数,或者直接通过删除不相关的属性(维)来减少数据维数,从而提高数据挖掘的效率、降低计算成本。
属性规约的目标是寻找出最小的属性子集并确保新数据子集的概率分布尽可能地接近原来数据集的概率分布。
主成分分析
sklearn.decomposition.PCA(n_components=None,copy=True,whiten=False)
参数说明: (1)n_components意义:PCA算法中所要保留的主成分个数n,也即保留下来的特征个数n。
类型:int或者string,缺省时默认为None,所有成分被保留。赋值为int,比如n_components=1,将把原始数据降到一个维度。赋值为string,
比如n_components=’mle’,将自动选取特征个数n,使得满足所要求的方差百分比。
(2)copy类型:bool,True或者False,缺省时默认为True。
意义:表示是否在运行算法时,将原始训练数据复制一份。若为True,则运行PCA算法后,原始训练数据的值不会有任何改变,因为是在原始数据的副本上进行运算;
若为False,则运行PCA算法后,原始训练数据的值会改,因为是在原始数据上进行降维计算。
(3)whiten类型:bool,缺省时默认为False。意义:白化,使得每个特征具有相同的方差。
#主成分分析 降维
import pandas as pd
#参数初始化
inputfile = '../data/principal_component.xls'
outputfile = '../tmp/dimention_reducted.xls' #降维后的数据
data = pd.read_excel(inputfile, header = None) #读入数据
from sklearn.decomposition import PCA
pca = PCA()
pca.fit(data)
pca.components_ #返回模型的各个特征向量
"""
array([[ 0.56788461, 0.2280431 , 0.23281436, 0.22427336, 0.3358618 ,
0.43679539, 0.03861081, 0.46466998],
[ 0.64801531, 0.24732373, -0.17085432, -0.2089819 , -0.36050922,
-0.55908747, 0.00186891, 0.05910423],
[-0.45139763, 0.23802089, -0.17685792, -0.11843804, -0.05173347,
-0.20091919, -0.00124421, 0.80699041],
[-0.19404741, 0.9021939 , -0.00730164, -0.01424541, 0.03106289,
0.12563004, 0.11152105, -0.3448924 ],
[-0.06133747, -0.03383817, 0.12652433, 0.64325682, -0.3896425 ,
-0.10681901, 0.63233277, 0.04720838],
[ 0.02579655, -0.06678747, 0.12816343, -0.57023937, -0.52642373,
0.52280144, 0.31167833, 0.0754221 ],
[-0.03800378, 0.09520111, 0.15593386, 0.34300352, -0.56640021,
0.18985251, -0.69902952, 0.04505823],
[-0.10147399, 0.03937889, 0.91023327, -0.18760016, 0.06193777,
-0.34598258, -0.02090066, 0.02137393]])
"""
pca.explained_variance_ratio_ #返回各个成分各自的方差百分比
"""
array([7.74011263e-01, 1.56949443e-01, 4.27594216e-02, 2.40659228e-02,
1.50278048e-03, 4.10990447e-04, 2.07718405e-04, 9.24594471e-05])
"""
2.4.2数值规约
数值规约指通过选择替代的、较小的数据来减少数据量,包括有参数方法和无参数方法两类。有参数方法是使用一个模型来评估数据,只需存放参数,而不需要存放实际数据,例如回归(线性回归和多元回归)和对数线性模型(近似离散属性集中的多维概率分布)。无参数方法就需要存放实际数据,例如直方图、聚类、抽样(采样)。
(1)直方图
(2)聚类
(3)抽样
2.5Python主要数据预处理函数
(1)interpolate
1)功能:interpolate是Scipy的一个子库,包含了大量的插值函数,如拉格朗日插值、样条插值、高维插值等。使用前需要用from scipy.interpolate import *引入相应的插值函数,读者应该根据需要到官网查找对应的函数名。
2)使用格式:f=scipy.interpolate.lagrange(x,y)。这里仅仅展示了一维数据的拉格朗日插值的命令,其中x,y为对应的自变量和因变量数据。插值完成后,可以通过f(a)计算新的插值结果
(2)unique
1)功能:去除数据中的重复元素,得到单值元素列表。它既是Numpy库的一个函数(np.unique()),也是Series对象的一个方法。
2)使用格式:
np.unique(D),D是一维数据,可以是list、array、Series
D.unique(),D是Pandas的Series对象。
3)实例:求向量A中的单值元素,并返回相关索引。
>>>D=pd.Series([1,1,2,3,5])
>>>D.unique()
array([1,2,3,5],dtype=int64)
>>>np.unique(D)
array([1,2,3,51,dtype=int64)
(3)isnull/notnull
1)功能:判断每个元素是否空值/非空值.
2)使用格式:D.isnull0/D.notmull().这里的D要求是Series对象,返回一个布尔Series.可以通过D[D.isnull(0)]或D[D.notmull0]找出D中的空值/非空值.
(4)random
1)功能;random是Numpy的一个子库(Python本身也自带了random,但Numpy的更加强大),可以用该库下的各种函数生成服从特定分布的随机矩阵,抽样时可使用.
2)使用格式:
np.random.rand(k,m,n.…)生成一个kxmxnx..随机矩阵,其元素均匀分布在区间(0,l)上;
np.random.randn(k,m,n…)生成一个kxmxnx..随机矩阵,其元素服从标准正态分布.
(5)PCA
1)功能:对指标变量矩阵进行主成分分析.使用前需要用from sklearn.decomposition import PCA引入该函数.
2)使用格式:model=PCAO.注意,Scikit-Learn下的PCA是一个建模式的对象,也就是说,一般的流程是建模,然后是训练model.fit(D),D为要进行主成分分析的数据矩阵,训练结束后获取模型的参数,如.components_获取特征向量,以及.explained_varianceratio获取各个属性的贡献率等.
3)实例:使用PCA0对一个10×4维的随机矩阵进行主成分分析.
>>>from sklearn,decomposition import PCA
>>>D=np.random.rand(10,4)
>>>pca=PCA()
>>>pca.fit(D)
PCA(copy=True,n components=None,whiten=False)
>>>pca.componenta#返回模型的各个特征向量
array([[-0.42899319,-0.69804397,0.32876844,-0.469692211,t0.03680965,-0.0667248,0.7848853,0.61493733],
[-0.62222716,0.68499407,0.28400153,-0.25091755],
1-0.65379144,-0.19765007,-0.4418252,0.58161989]])
>>>pca.explained variance_ratio#返回各个成分各自的方差百分比
array([0.40836652,0.32861061,0.21894296,0.04407991])