数据挖掘:数据清洗——缺失值处理

数据挖掘:数据清洗——缺失值处理数据挖掘 数据预处理 缺失值处理一 什么是缺失值缺失值是指粗糙数据中由于缺少信息而造成的数据的聚类 分组 删失或截断

大家好,欢迎来到IT知识分享网。

数据挖掘:数据清洗——缺失值处理

在这里插入图片描述

一、什么是缺失值

缺失值是指粗糙数据中由于缺少信息而造成的数据的聚类、分组、删失或截断。它指的是现有数据集中某个或某些属性的值是不完全的。

  • None是一个python特殊的数据类型。不同于空列表和空字符串,是一种单独的格式。
  • NaN是numpy\pandas下的,不是Python原生的,Not a Number的简称。数据类型是float。
    • 对整体的series或Dataframe判断是否未空,用isnull()
    • 对单独的某个值判断,可以用 np.isnan()
  • Null在Python中没有这个NULL,NULL主要是在C语言中,在Python中对应的就是None,空字符,数据类型是字符串。
  • NaT非时间空值,Not a Time.该值可以存储在 datetime 数组中以指示未知或缺失的 datetime 值。NaT 返回一个 (NaT) datetime 非时间标量值。
空值语义

对于某个对象的属性值未知的情况,我们称它在该属性的取值为空值(null value)。空值的来源有许多种,因此现实世界中的空值语义也比较复杂。总的说来,可以把空值分成以下三类:

  1. 不存在型空值。即无法填入的值,或称对象在该属性上无法取值,如一个未婚者的配偶姓名等。
  2. 存在型空值。即对象在该属性上取值是存在的,但暂时无法知道。如一个已婚者的配偶姓名等。一般情况下,空值是指存在型空值。
  3. 占位型空值。即无法确定是不存在型空值还是存在型空值,这要随着时间的推移才能够清楚,是最不确定的一类。这种空值除填充空位外,并不代表任何其他信息。

二、缺失值产生的原因

  1. 机械原因:是由于机械原因导致的数据收集或保存的失败造成的数据缺失。比如数据存储出现问题,机械故障导致某段时间数据未能收集(对于定时数据采集而言)。
  2. 人为原因:是由于人的主观失误、历史局限或有意隐瞒造成的数据缺失,比如,在市场调查中被访人拒绝透露相关问题的答案,或者回答的问题是无效的,数据录入人员失误漏录了数据。

三、数据缺失机制

在对缺失数据进行处理前,了解数据缺失的机制和形式是十分必要的。将数据集中不含缺失值的变量称为完全变量,数据集中含有缺失值的变量称为不完全变量。从缺失的分布来将缺失可以分为完全随机缺失,随机缺失和完全非随机缺失。

  1. 完全随机缺失(missing completely at random,MCAR):指的是数据的缺失是完全随机的,不依赖于任何不完全变量或完全变量,不影响样本的无偏性。如家庭地址缺失,与其他变量无关
  2. 随机缺失(missing at random,MAR):指的是数据的缺失不是完全随机的,即该类数据的缺失依赖于其他完全变量。例如财务数据缺失情况与企业的大小有关,两个变量间存在关系
  3. 非随机缺失(missing not at random,MNAR):指的是数据的缺失与不完全变量自身的取值有关。如高收入人群的不原意提供家庭收入,人为不可控因素造成的

四、缺失值处理的重要性

当缺失比例很小时,可直接对缺失记录进行舍弃或进行手工处理。但在实际数据中,往往缺失数据占有相当的比重。这时如果手工处理非常低效,如果舍弃缺失记录,则会丢失大量信息,使不完全观测数据与完全观测数据间产生系统差异,对这样的数据进行分析,很可能会得出错误的结论。

数据缺失在许多研究领域都是一个复杂的问题。对数据挖掘来说,缺省值的存在,造成了以下影响:

  1. 系统丢失了大量的有用信息;
  2. 系统中所表现出的不确定性更加显著,系统中蕴涵的确定性成分更难把握,;
  3. 包含空值的数据会使挖掘过程陷入混乱,直接拿来进行分析挖掘,那么很可能会得到错误的结论。

