R语言-缺失值处理4
R语言:缺失值处理
前言
《数据挖掘:R语言实战》第5章数据预处理,本章我们将使用mice软件包中的示例数据集来进行数据预处理演示,由于mice软件包以软件包lattice、MASS及nnet为基础建立,因此在加载mice软件包前要先安装、加载这三个软件包。本节为大家介绍缺失值处理。
缺失值是数据中经常出现的问题,也是任何数据集中都可能出现的问题,无回答、录入错误等调查中常会出现的现象都会导致缺失数据。缺失值通常会用一些特殊符号进行标记,比如9999、1990年1月1日,或者是“*”、“?”、“#”、“$”等符号。
缺失数据会影响分析工作的进行,进而影响统计工作的效率,还会导致分析的偏差。数据使用者、分析者往往缺乏缺失值处理方面的知识,仅仅对数据进行简单删除或插补会影响数据规模和数据结构,进而影响分析结果。
目录
1. 判断是否存在缺失值
2. 缺失值处理
1. 缺失值与数值比较
在数据预处理中,首先要做的通常是判断是否存在缺失值。在R语言中缺失值通常以NA表示,可以使用函数is.na判断缺失值。
#计算nhanes2中缺失值的数量
> sum(is.na(nhanes2))
[1] 27
另一个常用到的函数是complete.cases,用来判断某一观测样本是否完整。
#计算nhanes2中完整样本的数量
> sum(complete.cases(nhanes2))
[1] 13
两个函数结果分别表示数据中共有27个缺失值以及数据框中共有13条完整观测值,即有12条观测值中存在缺失值。
在存在缺失数据的情况下,需要进一步对数据缺失状况进行观测,判断缺失数据是否随机。我们可以利用mice包中的md.pattern函数完成这一任务。
#观测nhanes2中缺失值的情况
> md.pattern(nhanes2)
age hyp bmi chl
13 1 1 1 1 0
1 1 1 0 1 1
3 1 1 1 0 1
1 1 0 0 1 2
7 1 0 0 0 3
0 8 9 10 27
>
其中1表示没有缺失数据,0表示存在缺失数据。第一行第一列的13表示有13个样本是完整的,即不存在缺失数据。第一列最后一个7表示有7个样本少了hyp、bmi、chl三个变量,最后一行表示各个变量缺失的样本数合计。
对于缺失数据最简单粗暴的方式,即是直接删除含有缺失值的样本,这样做有时也是最为简单有效的方法,但前提是缺失数据的比例较少,且缺失数据是随机出现的,这样删除缺失数据后对分析结果影响不大。
另外,也可采取用变量均值或中位数来代替缺失值的方式,其优点在于不会减少样本信息,处理简单;其缺点在于当缺失数据不是随机出现时会产成偏误。
而多重插补法(Multivariate Imputation)通过变量间的关系对缺失数据进行预测,利用蒙特卡洛方法生成多个完整的数据集,再对这些数据集分别进行分析,最后对分析结果进行汇总处理。
在R语言中,可以通过调用mice包中的mice函数实现,函数的基本形式是:
mice(data, m = 5,...)
其中,data代表一个有缺失值的数据框或矩阵,缺失值用NA表示;m表示插补重数,即生成m个完整数据集,默认值为m=5。
举个例子,若要构建以chl为因变量,age、hyp、bmi为自变量的线性回归模型,因为nhanes2数据中存在缺失值,不能直接用来构建模型,因此可以利用mice()函数,通过如下方式构建模型:
> # 生成4组完整的数据库并赋给imp
> imp=mice(nhanes2,m=4)
iter imp variable
1 1 bmi hyp chl
1 2 bmi hyp chl
1 3 bmi hyp chl
1 4 bmi hyp chl
2 1 bmi hyp chl
2 2 bmi hyp chl
2 3 bmi hyp chl
2 4 bmi hyp chl
3 1 bmi hyp chl
3 2 bmi hyp chl
3 3 bmi hyp chl
3 4 bmi hyp chl
4 1 bmi hyp chl
4 2 bmi hyp chl
4 3 bmi hyp chl
4 4 bmi hyp chl
5 1 bmi hyp chl
5 2 bmi hyp chl
5 3 bmi hyp chl
5 4 bmi hyp chl
> # 生成线性回归模型
> fit=with(imp,lm(chl~age+hyp+bmi))
> fit
call :
with.mids(data = imp, expr = lm(chl ~ age + hyp + bmi))
call1 :
mice(data = nhanes2, m = 4)
nmis :
age bmi hyp chl
0 9 8 10
analyses :
[[1]]
Call:
lm(formula = chl ~ age + hyp + bmi)
Coefficients:
(Intercept) age2 age3 hyp2
-29.3721 42.0197 60.0936 0.6452
bmi
7.4739
[[2]]
Call:
lm(formula = chl ~ age + hyp + bmi)
Coefficients:
(Intercept) age2 age3 hyp2
10.017 62.164 76.705 -11.433
bmi
5.546
[[3]]
Call:
lm(formula = chl ~ age + hyp + bmi)
Coefficients:
(Intercept) age2 age3 hyp2
34.7142 36.1401 46.6008 -0.3335
bmi
5.1506
[[4]]
Call:
lm(formula = chl ~ age + hyp + bmi)
Coefficients:
(Intercept) age2 age3 hyp2
31.090 46.228 66.794 -5.168
bmi
5.243
> # 对建立的4个模型进行汇总
> pooled=pool(fit)
> # 展示pooled的内容
> summary(pooled)
est se t df
(Intercept) 11.612394 66.290179 0.1751752 10.773211
age2 46.637976 23.213129 2.0091207 9.557044
age3 62.548392 26.015523 2.4042719 9.379841
hyp2 -4.072112 19.618366 -0.2075663 15.608178
bmi 5.853575 2.339205 2.5023781 9.980666
Pr(>|t|) lo 95 hi 95 nmis
(Intercept) 0.86419087 -134.6669203 157.89171 NA
age2 0.07359557 -5.4108898 98.68684 NA
age3 0.03857194 4.0584799 121.03830 NA
hyp2 0.83825159 -45.7462023 37.60198 NA
bmi 0.03136061 0.6401328 11.06702 9
fmi lambda
(Intercept) 0.3555612 0.24608572
age2 0.4016100 0.28824681
age3 0.4086948 0.29476141
hyp2 0.1959925 0.09917185
bmi 0.3850863 0.27308700
>
生成多个完整数据集储存于imp中,再对imp进行线性回归,最后用pool函数对回归结果进行汇总。汇总结果的前面部分和普通回归结果相似,nmis表示了变量中的缺失数据个数,fmi表示fraction of missing information,即由缺失数据贡献的变异。
2. 缺失值处理
在对是否存在缺失值进行判断后,我们将对缺失值的处理方法进行讲解。
1.删除法
在不影响数据结构的情况下,删除法是最简单的将缺失数据集转变成完整数据集的方法。根据数据处理的不同角度,可以将删除法分为以下4种。
(1)删除观测样本。
(2)删除变量:当某个变量缺失值较多且对研究目标影响不大时,可以将整个变量整体删除。
(3)使用完整原始数据分析:当数据存在较多缺失而其原始数据完整时,可以使用原始数据替代现有数据进行分析。
(4)改变权重:当删除缺失数据会改变数据结构时,通过对完整数据按照不同的权重进行加权,可以降低删除缺失数据带来的偏差。
2.插补法
删除数据虽然简单易行,但会带来信息浪费、改变数据结构等问题,因此在条件允许的情况下,找到缺失值的替代值来进行插补,尽可能还原真实数据是更好的方法。
下面介绍均值插补、回归插补、二阶插补、热平台、冷平台、抽样填补等单一变量插补,多变量插补是单变量插补的推广,请读者自行尝试。
在插补方法中,最简单的是从总体中随机抽取某个样本代替缺失样本。
R程序如下:
# 返回nhanes2数据集中第4列为NA的行
> sub=which(is.na(nhanes2[,4])==TRUE)
# 将第4列不为NA的数存入数据集dataTR中
> dataTR=nhanes2[-sub,]
# 将第4列为NA的数存入数据集dataTE中
> dataTE=nhanes2[sub,]
# 在非缺失值中简单抽样
> dataTE[,4]=sample(dataTR[,4],length(dataTE[,4]),replace=T)
> dataTE
age bmi hyp chl
1 20-39 NA <NA> 186
4 60-99 NA <NA> 113
10 40-59 NA <NA> 187
11 20-39 NA <NA> 204
12 40-59 NA <NA> 238
15 20-39 29.6 no 131
16 20-39 NA <NA> 186
20 60-99 25.5 yes 229
21 20-39 NA <NA> 206
24 60-99 24.9 no 238
均值法是通过计算缺失值所在变量所有非缺失观测值的均值,使用均值来代替缺失值的插补方法。
类似的,可以使用中位数、四分位数等进行插补,下面仅以均值法为例来对nhanes2数据集的第4列进行实现。
# 返回nhanes2数据集中第4列为NA的行
> sub=which(is.na(nhanes2[,4])==TRUE)
# 将第四列不为NA的数存入数据集dataTR中
> dataTR=nhanes2[-sub,]
# 将第四列为NA的数存入数据集dataTE中
> dataTE=nhanes2[sub,]
# 用非缺失值的均值代替缺失值
> dataTE[,4]=mean(dataTR[,4])
> dataTE
age bmi hyp chl
1 20-39 NA <NA> 191.4
4 60-99 NA <NA> 191.4
10 40-59 NA <NA> 191.4
11 20-39 NA <NA> 191.4
12 40-59 NA <NA> 191.4
15 20-39 29.6 no 191.4
16 20-39 NA <NA> 191.4
20 60-99 25.5 yes 191.4
21 20-39 NA <NA> 191.4
24 60-99 24.9 no 191.4
由于随机插补和均值插补中没有利用到相关变量信息,因此会存在一定偏差,而回归模型是将需要插补变量作为因变量,其他相关变量作为自变量,通过建立回归模型预测出因变量的值对缺失变量进行插补。
# 返回nhanes2数据集中第4列为NA的行
> sub=which(is.na(nhanes2[,4])==TRUE)
# 将第4列不为NA的数存入数据集dataTR中
> dataTR=nhanes2[-sub,]
# 将第4列为NA的数存入数据集dataTE中
> dataTE=nhanes2[sub,]
# dataTE数据
> dataTE
age bmi hyp chl
1 20-39 NA <NA> NA
4 60-99 NA <NA> NA
10 40-59 NA <NA> NA
11 20-39 NA <NA> NA
12 40-59 NA <NA> NA
15 20-39 29.6 no NA
16 20-39 NA <NA> NA
20 60-99 25.5 yes NA
21 20-39 NA <NA> NA
24 60-99 24.9 no NA
# 利用dataTR中age为自变量,chl为因变量构建线性回归模型lm
> lm=lm(chl~age,data=dataTR)
# 利用dataTE中数据按照模型lm对nhanes2中chl中的缺失数据进行预测
> nhanes2[sub,4]=round(predict(lm,dataTE))
# 缺失值处理后的nhanes2的前若6条
> head(nhanes2)
age bmi hyp chl
1 20-39 NA <NA> 169
2 40-59 22.7 no 187
3 20-39 NA no 187
4 60-99 NA <NA> 225
5 20-39 20.4 no 113
6 60-99 NA <NA> 184
热平台插补是指在非缺失数据集中找到一个与缺失值所在样本相似的样本(匹配样本),利用其中的观测值对缺失值进行插补。
# 存在缺失值的样本
> accept=nhanes2[which(apply(is.na(nhanes2),1,sum)!=0),]
# 无缺失值的样本
> donate=nhanes2[which(apply(is.na(nhanes2),1,sum)==0),]
> accept[1,]
age bmi hyp chl
1 20-39 NA <NA> 169
> donate[1,]
age bmi hyp chl
2 40-59 22.7 no 187
上述程序按照样本中是否含有缺失值将nhanes2分成存在缺失值和无缺失值两个数据表,分别命名为accept和donate。对于accept中的每个样本,热平台插补就是在donate中找到与该样本相似的样本,用相似样本的对应值代替该样本的缺失值。如,对于accept中的第2个样本,插补方法如下:
> accept[2,]
age bmi hyp chl
3 20-39 NA no 187
# 寻找与accept中第2个样本相似的样本
> sa=donate[which(donate[,1]==accept[2,1]&donate[,3]==accept[2,3]&donate[,4]==accept[2,4]),]
> sa
age bmi hyp chl
8 20-39 30.1 no 187
# 用找到的样本的对应值替代缺失值
> accept[2,2]=sa[1,2]
> accept[2,]
age bmi hyp chl
3 20-39 30.1 no 187
在实际操作中,尤其当变量数量很多时,通常很难找到与需要插补样本完全相同的样本,此时可以按照某些变量将数据分层,在层中对缺失值使用均值插补,即采取冷平台插补方法。
# 按照变量hyp分层
> level1=nhanes2[which(nhanes2[,3]=="yes"),]
> level1
age bmi hyp chl
14 40-59 28.7 yes 204
17 60-99 27.2 yes 284
18 40-59 26.3 yes 199
20 60-99 25.5 yes 225
# 用层内均值代替第4个样本的缺失值
> level1[4,4]=mean(level1[1:3,4])
> level1
age bmi hyp chl
14 40-59 28.7 yes 204
17 60-99 27.2 yes 284
18 40-59 26.3 yes 199
20 60-99 25.5 yes 229
转载请注明:数据分析 » R语言-缺失值处理4_判断是否存在缺失值_R语言缺失值处理