数据分析中缺失值的处理

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据分析中缺失值的处理相关的知识,希望对你有一定的参考价值。

参考技术A 数据缺失在许多研究领域都是一个复杂的问题,对数据挖掘来说,缺失值的存在,造成了以下影响:
1.系统丢失了大量的有用信息
2.系统中所表现出的不确定性更加显著,系统中蕴涵的确定性成分更难把握
3.包含空值的数据会使挖掘过程陷入混乱,导致不可靠的输出

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

1.列表显示缺失值 mice包 md.pattern( )

2.图形探究缺失值 VIM包

3.用相关性探索缺失值

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

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

3.平均值填充
将信息表中的属性分为数值属性和非数值属性来分别进行处理。如果空值是数值型的,就根据该属性在其他所有对象的取值的平均值来填充该缺失的属性值;如果空值是非数值型的,就根据统计学中的众数原理,用该属性在其他所有对象的取值次数最多的值(即出现频率最高的值)来补齐该缺失的属性值。另外有一种与其相似的方法叫条件平均值填充法(Conditional Mean Completer)。在该方法中,缺失属性值的补齐同样是靠该属性在其他对象中的取值求平均得到,但不同的是用于求平均的值并不是从信息表所有对象中取,而是从与该对象具有相同决策属性值的对象中取得。这两种数据的补齐方法,其基本的出发点都是一样的,以最大概率可能的取值来补充缺失的属性值,只是在具体方法上有一点不同。与其他方法相比,它是用现存数据的多数信息来推测缺失值。

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

5.K最近距离邻法
先根据欧式距离或相关分析来确定距离具有缺失数据样本最近的K个样本,将这K个值加权平均来估计该样本的缺失数据。
同均值插补的方法都属于单值插补,不同的是,它用层次聚类模型预测缺失变量的类型,再以该类型的均值插补。假设X=(X1,X2…Xp)为信息完全的变量,Y为存在缺失值的变量,那么首先对X或其子集行聚类,然后按缺失个案所属类来插补不同类的均值。如果在以后统计分析中还需以引入的解释变量和Y做分析,那么这种插补方法将在模型中引入自相关,给分析造成障碍。

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

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

8.回归
基于完整的数据集,建立回归方程(模型)。对于包含空值的对象,将已知属性值代入方程来估计未知属性值,以此估计值来进行填充,当变量不是线性相关或预测变量高度相关时会导致有偏差的估计(SPSS菜单里有这种方法)

9.期望值最大化方法
EM算法是一种在不完全数据情况下计算极大似然估计或者后验分布的迭代算法。在每一迭代循环过程中交替执行两个步骤:E步(Excepctaion step,期望步),在给定完全数据和前一次迭代所得到的参数估计的情况下计算完全数据对应的对数似然函数的条件期望;M步(Maximzation step,极大化步),用极大化对数似然函数以确定参数的值,并用于下步的迭代。算法在E步和M步之间不断迭代直至收敛,即两次迭代之间的参数变化小于一个预先给定的阈值时结束。该方法可能会陷入局部极值,收敛速度也不是很快,并且计算很复杂。(SPSS菜单里有这种方法)

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

10.2多重填补在SPSS中的实现
10.2.1缺失模式分析
分析>多重归因>分析模式

10.2.2缺失值的多重填充
分析>多重归因>归因缺失数据值

10.2.3采用填充后的数据建模

10.3多重填补在R中的实现(基于mice包)

实例:

11.C4.5方法
通过寻找属性间的关系来对遗失值填充。它寻找之间具有最大相关性的两个属性,其中没有遗失值的一个称为代理属性,另一个称为原始属性,用代理属性决定原始属性中的遗失值。这种基于规则归纳的方法只能处理基数较小的名词型属性。