数据挖掘算法本身更致力于避免数据过分拟合所建的模型,这一特性使得它难以通过自身的算法去很好地处理不完整数据。因此,缺省值需要通过专门的方法进行推导、填充等,以减少数据挖掘算法与实际应用之间的差距。

五、缺失值处理的要素

个人认为关于缺失值的处理,主要包含以下两个因素:

  1. 尽可能防止数据信息的缺失。仅因为数据某一特征的缺失,就删除整行数据,那么其他特征的数据信息也会丢失,这对数据挖掘(充分利用数据给定的信息,从中挖掘出能解决目标问题的信息)是极其不利的。
  2. 缺失值填充的合理性。这个一方面与数据本身的数值有关,采用一些算法或图形对填充的合理性进行检验。如填充后的数据与之前的直方图上是否有太大的变化。另一方面与数据的特定场景有关,需要按照不同的方法对缺失值进行填充,如
    1. “年收入”:商品推荐场景下填充平均值,借贷额度场景下填充最小值;
    2. “行为时间点”:填充众数;
    3. “价格”:商品推荐场景下填充最小值,商品匹配场景下填充平均值;
    4. “人体寿命”:保险费用估计场景下填充最大值,人口估计场景下填充平均值;
    5. “驾龄”:没有填写这一项的用户可能是没有车,为它填充为0较为合理;
    6. ”本科毕业时间”:没有填写这一项的用户可能是没有上大学,为它填充正无穷比较合理;
    7. “婚姻状态”:没有填写这一项的用户可能对自己的隐私比较敏感,应单独设为一个分类,如已婚1、未婚0、未填-1。

六、缺失值处理方法的分析与比较

处理不完整数据集的方法主要有三大类:删除元组、数据补齐、不处理。

6.1删除元祖

也就是将存在遗漏信息属性值的对象(元组,记录)删除,从而得到一个完备的信息表。这种方法简单易行,在对象有多个属性缺失值、被删除的含缺失值的对象与初始数据集的数据量相比非常小的情况下非常有效,类标号缺失时通常使用该方法
然而,这种方法却有很大的局限性。

  1. 它以减少历史数据来换取信息的完备,会丢弃大量隐藏在这些对象中的信息。
  2. 当缺失数据比例较大时,特别是缺失数据非随机分布时,直接删除可能会导致数据发生偏离,比如原本的正态分布变为非正太。

说明:这种方法在样本数据量十分大且缺失值不多的情况下非常有效,但如果样本量本身不大且缺失也不少,那么不建议使用。但若数据量缺失值的过大75%,则无法获取有用的信息,甚至对后续的工作产生不利影响,建议直接删除该特征。

6.2数据补齐

这类方法是用一定的值去填充空值,从而使信息表完备化。通常基于统计学原理,根据初始数据集中其余对象取值的分布情况来对一个缺失值进行填充。数据挖掘中常用的有以下几种补齐方法:


替换缺失值

6.2.1 人工填写(filling manually)

由于最了解数据的还是用户自己,因此这个方法产生数据偏离最小,可能是填充效果最好的一种。然而一般来说,该方法很费时,当数据规模很大、空值很多的时候,该方法是不可行的。

6.2.2 特殊值填充(Treating Missing Attribute values as Special values)

将空值作为一种特殊的属性值来处理,它不同于其他的任何属性值。如所有的空值都用“unknown”填充。这样将形成另一个有趣的概念,可能导致严重的数据偏离,一般不推荐使用。

6.2.3 平均值填充(Mean/Mode Completer)
6.2.4 热卡填充(Hot deck imputation,或就近补齐)

对于一个包含空值的对象,热卡填充法在完整数据中找到一个与它最相似的对象(特征),然后用这个相似对象的值来进行填充。不同的问题可能会选用不同的标准来对相似进行判定。该方法概念上很简单,且利用了数据间的关系来进行空值估计这个方法的缺点在于难以定义相似标准,主观因素较多,人为选择

6.2.5 K最近距离邻法(K-means clustering)

注:缺失值填补的准确性就要看聚类结果的好坏了,而聚类结果的可变性很大,通常与初始选择点有关,并且在下图中可看到单独的每一类中特征值也有很大的差别,因此使用时要慎重。

