赞
踩
前边几个文章都是对于数据预处理之前的数据分析,在经过了数据分析后,我们就要进行对于数据的预处理。前边提到数据存在缺失值和异常值,那么对于这些数据,我们要进行数据清洗。数据清洗完成后接着进行或者同时进行数据集成、转换、规约等一系列的处理,该过程就是数据预处理。数据的预处理是进行数据挖掘的非常重要的环节,几乎占到整个数据挖掘的百分之六十。
缺失值的处理方法可以分成三类:删除记录,数据插补和不处理。其中常见的数据插补方法有均值,中位数,众数插补,使用固定值补充,最近邻差补法,回归法还有插值法。
其中最简单的方法就是删除异常数据或者缺失值,然而这种方法有很大的局限性。它是以减少历史数据来换取数据的完备,会造成资源的大量浪费,将丢弃了大量隐藏在这些记录中的信息。尤其在数据集中本来就可能将缺失值视为一种特殊值。
为此我们可以选择拉格朗日插值法和牛顿插值法。拉格朗日插值法和牛顿插值法的具体理解可以查看链接。值得一提的是牛顿插值法的优点是计算较简单,尤其是增加节点时,计算只增加一项,这是拉格朗日插值无法比的。
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) #输出结果,写入文件
这是拉格朗日插值法的源代码,可以看到在进行插值之前会对数据进行异常值检测并且把异常值定义为空缺值,进行补数。
在数据预处理时,异常值是否剔除,需视具体情况而定,因为有些异常值可能蕴含有用的信息。
对于异常值的处理常用删除法,视为缺失值,平均值修正法和不处理。
直接删除异常值简单易行,但是确定也很明显,在观测量很小的情况下,这种删除会造成样本量不足,可能会改变变量的原有分布,从而造成分析结果的不准确。视为缺失值处理的好处是可以利用现有变量的信息,对异常值进行填补。在很多情况下,要先分析异常值出现的可能原因,再判断异常值是否应该舍弃,如果是正确的数据,可以直接在具有异常值的数据集上进行挖掘建模。
数据挖掘需要的数据往往分布在不同的数据源中,数据集成就是将多个是数据源合并存放在一个一致的数据存储(比如数据仓库)中的过程。
在数据集成时,来自多个数据源的现实世界实体的表达形式是不一样的,有可能不匹配,要考虑实体识别问题和属性冗杂问题,从而将源数据在最底层上加以转换、提炼和集成。
(1)实体识别
1)同名异义 2)异名同义 3)单位不统一
(2)冗余属性识别
数据集成往往导致数据冗余,仔细整合不同源数据能减少甚至避免数据冗杂与不一致,从而提高数据挖掘的速度和质量。对于冗余属性要先分析,检测到后再将其删除。
数据变换主要是对数据进行规范化处理,将数据转换成适当的形式,以适应于挖掘任务及算法的需要。
简单的函数变换是对原始数据进行某些数学函数变换,常用的变换包括平方、开方、取对数、差分运算等。
简单的函数变换常用来将不具有正态分布的数据变换成具有正态分布的数据。在时间序列中,有时简单的对数变换或者差分运算就可以将非平稳序列转换成平稳序列。在数据挖掘中,简单的函数变换可能更有必要,比如个人年收入的取值范围为10000元到十亿元,这是一个很大的区间,使用对数变换对其进行压缩是常用的一种变换处理方法。
数据规范化处理是数据挖掘的一项基础工作。不同评价指标往往具有不同的量纲,数值间的差别可能很大,不进行处理可能会影响到数据分析的结果。为了消除指数之间的量纲和取值范围差异的影响,需要进行标准化处理,将数据按照比例进行缩放,使之进入一个特定的区域,便于进行综合分析。
数据规范化对于基于距离的挖掘算法尤为重要。
(1)最小-最大规范化
最小-最大规范化也称为离差标准化,也是对原始数据的线性变换,将数值值映射到[0,1]之间。
转化公式为 x^* = (x - min )/(max -min)
离差标准化保留了原来数据中存在的关系,是消除量纲和数据取值范围影响的最简单方法。这种处理方式的缺点是如果数值集中且某个数值很大,则规范化后各值会接近于0。
(2)零-均值规范化
零-均值规范化,经过处理的数据的均值为零,标准差为1。
转化公式为x^*=x-x的均值/x的标准差,这是目前用的最多的数据标准化方法。
(3)小数定标规范法
通过移动属性值的小数点,将属性映射到[0,1]之间,移动的小数点位数取决于属性值绝对值的最大值。
下面是三种方法的代码实现
datafile = '../data/normalization_data.xls' #参数初始化
data = pd.read_excel(datafile, header = None) #读取数据
(data - data.min())/(data.max() - data.min()) #最小-最大规范化
(data - data.mean())/data.std() #零-均值规范化
data/10**np.ceil(np.log10(data.abs().max())) #小数定标规范化
这两种方法简单易操作。但是存在一些问题,等宽法对于离群点比较敏感,倾向于不均匀地把属性值分布到各个区间,会导致有的区间的值特别少,严重影响挖掘建模。等频法虽然避免了上述问题的产生,但是可能将相同的数据分到不同的区间以满足每个区间中固定的数据个数。
3.基于聚类分析的方法
一维聚类的方法包括两个步骤,首先将连续属性的值用聚类算法(k-means算法)进行聚类,然后再将聚类得到的簇进行处理,合并一个簇的连续属性值并做同一标记。聚类分析的离散化方法也需要用户指定簇的个数,从而决定产生的区间数。
下面对于三种方法的代码示例
datafile = '../data/discretization_data.xls' #参数初始化 data = pd.read_excel(datafile) #读取数据 data = data[u'肝气郁结证型系数'].copy() k = 4 d1 = pd.cut(data, k, labels = range(k)) #等宽离散化,各个类比依次命名为0,1,2,3 #等频率离散化 w = [1.0*i/k for i in range(k+1)] w = data.describe(percentiles = w)[4:4+k+1] #使用describe函数自动计算分位数 w[0] = w[0]*(1-1e-10) d2 = pd.cut(data, w, labels = range(k)) from sklearn.cluster import KMeans #引入KMeans kmodel = KMeans(n_clusters = k, n_jobs = 4) #建立模型,n_jobs是并行数,一般等于CPU数较好 kmodel.fit(data.reshape((len(data), 1))) #训练模型 c = pd.DataFrame(kmodel.cluster_centers_).sort(0) #输出聚类中心,并且排序(默认是随机序的) w = pd.rolling_mean(c, 2).iloc[1:] #相邻两项求中点,作为边界点 w = [0] + list(w[0]) + [data.max()] #把首末边界点加上 d3 = pd.cut(data, w, labels = range(k)) def cluster_plot(d, k): #自定义作图函数来显示聚类结果 import matplotlib.pyplot as plt plt.rcParams['font.sans-serif'] = ['SimHei'] #用来正常显示中文标签 plt.rcParams['axes.unicode_minus'] = False #用来正常显示负号 plt.figure(figsize = (8, 3)) for j in range(0, k): plt.plot(data[d==j], [j for i in d[d==j]], 'o') plt.ylim(-0.5, k-0.5) return plt cluster_plot(d1, k).show() cluster_plot(d2, k).show() cluster_plot(d3, k).show()
在数据挖掘的过程中,为了提取更有用的信息,挖掘更深层次的模式,提高挖掘的精度,我们需要利用已有的属性集构造出新的属性,并加入到现有的属性集合中。
在大数据集上进行复杂的数据分析和挖掘需要很长的时间,数据规约产生更小但是保持原有数据完整性的新数据集。在规约后的数据集上进行分析和挖掘将更有效率。
数据规约的意义在于:
降低无效,错误数据对建模的影响,提高建模的准确性
少量且具有代表性的数据将大幅度减小数据挖掘所需要的时间
降低储存数据的成本
属性规约的目的是寻找出最小的属性子集,并确保新数据子集的概率分布尽可能地接近原来数据集的概率分布。
方法包括合并属性、主成分分析等。
主成分分析是数据规约(包含属性规约和数值规约)的一种常用方法。用较少的变量去解释原始数据中的大部分变量,即将许多相关性很高的变量转化成彼此相互独立或不相关的变量。
主成分分析,当自变量之间不是相互独立时,能够将自变量变换成独立的成分;在自变量太多的情况下,能够降维。主成分分析是一种经常使用的辅助性的分析方法。
数值规约通过选择替代的、较少的数据来减少数据量,包括有参数方法和无参数方法。
1、有参数方法。使用一个模型来评估数据,只需存放参数,而不需要存放实际数据,如回归。
2、无参数方法。需要存放实际数据。
(1)直方图。如一连串的数据,通过绘制直方图(R中用hist()函数绘制直方图),分为“315”、“1628”、“29~41”三个范围。
(2)聚类。将对象划分为簇,使一个簇中的对象相互“相似”,而与其他簇中的对象“相异”,用数据的簇替换实际数据。
(3)抽样。R实现:newD = D[sample(N,s,replace=T/F),]
interpolate:一维高纬数据插值
unique:去除数据中的重复元素,得到单值元素列表,它是对象的方法名
isnull:判断是否为空值
notnull:判断是否非空值
PCA:对指标变量矩阵进行主成分分析
random:生成随机矩阵
PCA
1)功能:对指标变量矩阵进行主成分分析。使用前要用 from sklearn.decomposition import PCA
引入该函数。
2)使用格式:model =PCA().注意,scikit-learn下的PCA是一个建模式的对象,也就是说,一般流程是建模,然后是训练model.fit(D),D为要进行主成分分析的数据矩阵,训练结束后获取模型的参数
3)实例:对一个10*3维的随机矩阵进行主成分分析
import numpy as np
from sklearn.decomposition import PCA
d = np.random.rand(10,3)
pca = PCA()
pca.fit(d)
PCA(copy=True, n_components= None, whiten= False)
print(pca.components_)
print(pca.explained_variance_ratio_)
展示结果
[[ 0.60042601 -0.02636193 -0.79924568]
[-0.79942252 -0.04516306 -0.59906923]
[ 0.02030376 -0.99863174 0.0481914 ]]
[0.5516147 0.32519712 0.12318818]
这一篇文章用大篇幅介绍了数据预处理的方法,数据预处理的主要任务是数据清洗、数据集成、数据变换和数据规约。数据清洗主要介绍了对缺失值和异常值的处理;数据集成是合并多个数据源中的数据,并存放到一个数据储存的过程。数据变换介绍了如何从不同的应用角度对已有属性进行函数变换;数据规约从属性和数值两个方向进行规约,使挖掘的性能和效率得到很大的提高。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。