就几种基于统计的方法而言,删除元组法和平均值填充法差于热卡填充法、期望值最大化方法和多重填充法;回归是比较好的一种方法,但仍比不上热卡填充和期望值最大化方法;期望值最大化方法缺少多重填补包含的不确定成分。值得注意的是,这些方法直接处理的是模型参数的估计而不是空缺值预测本身。它们合适于处理无监督学习的问题,而对有监督学习来说,情况就不尽相同了。譬如,你可以删除包含空值的对象用完整的数据集来进行训练,但预测时你却不能忽略包含空值的对象。另外,C4.5和使用所有可能的值填充方法也有较好的补齐效果,人工填写和特殊值填充则是一般不推荐使用的。

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

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

多数统计方法都假设输入数据是完整的且不包含缺失值,但现实生活中大多数数据集都包含了缺失值。因此,在进行下一步分析前,你要么删除,要么用合理的数值代理它们,SPSS、R、Python、SAS等统计软件都会提供一些默认的处理缺失值方法,但这些方法可能不是最优的,因此,学习各种各样的方法和他们的分支就显得非常重要。Little和Rubin的《Sstatistical Analysis With Missing Data 》是缺失值领域里经典的读本,值得一看。

数据预处理之缺失值的处理

 

缺失值的类型

首先对数据的变量(特征)按照缺失和不缺失进行分类:不含有缺失值的变量称为完全变量,含有缺失值的变量称为非完全变量。

缺失值的类型分为三种:完全随机缺失,随机缺失和非随机缺失。

完全随机缺失: 缺失的变量和其余的变量没有关系。比如”家庭住址“这个信息,和”身高“等其余的变量没有关系。

随机缺失: 缺失的变量和完全变量存在一定的关系。假如“学历”中不含缺失值,“收入”和它有关,那么“收入”为随机缺失。

非随机缺失:缺失的变量和非完全变量存在一定的关系。

根据上面变量的分类,其实我们已经大致可以想出来一些处理缺失值的方法了:比如对于完全随机缺失,我们可以选择丢弃或者是依靠变量自身未缺失值的信息(均值、方差)进行补全。 而对于随机缺失,我们可以利用完全变量的信息来进行补全。

 

数据处理的方法

  总的来说,在处理缺失值的时候我们可以采用三种方法,第一种是不作处理,这个很简单,把缺失值放在那里就可以了。 第二种方法是进行删除操作。 第三种方法就是进行数据的补全操作。

删除操作

当某个特征上面的数据缺失太大的时候,直接将这个特征删除了。

而当特征上面的缺失值很少的时候,比如只有几个缺失值的时候,可以考虑把包含这些缺失值的元组进行删除。

补全操作

实际当中用的最多的还是补全操作,补全操作有很多种,按照参考文章一的划分有很多种,可以看原文查看具体的类型,这里我只介绍自己目前明白的几种:

1:人工填充:根据已经掌握的数据的知识进行填充,但是这个方法在数据量很大,缺失值很多的时候明显是不可以的。

2:特殊值填充:将缺失值用unknown表示,这和原来的缺失值的意思还是有一点差别的。在这里unknown可以当做一种取值的可能性。

3:平均值填充。 对于数字类型的变量,可以使用没有缺失值的一些信息进行估计,使用用平均值进行的估计称为平均值填充。对于分类变量可以使用众数来进行填充。其实也可以加上一点方差的信息来进行估计,我在后面的例子当中来说明这一点。

4:将数据映射到高维,第二个参考文章。这个方法有点暴力,使得特征的数量大大的增加,但是保留原始数据的全部信息。

5:使用其它的变量来进行预估。 这里的方法就多了,包括文章中讲的回归,期望最大化方法和C4.5方法。这里因为都没有接触过,就不写了。

下面我将用一些例子来说明如何如何处理缺失值

 

使用pandas来处理泰坦尼克号的数据

数据集的准备:

  我们使用kaggle 的titanic的数据来进行实验,https://www.kaggle.com/c/titanic/data 

首先导入数据集

import pandas as pd
train_df = pd.read_csv(../input/train.csv)
print(train_df.info())

看一下各个特征里面数据的缺失情况