说明
利用了样本之间关联性,而非单个特征数据进行自我填充。
在这里插入图片描述

6.2.6 使用所有可能的值填充(Assigning All Possible values of the Attribute)

用空缺属性值的所有可能的属性取值来填充,能够得到较好的补齐效果。但是,当数据量很大或者遗漏的属性值较多时,其计算的代价很大,可能的测试方案很多。

6.2.7 组合完整化方法(Combinatorial Completer)

用空缺属性值的所有可能的属性取值来试,并从最终属性的约简结果中选择最好的一个作为填补的属性值。这是以约简为目的的数据补齐方法,能够得到好的约简结果;但是,当数据量很大或者遗漏的属性值较多时,其计算的代价很大。


拟合缺失值

6.2.8 回归(Regression)

基于完整的数据集,建立回归方程。对于包含空值的对象,将已知属性值代入方程来估计未知属性值,以此估计值来进行填充。当变量不是线性相关时会导致有偏差的估计。

6.2.9 期望值最大化方法(Expectation maximization,EM)

在缺失类型为随机缺失的条件下,假设模型对于完整的样本是正确的,那么通过观测数据的边际分布可以对未知参数进行极大似然估计(Little and Rubin)。这种方法也被称为忽略缺失值的极大似然估计,对于极大似然的参数估计实际中常采用的计算方法是期望值最大化(Expectation Maximization,EM)。该方法比删除个案和单值插补更有吸引力,它一个重要前提:适用于大样本。有效样本的数量足够以保证ML估计值是渐近无偏的并服从正态分布。但是这种方法可能会陷入局部极值,收敛速度也不是很快,并且计算很复杂

EM算法是一种在不完全数据情况下计算极大似然估计或者后验分布的迭代算法。在每一迭代循环过程中交替执行两个步骤:

  1. E步(Excepctaion step,期望步),在给定完全数据和前一次迭代所得到的参数估计的情况下,计算完全数据对应的对数似然函数的条件期望;
  2. M步(Maximzation step,极大化步),用极大化对数似然函数以确定参数的值,并用于下步的迭代。
    算法在E步和M步之间不断迭代直至收敛,即两次迭代之间的参数变化小于一个预先给定的阈值时结束。
6.2.10 有序K近邻法(Sequential KNN)

方法是对上述KNN法的改进,它在缺失值占比稍微大些的数据中表现依然良好。实现流程是先根据数据中每个对象缺失值的比例进行排序(这里也就体现出“Sequential”的思想),从比例最小的那个对象开始计算,根据预先设定的K个近邻(注意这里是指没有缺失值的,KNN法里面并没有强调这一点)的值进行加权或者平均计算填充。此外当该对象填充完毕后,也会加入后续其他对象缺失值填充的计算当中。

6.2.11 多重填补(Multiple Imputation,MI)

多值插补的思想来源于贝叶斯估计,认为待插补的值是随机的,它的值来自于已观测到的值。具体实践上通常是估计出待插补的值,然后再加上不同的噪声,形成多组可选插补值。根据某种选择依据,选取最合适的插补值。

多重填补方法分为三个步骤:

  1. 为每个空值产生一套可能的填补值,这些值反映了无响应模型的不确定性;每个值都被用来填补数据集中的缺失值,产生若干个完整数据集合。
  2. 每个填补数据集合都用针对完整数据集的统计方法进行统计分析。
  3. 对来自各个填补数据集的结果进行综合,产生最终的统计推断,这一推断考虑到了由于数据填补而产生的不确定性。该方法将空缺值视为随机样本,这样计算出来的统计推断可能受到空缺值的不确定性的影响。该方法的计算也很复杂。

上例中假定了Y1,Y2,Y3的联合分布为正态分布。这个假设是人为的,但是已经通过验证(Graham和Schafer于1999),非正态联合分布的变量,在这个假定下仍然可以估计到很接近真实值的结果。

注:使用多重插补要求数据缺失值为随机性缺失,一般重复次数20-50次精准度很高,但是计算也很复杂,需要大量计算。

