R语言中缺失值的识别与可视化

R语言中缺失值的识别与可视化

在问卷数据或实验数据中,经常会包含由于未作答、设备故障或误编码数据的缘故出现缺失值。处理带有缺失值的数据是一件很普遍的事,同时也是一件麻烦事,本文教大家如何在R中找出缺失值,探索缺失值模式和处理缺失值。选用R语言的原因是因为它可以将缺失值可视化,非常直观地看出缺失值在哪里。

数据缺失的原因

数据缺失有多种原因,如:

  1. 调查对象忘记回答一个或多个问题;
  2. 调查对象拒绝回答敏感问题;
  3. 感觉疲劳而没有完成一份很长的问卷;
  4. 错过了约定;
  5. 过早地从研究中退出;
  6. 记录设备出现问题;
  7. 网络连接失效;
  8. 数据误记等。

在R中,缺失值以符号NA表示,NA就是Not Available的缩写。本文主要使用VIM和mice包,如果你的R中没有安装过这两个包,需要先安装然后载入。

#安装VIM和mice包
install.packages(c("VIM","mice")) 
# 载入VIM和mice包
library(VIM)
library(mice)

本次分析使用的数据集sleep就是VIM包中包含的数据集,看这个名字就是这些数据和睡眠有关,其实是哺乳动物睡眠数据。来源于Allison和Chichetti (1976)的研究。

自变量:生态学变量、体质变量

因变量:睡眠变量

生态学变量包含:物种被捕食程度(Pred),睡眠时的暴露程度(Exp),面临的总危险度(Danger)。1(低)到5(高)计分。

体质变量包含:体重(BodyWgt,单位kg),脑重(BrainWgt,单位g),寿命(Span,单位年),妊娠期(Gest,单位为天)。

睡眠变量包含:做梦时长(Dream),不做梦时长(NonD)以及它们的和(Sleep)。

在分析缺失值之前,我们先熟悉一下sleep数据集的构成。

# 查看sleep数据框中的信息
str(sleep)
'data.frame':	62 obs. of  10 variables:
 $ BodyWgt : num  6654 1 3.38 0.92 2547 ...
 $ BrainWgt: num  5712 6.6 44.5 5.7 4603 ...
 $ NonD    : num  NA 6.3 NA NA 2.1 9.1 15.8 5.2 10.9 8.3 ...
 $ Dream   : num  NA 2 NA NA 1.8 0.7 3.9 1 3.6 1.4 ...
 $ Sleep   : num  3.3 8.3 12.5 16.5 3.9 9.8 19.7 6.2 14.5 9.7 ...
 $ Span    : num  38.6 4.5 14 NA 69 27 19 30.4 28 50 ...
 $ Gest    : num  645 42 60 25 624 180 35 392 63 230 ...
 $ Pred    : int  3 3 1 5 3 4 1 4 1 1 ...
 $ Exp     : int  5 1 1 2 5 4 1 5 2 1 ...
 $ Danger  : int  3 3 1 3 4 4 1 4 1 1 ...
# 我们也可以用head()查看数据集中的数据,默认给出前6行
head(sleep)
 BodyWgt BrainWgt NonD Dream Sleep Span Gest Pred Exp Danger
1 6654.000   5712.0   NA    NA   3.3 38.6  645    3   5      3
2    1.000      6.6  6.3   2.0   8.3  4.5   42    3   1      3
3    3.385     44.5   NA    NA  12.5 14.0   60    1   1      1
4    0.920      5.7   NA    NA  16.5   NA   25    5   2      3
5 2547.000   4603.0  2.1   1.8   3.9 69.0  624    3   5      4
6   10.550    179.5  9.1   0.7   9.8 27.0  180    4   4      4

我们可以看到sleep这个数据集是个数据框data.frame,包含10个变量,62条数据。其中前7个的数据类型为数值型num,后三个为整数型int。

比如第一条数据中,该动物的体重是6654千克,脑重是5712克,不做梦时长缺失,做梦时长缺失,睡眠时间3.3小时,寿命38.6年,妊娠期645天,被捕食程度3分,睡眠时的暴露程度5分,面临的总危险度3分。


识别缺失值

(1)is.na函数

在R中,可以用函数is.na( )检测缺失值是否存在。它将返回一个相同大小的对象,如果某个元素是缺失值,相应的位置将被改写为TRUE,不是缺失值的位置则为FALSE。

#检测sleep数据集的缺失值
is.na(sleep)
      BodyWgt BrainWgt  NonD Dream Sleep  Span  Gest  Pred   Exp Danger
 [1,]   FALSE    FALSE  TRUE  TRUE FALSE FALSE FALSE FALSE FALSE  FALSE
 [2,]   FALSE    FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE  FALSE
 [3,]   FALSE    FALSE  TRUE  TRUE FALSE FALSE FALSE FALSE FALSE  FALSE
 [4,]   FALSE    FALSE  TRUE  TRUE FALSE  TRUE FALSE FALSE FALSE  FALSE
 [5,]   FALSE    FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE  FALSE
 [6,]   FALSE    FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE  FALSE