<class pandas.core.frame.DataFrame>
RangeIndex: 891 entries, 0 to 890
Data columns (total 12 columns):
PassengerId    891 non-null int64
Survived       891 non-null int64
Pclass         891 non-null int64
Name           891 non-null object
Sex            891 non-null object
Age            714 non-null float64
SibSp          891 non-null int64
Parch          891 non-null int64
Ticket         891 non-null object
Fare           891 non-null float64
Cabin          204 non-null object
Embarked       889 non-null object
dtypes: float64(2), int64(5), object(5)
memory usage: 83.6+ KB

其中Age,Cabin,和Embarked三个数据有缺失,

 

对Cabin和Embarked进行处理

对于Cabin的数据,因为它的缺失值太多了,所以我们的做法就是直接删除掉,直接把这一个特征删除了就可以了

train_df = train_df.drop([Cabin], axis=1)

对于Embarked特征来说,它有两个缺失值,我们可以删除了包含有缺失值的两条记录

train_df = train_df.drop(train_df[train_df[Embarked].isnull()].index, axis=0)

也可以用众数进行填充

embarked_mode = train_df[Embarked].mode()[0]
train_df[Embarked] = train_df[Embarked].fillna(embarked_mode)

 

于Age信息的补全

最容易想到的就是用平均值来进行补充

age_mean = train_df[Age].dropna().mean()
train_df[Age] = train_df[Age].fillna(age_mean)

当然也可以利用均值和方差(标准差)的信息进行一些填充

import numpy as np
age_mean = train_df[Age].dropna().mean()
age_std = train_df[Age].dropna().std()
age_nan_num = train_df[Age].isnull().sum()
#在 (均值-标准差) 和 (均值+标准差) 之间产生一些均分分布的数作为填充
fill_age = np.random.randint(age_mean - age_std, age_mean + age_std , size=age_nan_num)
train_df.loc[train_df[Age].isnull(),Age] = fill_age

此外,就是利用别的属性的信息进行填充,比如在泰塔尼克号数据当中,我们分析性别和登陆的港口不同,他们的年龄可能也不同,于是我们可以这样做,为每个类别的人填充不同的值。

#先将数据转换一下,好进行处理
train_df[Sex] = train_df[Sex].map({male:0, female:1})
train_df[Embarked] = train_df[Embarked].map({C:0, Q:1, S:2})

fill_ages = np.zeros((2, 3))
for i in range(0, 2):
    for j in range(0, 3):
        age_i_j = train_df.loc[(train_df[Sex] == i) & (train_df[Embarked] == j),                                Age].dropna()

        fill_ages[i, j] = age_i_j.median()  #这里可以选择均值,还有随机值等

for i in range(0, 2):
    for j in range(0, 3):
        train_df.loc[(train_df[Age].isnull()) & (train_df[Sex] == i) &                       (train_df[Embarked] == j), Age] = fill_ages[i, j]

 

sklearn中处理缺失值的方法

sklearn.preprocessing的Imputer方法可以进行缺失值的处理,可以选择平均数,众数或者中位数来填充缺失的值。

from sklearn.preprocessing import Imputer
import numpy as np

#strategy表示采用何种策略,有mean,median, most_frequent
#axis=0, 表示在咧上面进行操作, axis=1表示在行上面进行操作
imp  = Imputer(missing_values=NaN, strategy=mean, axis=0)
#通过fit以后,得到第一列的均值为(1+7)/2 = 4 ,第二列的均值为11/3,
## 以后进行transform的时候,直接将这些值填充过去就可以了
imp.fit([[1, 2], [np.nan, 3], [7, 6]])

X = [[np.nan, 2], [6, np.nan], [7, 6]]
print(imp.transform(X))

输出结果如下:

[[4.         2.        ]
 [6.         3.66666667]
 [7.         6.        ]]

 

参考:

数据分析中的缺失值处理

机器学习中如何处理缺失数据? - 马骏的回答 - 知乎

Preprocessing data

以上是关于数据分析中缺失值的处理的主要内容,如果未能解决你的问题,请参考以下文章

数据预处理之缺失值的处理

数据预处理----缺失值的填充

机器学习基础:缺失值的处理技巧(附Python代码)

Python3 DataFrame缺失值的处理

Python3 DataFrame缺失值的处理

​一文看懂数据清洗:缺失值、异常值和重复值的处理