多重插补和贝叶斯估计的思想是一致的,但是多重插补弥补了贝叶斯估计的几个不足:

  1. 贝叶斯估计以极大似然的方法估计,极大似然的方法要求模型的形式必须准确,如果参数形式不正确,将得到错误得结论,即先验分布将影响后验分布的准确性。而多重插补所依据的是大样本渐近完整的数据的理论,在数据挖掘中的数据量都很大,先验分布将极小的影响结果,所以先验分布的对结果的影响不大。
  2. 贝叶斯估计仅要求知道未知参数的先验分布,没有利用与参数的关系。而多重插补对参数的联合分布作出了估计,利用了参数间的相互关系。
6.2.12 C4.5方法

通过寻找属性间的关系来对遗失值填充。它寻找之间具有最大相关性的两个属性,其中没有遗失值的一个称为代理属性,另一个称为原始属性,用代理属性决定原始属性中的遗失值。这种基于规则归纳的方法只能处理基数较小的名词型属性。应用随机森林将缺失值作为目标变量。


虚拟变量

6.2.13 引入虚拟变量

把变量映射到高维空间。比如性别,有男、女、缺失三种情况,则映射成3个变量:是否男、是否女、是否缺失。连续型变量也可以这样处理。比如Google、百度的CTR预估模型,预处理时会把所有变量都这样处理,达到几亿维。这样做的好处是完整保留了原始数据的全部信息、不用考虑缺失值、不用考虑线性不可分之类的问题。缺点是计算量大大提升。

但只有在样本量非常大的时候效果才好,否则会因为过于稀疏,效果很差。

6.2.14 小结

就以上几种基于统计的方法而言:

  1. 删除元组法和平均值法(不建议直接插入常量)差于hot deck、EM和MI;
  2. 回归是比较好的一种方法,但仍比不上hot deck和EM;
  3. EM缺少MI包含的不确定成分。

值得注意的是,这些方法直接处理的是模型参数的估计而不是空缺值预测本身。它们合适于处理无监督学习的问题,而对有监督学习来说,情况就不尽相同了。譬如,你可以删除包含空值的对象用完整的数据集来进行训练(当数据缺失值占比多大时),但预测时你却不能忽略包含空值的对象。另外,C4.5和使用所有可能的值填充方法也有较好的补齐效果,人工填写和特殊值填充则是一般不推荐使用的。

不处理

补齐处理只是将未知值补以我们的主观估计值,不一定完全符合客观事实,在对不完备信息进行补齐处理的同时,我们或多或少地改变了原始的信息系统。而且,对空值不正确的填充往往将新的噪声引入数据中,使挖掘任务产生错误的结果。因此,在许多情况下,我们还是希望在保持原始信息不发生变化的前提下对信息系统进行处理。

不处理缺失值,直接在包含空值的数据上进行数据挖掘的方法包括贝叶斯网络和人工神经网络等。

  • 贝叶斯网络提供了一种自然的表示变量间因果信息的方法,用来发现数据间的潜在关系。在这个网络中,用节点表示变量,有向边表示变量间的依赖关系。贝叶斯网络仅适合于对领域知识具有一定了解的情况,至少对变量间的依赖关系较清楚的情况。否则直接从数据中学习贝叶斯网的结构不但复杂性较高(随着变量的增加,指数级增加),网络维护代价昂贵,而且它的估计参数较多,为系统带来了高方差,影响了它的预测精度。
  • 人工神经网络可以有效的对付缺失值,但人工神经网络在这方面的研究还有待进一步深入展开。

在实际应用中,一些模型无法应对具有缺失值的数据,因此要对缺失值进行处理。然而还有一些模型本身就可以应对具有缺失值的数据,此时无需对数据进行处理,比如Xgboost,rfr等高级模型