由于篇幅限制,我们就看前6条数据,拿第一条数据举例,可以看出该动物在NonD和Dream上的数据是缺失的,在其他变量上没有缺失数据。

使用sum汇总有缺失值的数据条数,可以看到sleep数据集共有38条缺失值。

sum(is.na(sleep))
[1] 38

如果想单独查看某个变量上共含几条缺失值,只需在数据集后加上变量名。这里我们查看有多少条数据在寿命这个变量上是缺失的。

sum(is.na(sleep$Span))
[1] 4

(2)complete.cases函数

函数complete.cases( )可以用来识别矩阵或数据框中没有缺失值的行。若每行都包含完整实例,则返回TRUE的逻辑向量;若每行有一个或多个缺失值,则返回FALSE。

# 加载VIM包中的哺乳动物睡眠数据集sleep
data(sleep, package="VIM")
# 列出没有缺失值的行
sleep[complete.cases(sleep),]
    BodyWgt BrainWgt NonD Dream Sleep  Span  Gest Pred Exp Danger
2     1.000     6.60  6.3   2.0   8.3   4.5  42.0    3   1      3
5  2547.000  4603.00  2.1   1.8   3.9  69.0 624.0    3   5      4
6    10.550   179.50  9.1   0.7   9.8  27.0 180.0    4   4      4
7     0.023     0.30 15.8   3.9  19.7  19.0  35.0    1   1      1
8   160.000   169.00  5.2   1.0   6.2  30.4 392.0    4   5      4
9     3.300    25.60 10.9   3.6  14.5  28.0  63.0    1   2      1
10   52.160   440.00  8.3   1.4   9.7  50.0 230.0    1   1      1

我们可以看到以上这些数据均没有缺失值。下面我们在语句前加入感叹号!,!代表“非”,所以sleep[!complete.cases(sleep),]的意思就是列出有缺失值的行。

# 列出有一个或多个缺失值的行
sleep[!complete.cases(sleep),]
  BodyWgt BrainWgt NonD Dream Sleep Span Gest Pred Exp Danger
1  6654.000   5712.0   NA    NA   3.3 38.6  645    3   5      3
3     3.385     44.5   NA    NA  12.5 14.0   60    1   1      1
4     0.920      5.7   NA    NA  16.5   NA   25    5   2      3
13    0.550      2.4  7.6   2.7  10.3   NA   NA    2   1      2
14  187.100    419.0   NA    NA   3.1 40.0  365    5   5      5
19    1.410     17.5  4.8   1.3   6.1 34.0   NA    1   2      1
20   60.000     81.0 12.0   6.1  18.1  7.0   NA    1   1      1

从以上数据可以看出,每行至少有一个缺失值NA,也可能包含多个NA。


(3)md.pattern函数

mice包中的md.pattern,形成缺失表

md.pattern(data)
md.pattern(sleep)
    BodyWgt BrainWgt Pred Exp Danger Sleep Span Gest Dream NonD   
42       1        1    1   1      1     1    1    1     1    1  0
 2       1        1    1   1      1     1    0    1     1    1  1
 3       1        1    1   1      1     1    1    0     1    1  1
 9       1        1    1   1      1     1    1    1     0    0  2
 2       1        1    1   1      1     0    1    1     1    0  2
 1       1        1    1   1      1     1    0    0     1    1  2
 2       1        1    1   1      1     0    1    1     0    0  3
 1       1        1    1   1      1     1    0    1     0    0  3
         0        0    0   0      0     4    4    4    12   14 38

1表示无缺失,0表示有缺失。

第一列表示该行模式数据的个数,该行没有缺失值,也就是在数据集sleep中,没有缺失值的数据共42条。缺失Span的数据共2条,同时缺失Dream和NonD的数据共9条。


(4)aggr函数

aggr是VIM包中的函数,可以形成缺失图。

aggr(sleep, prop = F, number = T)
prop = F

红色表示缺失的数量,这是因为prop是false。当prop是true的时候,纵轴便是缺失值的比例。

prop= T

我们也可以将aggr的结果赋值给a,然后查看a

a <- aggr(sleep, P= F, N= T)
summary(a)
 Missings per variable: 
 Variable Count
  BodyWgt     0
 BrainWgt     0
     NonD    14
    Dream    12
    Sleep     4
     Span     4
     Gest     4
     Pred     0
      Exp     0
   Danger     0
 Missings in combinations of variables: 
        Combinations Count   Percent
 0:0:0:0:0:0:0:0:0:0    42 67.741935
 0:0:0:0:0:0:1:0:0:0     3  4.838710