(一)缺失值分析
在数据挖掘的过程中,数据预处理占到了整个过程的60%
脏数据:指一般不符合要求,以及不能直接进行相应分析的数据
脏数据包括:缺失值、异常值、不一致的值、重复数据及含有特殊符号(如#、¥、*)的数据
数据清洗:删除原始数据集中的无关数据、重复数据、平滑噪声数据、处理缺失值、异常值等
缺失值处理包括两个步骤:缺失数据的识别和缺失值处理。在R语言总缺失值以NA表示,使用函数is.na()判断缺失值是否存在,函数complete.cases()可识别样本数据是否完整从而判断缺失情况。缺失值处理常用方法有删除法、替换法、插补法。
1)删除法:可分为删除观测样本与删除变量。
删除观测样本通过na.omit()函数移除所有含有缺失数据的行,属于以减少样本量来换取信息完整性的方法,适用于缺失值所含比例较小的情况。
删除变量通过data[,-p]函数移除含有缺失数据的列,适用于变量有较大缺失且对研究目标影响不大的情况。
缺点:会存在信息浪费的问题,且数据结构会发生变动,以致最后得到有偏的统计结构。
(2)替换法:变量按属性可分为数值型和非数值型
缺失数据为数值型的一般用该变量在其他对象的取值均值来替换变量的缺失值
缺失数据为非数值型的一般用其他全部有效观测值的中位数或者众数来替换
缺点:会存在信息浪费的问题,且数据结构会发生变动,以致最后得到有偏的统计结构
(3)插补法:常用的插补方法有回归插补,多重插补
回归插补:利用回归模型,将需要插补的变量作为因变量,其他相关变量作为自变量,通过回归函数lm()预测出因变量的值来对缺失变量进行补缺
多重插补:是从一个包含缺失值的数据集中生成一组完整的数据,如此多次,从而产生缺失值的一组随机样本,R中的mice()函数可以用来进行多重插补。
1. 缺失值数据的分类
缺失值从缺失的分布来讲可以分为完全随机缺失,随机缺失和完全非随机缺失。
(1) 完全随机缺失(missing completely at random,MCAR)指的是数据的缺失是随机的,数据的缺失不依赖于任何不完全变量或完全变量。
(2) 随机缺失(missing at random,MAR)指的是数据的缺失不是完全随机的,即该类数据的缺失依赖于其他完全变量。
(3) 完全非随机缺失(missing not at random,MNAR)指的是数据的缺失依赖于不完全变量自身。
从缺失值的所属属性上讲,如果所有的缺失值都是同一属性,那么这种缺失成为单值缺失,如果缺失值属于不同的属性,称为任意缺失。另外对于时间序列类的数据,可能存在随着时间的缺失,这种缺失称为单调缺失。
2. 探索缺失值模式
(1)列表显示缺失值
mice包中的md.pattern()函数可以生成一个以矩阵或数据框形式展示缺失值模式的表格
library(mice)
data(sleep,package="VIM")
md.pattern(sleep)
1和0显示了缺失值模式,0:缺失值,1:没有缺失值。第一行表述了“无缺失值”的模式(所有元素都为1)。第四行表述了“除Span之外无缺失值”的模式。第一列表示各缺失值模式的实例个数,最后一列是各模式中有缺失值的变量的个数。此处可以看到,有42个实例没有缺失值,仅2个实例缺失了Span。9个实例同时缺失了NonD和Dream的值。数据集包含了总共(42*0)+(2*1)+...+(1*3)=38个缺失值。最后一行给出了每个变量中缺失值的数目。
(2)图形探究缺失数据
VIM包中提供大量能可视化数据集中缺失值模式的函数:aggr()、matrixplot()、scattMiss()
library("VIM")
aggr(sleep,prop=TRUE,numbers=TRUE)#用比例代替了计数
summary(aggr(sleep))
#matrixplot()函数可生成展示每个实例数据的图形
matrixplot(sleep)
#浅色表示值小,深色表示值大;默认缺失值为红色。
#marginplot()函数可生成一幅散点图,在图形边界展示两个变量的缺失值信息。
library("VIM")
marginplot(sleep[c("Gest","Dream")],pch=c(20),col=c("darkgray","red","blue"))
图形的主体是Gest(缺4个)和Dream(缺12个)的散点图。左边界的箱线图展示的是包含(深灰色)与不包含(红色)Gest值的Dream变量分布。注意,在灰度图上红色是更深的阴影。四个红点代表着缺失了Gest得分的Dream值。在底部边界,Gest和Dream间的关系反过来了。可以看到,妊娠期和做梦时长呈负相关,缺失妊娠期数据时动物的做梦时长一般更长。两个变量均有缺失值的观测个数在两边界交叉处(左下角)用蓝色输出。
VIM包有许多图形可以帮助我们理解缺失数据在数据集中的模式,包括散点图、箱线图、直方图、散点图矩阵、平行坐标图、轴须图和气泡图来展示缺失值的信息。
(3)用相关性探索缺失值
影子矩阵:用指示变量替代数据集中的数据(1:缺失,0:存在),生成的矩阵有时称作影子矩阵。
求这些指示变量间和它们与初始(可观测)变量间的相关性,有助于观察哪些变量常一起缺失,以及分析变量“缺失”与其他变量间的关系。
head(sleep)
str(sleep)
x<-as.data.frame(abs(is.na(sleep)))
head(sleep,n=5)
head(x,n=5)
sd=sapply(x,sd)
y<-x[which(sd>0)] #可提取含(但不全部是)缺失值的变量
cor(y)#列出这些指示变量间的相关系数
可以看到Dream和NonD常常一起缺失(r=0.91)。相对可能性较小的是Sleep和NonD一起缺失(r=0.49),以及Sleep和Dream(r=0.20)。
cor(sleep,y,use="pairwise.complete.obs")#含缺失值变量与其他可观测变量间的关系
在这个相关系数矩阵中,行代表可观测变量,列代表缺失的指示标量。从相关系数矩阵的第一列可以看到,体重越大(r=0.227)、妊娠期越长(r=0.202)、睡眠暴露度越大(r=0.245)的动物无梦睡眠的评分更可能缺失。其他列的信息也可以按照类似方式得出。注意,表中的相关系数并不特别大,表明数据是MCAR(完全随机缺失)的可能性比较小,更可能为MAR(随机缺失)。
不过也绝不能排除数据是NMAR(非随机缺失)的可能性,因为我们并不知道缺失数据背后对应的真实数据是怎么样的。当缺乏强力的外部证据时,我们通常假设数据是MCAR和MAR。
3. 理解缺失值数据的来由和影响
识别缺失数据的数目、分布和模式有两个目的:
(1)分析生成缺失数据的潜在机制;
(2)评价缺失数据对回答实质性问题的影响。
即:
(1)缺失数据的比例有多大?
(2)缺失数据是否集中在少数几个变量上,抑或广泛存在?
(3)缺失是随机产生的吗?
(4)缺失数据间的相关性或与可观测数据间的相关性,是否可以表明产生缺失值的机制呢?
若缺失数据集中在几个相对不太重要的变量上,则可以删除这些变量,然后再进行正常的数据分析;
若有一小部分数据随机分布在整个数据集中(MCAR),则可以分析数据完整的实例,这样仍可得到可靠有效的结果;
若以假定数据是MCAR或MAR,则可以应用多重插补法来获得有铲的结论。
若数据是NMAR,则需要借助专门的方法,收集新数据,或加入一个相对更容易、更有收益的行列。
4. 处理缺失值的方法
(1)成对删除——删除行/列(na.action=na.omit())
处理含缺失值的数据集时,成对删除常作为行删除的备选方法使用。对于成对删除,观测只是当它含缺失数据的变量涉及某个特定分析时才会被删除。
cor(sleep,use="pairwise.complete.obs")
虽然成对删除似乎利用了所有可用数据,但实际上每次计算只用了不同的数据集,这将会导致一些扭曲,故建议不要使用该方法。
适用条件:
足够大数据集(model doesn’t lose power)
不会引入偏差 (no disproportionate or non-representation ofclasses)
删列:不起重要预测作用的变量
(2)简单(非随机)插补——替换缺失值(如均值mean、中位数median或众数mode)
注意,替换是非随机的,这意味着不会引入随机误差(与多重衬托不同)。
简单插补的一个优点是,解决“缺失值问题”时不会减少分析过程中可用的样本量。虽然简单插补用法简单,但对于非MCAR的数据会产生有偏的结果。若缺失数据的数目非常大,那么简单插补很可能会低估标准差、曲解变量间的相关性,并会生成不正确的统计检验的p值。应尽量避免使用该方法。
适用条件:不需要非常精确的估算
# 用均值和特定值替换
# 自定义插补函数
library(VIM)
library(mice)
impute<-function(x,x.impute){ifelse(is.na(x),x.impute,x)}
sleep_IMP1<-list()
#sleep_IMP2<-list()
for(iinnames(sleep)){
#print(i)
sleep_IMP1[[i]]<-impute(sleep[[i]],lapply(na.omit(sleep),mean)[[i]])
#sleep_IMP2[[i]]<-impute(sleep[[i]],mean(na.omit(sleep[[i]])))
} #均值替换
sleep_IMP=as.data.frame(sleep_IMP1)
impute(sleep$Span,20) # 特定值替换
(3) 最近邻插补——kNN
# 最近邻填补缺失值
data(sleep,package="VIM")
## for missing values
a<-aggr(sleep)
summary(a)
## for imputed values
sleep_IMPUTED<-kNN(sleep)
a<-aggr(sleep_IMPUTED,delimiter="_imp")
summary(a)
data(sleep,package="VIM")
summary(aggr(sleep,plot=FALSE))
(4) 分类回归树——rpart
相比于kNN,rpart方法可以应用于分类数据
注意:rpart()建立分类回归树模型
对于分类变量,添加参数:method = “class”
对于数值变量,添加参数:method = “anova”
(5) 多重插补
多重插补(MI)是一种基于重复模拟的处理缺失值的方法。
MI从一个包含缺失值的数据集中生成一组完整的数据集。每个模拟数据集中,缺失数据将使用蒙特卡洛方法来填补。此时,标准的统计方法便可应用到每个模拟的数据集上,通过组合输出结果给出估计的结果。
可用到的包Amelia、mice和mi包
mice()函数首先从一个包含缺失数据的数据框开始,然后返回一个包含多个完整数据集的对象。每个完整数据集都是通过对原始数据框中的缺失数据进行插补而生成的。
with()函数可依次对每个完整数据集应用统计模型
pool()函数将这些单独的分析结果整合为一组结果。
最终模型的标准误和p值都将准确地反映出由于缺失值和多重插补而产生的不确定性。
基于mice包的分析通常符合以下分析过程:
#library(mice)
#imp<-mice(mydata,m)
#fit<-with(imp,analysis)
#pooled<-pool(fit)
#summary(pooled)
mydata是一个饮食缺失值的矩阵或数据框;imp是一个包含m个插补数据集的列表对象,同时还含有完成插补过程的信息,默认的m=5,analysis是一个表达式对象,用来设定应用于m个插补的统计分析方法。方法包括做线回归模型的lm()函数、做广义线性模型的glm()函数、做广义可加模型的gam()、及做负二项模型的nbrm()函数。fit是一个包含m个单独统计分析结果的列表对象;pooled是一个包含这m个统计分析平均结果的列表对象。
library(mice)
data(sleep,package="VIM")
imp<-mice(sleep,seed=1234)
fit<-with(imp,lm(Dream~Span+Gest))
pooled<-pool(fit)
summary(pooled)
imp$imp$Dream
#利用complete()函数可观察m个插补数据集中的任意一个,格式为:complete(imp,action=#)
dataset3<-complete(imp,action=3)
dataset3
·END·
超乎想象的体验