七、总结

  1. 删除。最简单最直接的方法,很多时候也是最有效的方法,这种做法的缺点是可能会导致信息丢失。删除有缺失数据的样本删除有过多缺失数据的特征
  2. 补全。用规则或模型将缺失数据补全,这种做法的缺点是可能会引入噪声。
    1. 平均数、中位数、众数、最大值、最小值、固定值、插值等等。
    2. 建立一个模型来“预测”缺失的数据。(KNN, Matrix completion等方法)。但有一个缺点,如果其他变量与缺失变量无关,则预测毫无意义;如果预测结果相当准确,则这个变量没有必要加入模型。通常介于两者之间。
    3. 引入虚拟变量(dummy variable)来表征是否有缺失。
  3. 忽略。有一些模型,如随机森林,自身能够处理数据缺失的情况,在这种情况下不需要对缺失数据做任何的处理,这种做法的缺点是在模型的选择上有局限。

总而言之,大部分数据挖掘的预处理都会使用比较方便的方法来处理缺失值,比如均值法,但是效果上并一定好,因此还是需要根据不同的需要选择合适的方法,并没有一个解决所有问题的万能方法。具体的方法采用还需要考虑多个方面的:

数据缺失的原因;
数据缺失值类型;
样本的数据量;
数据缺失值随机性等;


Python中处理缺失值

删除

#删除数据表中含有空值的行 df.dropna(how='any') 

均值填充

在这里插入图片描述
单变量值插补
sklearn提供了单变量插补的工具类SimpleImputer ,其提供了计算缺失值的基本策略。缺失值可以用提供的常数值计算,也可以使用缺失值所在的行/列中的统计数据(平均值、中位数或者众数)来计算。这个类也支持不同的缺失值编码。

  • 参数说明:
    • missing_values :指定何种占位符表示缺失值,可选 number ,string ,np.nan(default) ,None
    • strategy :插补策略,字符串,默认”mean”
      • “mean” :使用每列的平均值替换缺失值,只能与数字数据一起使用
      • “median”:则使用每列的中位数替换缺失值,只能与数字数据一起使用
      • “most_frequent” :则使用每列中最常用的值替换缺失值,可以与字符串或数字数据一起使用
      • “constant” :则用 fill_value 替换缺失值。可以与字符串或数字数据一起使用
    • fill_value :字符串或数值,默认”None”,当strategy ==“constant”时,fill_value用于替换所有出现的missing_values。如果保留默认值,则在输入数字数据时fill_value将为0,对于字符串或对象数据类型则为“missing_value”。
  • 属性说明
    • statistics_ :每一个样本的插补值
    • indicator_ :指示用于为缺失值添加二进制指标
from sklearn.preprocessing import Imputer import numpy as np imputer = Imputer(missing_values='NaN', strategy="mean", axis=0) duty_data = [[1,2,np.nan],[4,5,6],[7,np.nan,9],[10,11,12],[np.nan,14,15]] imputed_data = imputer.fit_transform(duty_data) print(imputed_data) [[ 1. 2. 10.5] [ 4. 5. 6. ] [ 7. 8. 9. ] [10. 11. 12. ] [ 5.5 14. 15. ]] 

使用python本身的代码

Python中的使用: #使用price均值对NA进行填充 df['price'].fillna(df['price'].mean()) df['price'].fillna(df['price'].median()) df['price'].fillna(df['price'].mode()) 

多变量值插补
IterativeImputer类的功能是,将每个缺失值的特征建模为其他特征的函数,并使用该估计值进行估算。
它以循环迭代方式实现:在每个步骤中,将特征目标列指定为输出y,将其他列视为输入X。使用一个回归器来在已知(未缺失)y的样本上对(X,y)进行拟合。然后使用这个回归器来预测缺失的y值。这是以迭代的方式对每个特征进行的,然后重复max_iter轮。最后一轮的计算结果被返回。
参数说明


  • estimator :estimator对象,默认= BayesianRidge()。循环法插补的每一步使用的估算器。如果sample_posterior为True,则估算器必须支持 return_std其predict方法。
  • missing_values :指定何种占位符表示缺失值,可选 number ,string ,np.nan(default) ,None
  • sample_posterior :布尔值,默认为False,是否从每个插补的拟合估计的(高斯)预测后验进行采样。如果设置为True,Estimator 必须支持return_std 其predict 方法。True如果IterativeImputer用于多个插补,则设置为 。
  • max_iter :输入为int型数据,默认值是10。在返回最后一轮计算的估算值之前要执行的最大插补轮次数。
  • initial_strategy :使用哪种策略初始化缺失值。与 SimpleImputer 中的strategy参数相同
  • imputation_order :排序规则
    • ascending :从缺失值最少的功能到最多
    • descending :从具有最多缺失值的功能到最少
    • roman :左到右
    • arabic :右到左
    • random :随机顺序
imp = IterativeImputer(max_iter=10, random_state=0) imp.fit([[1, 2], [3, 6], [4, 8], [np.nan, 3], [7, np.nan]]) X_test = [[np.nan, 2], [6, np.nan], [np.nan, 6]] np.round(imp.transform(X_test)) 

KNN

  1. 首先将需要填补缺失值的特征x1提取出来,并把缺失值删除,剩下的值为train_y。将与x1缺失值有关的行删除,除x1以外的数据作为训练集train_x。训练集中不能有缺失值
  2. 将x1中缺失值所在行,以外的数据作为test_x。
from sklearn.neighbors import KNeighborsClassifier,KNeighborsRegressor def knn_missing_filled(train_x,train_y,test_x,k=3,dispersed=True): if dispersed: clf = KNeighborsClassifier(n_neighbors=k,weights='distance',n_jobs=-1) else: clf = KNeighborsRegressor(n_neighbors=k,weights='distance',n_jobs=-1) clf.fit(train_x,train_y) return test_x.index,clf.predict(test_x) index,pred = knn_missing_filled(train_x,train_y,test_x,k=3,dispersed=True) data.loc[index,'x1'] = pred 

参数:

train_x和train_y:表示模型训练集的x和y test:待填补的缺失样本 k:K近邻的K值,此处默认为3 dipersed:待填补的缺失变量是否离散,默认是,则用K近邻分类器,投票选出K个邻居中最多的类别进行填补;如为连续变量,则用K近邻回归器,拿K个邻居中该变量的平均值填补。 

返回:

待填补数据集的行号,预测的用于填补的值 

KNN模型参数:

n_neighbors-KNN的K,近邻个数 weights-样本的权重, distance为用样本间的距离(默认欧式距离)作为权重,样本间距离越近越”重要“, n_jobs-设置跑模型时,参与计算的cpu核心的个数,-1为建模时使用cpu的所有核心; fit方法表示进行拟合模型的操作,predict表示作预测,事实上,大多数sklearn模型都有fit和predict方法,含义相同。 

拟合填充

随机森林

这里是把缺失值这一特征当做目标特征进行回归预测。

from sklearn.ensemble import RandomForestRegressor def set_missing_ages(df): #把数值型特征都放到随机森林里面去 age_df=df[['Age','Fare','Parch','SibSp','Pclass']] known_age = age_df[age_df.Age.notnull()].as_matrix() unknown_age = age_df[age_df.Age.isnull()].as_matrix() y=known_age[:,0]#y是年龄,第一列数据 x=known_age[:,1:]#x是特征属性值,后面几列 rfr=RandomForestRegressor(random_state=0,n_estimators=2000,n_jobs=-1) #根据已有数据去拟合随机森林模型 rfr.fit(x,y) #预测缺失值 predictedAges = rfr.predict(unknown_age[:,1:]) #填补缺失值 df.loc[(df.Age.isnull()),'Age'] = predictedAges return df,rfr 

虚拟变量

具体做法是通过判断特征值是否有缺失值来定义一个新的二分类变量。比如,特征为A含有缺失值,我们衍生出一个新的特征B,如果A中特征值有缺失,那么相应的B中的值为1,如果A中特征值没有缺失,那么相应的B中的值为0

data_train['CabinCat'] = data_train['Cabin'].copy() data_train.loc[ (data_train.CabinCat.notnull()), 'CabinCat' ] = "No" data_train.loc[ (data_train.CabinCat.isnull()), 'CabinCat' ] = "Yes" fig, ax = plt.subplots(figsize=(10,5)) sns.countplot(x='CabinCat', hue='Survived',data=data_train) plt.show() 
data_train[['Cabin','CabinCat']].head(10) 

在这里插入图片描述

文献参考

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/134294.html

(0)
上一篇 2025-07-13 16:45
下一篇 2025-07-13 17:00

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信