R极简教程-8:缺失值与异常值

OK,数据都进来了,下一步要做的是查看数据质量怎么样?尤其要关注的两个问题是,有没有缺失值和异常值。

缺失值

这个很好理解,就是数据不见了呗。比如采集了5000行500列数据,其中某几个数据因为采集或者记录原因失败了,就造成了缺失值。缺失值在R语言中一般用NA来代替。(比如读取文件的时候,如果有些行有些列没有数值,就会自动填为NA)。

R使用NA(不可得)代表缺失值、NaN(不是一个数)代表不可能的值、Inf和-Inf代表正无穷和负无穷,函数is.na()、is.nan()、is.infinite()可分别用于识别缺失值、不可能值和无穷值。

再读取了一批文件以后,我们可以用is.na()函数来查看缺失值:

> A <- matrix(1:36,6,6)
> A
     [,1] [,2] [,3] [,4] [,5] [,6]
[1,]    1    7   13   19   25   31
[2,]    2    8   14   20   26   32
[3,]    3    9   15   21   27   33
[4,]    4   10   16   22   28   34
[5,]    5   11   17   23   29   35
[6,]    6   12   18   24   30   36
> A[1,3] <- NA
> A[5,2] <- NA
> A[6,6] <- NA
> A
     [,1] [,2] [,3] [,4] [,5] [,6]
[1,]    1    7   NA   19   25   31
[2,]    2    8   14   20   26   32
[3,]    3    9   15   21   27   33
[4,]    4   10   16   22   28   34
[5,]    5   NA   17   23   29   35
[6,]    6   12   18   24   30   NA
> is.na(A)
      [,1]  [,2]  [,3]  [,4]  [,5]  [,6]
[1,] FALSE FALSE  TRUE FALSE FALSE FALSE
[2,] FALSE FALSE FALSE FALSE FALSE FALSE
[3,] FALSE FALSE FALSE FALSE FALSE FALSE
[4,] FALSE FALSE FALSE FALSE FALSE FALSE
[5,] FALSE  TRUE FALSE FALSE FALSE FALSE
[6,] FALSE FALSE FALSE FALSE FALSE  TRUE
> 

再上面的程序中,我们首先建立了一个矩阵A,然后在其中人工加入了三个缺失值。然后用is.na()可以判断,每一个数据是不是缺失值。

在这里which函数是非常有用的。(其实which函数再R语言中是一个非常重要的函数。)可以用which看出是那几个位置有错误。

> which(is.na(A))
[1] 11 13 36

我们定义的是一个矩阵,但是which出来的结果确实数字,这是因为which会将Matrix或者DataFrame展开成Vector,然后计算缺失值。就类似于as.vector(A)一样。如果想要确切地知道哪行哪列的数据是缺失值,可以在which函数中加入参数:

> which(is.na(A),arr.ind = T)
     row col
[1,]   5   2
[2,]   1   3
[3,]   6   6
> 

可以看出,我们准确地找到了NA值所在的行列。

缺失值可视化

简而言之就是,想要直观地看看你的数据中缺失值在哪里。最直观的看法就是使用热图(heatmap)(不是地图上红一块绿一块那种热力图!),我之前的教程里用到的pheatmap函数就是这方面的好工具。

在之前,我们用命令is.na()的时候,其实已经看出缺失值的,但是目前我们数据缺省值很少,如果缺失值多怎么办?

> #随机产生一个40行50列的矩阵
> A <- matrix(rnorm(2000,0,1),40,50)
> #再其中增加200个NA值。
> A[sample(1:2000,200)] <- NA
> #生成一个全部是1,维度与A相同的矩阵
> B <- matrix(1,nrow=nrow(A),ncol=ncol(A))
> #将B中A的NA值,设置为0
> B[is.na(A)] <- 0
> #用pheatmap函数plot所有的缺失值
> pheatmap(B,cluster_rows = F,cluster_cols = F)

这里写图片描述
上图中的蓝点就是这批数据中的缺失值。

下面的话出自某网络博客。我觉得说的很对:

识别缺失数据的数目、分布和模式有两个目的:分析生成缺失数据的潜在机制,评价缺失数据对回答实质性问题的影响。我们需要弄清楚以下几个问题:

缺失数据的比例多大?
缺失数据是否集中在少数几个变量上,或者广泛存在?
缺失是随机产生的吗?
缺失数据间的相关性或与可观测数据间的相关性,是否可以表明产生缺失值的机制?

这些就是不那么容易解决的问题了,比如说,每一列缺失数据比例多大,可以很简单的用一行代码算出来:

> colMeans(is.na(A))

至于第二个问题,缺失值是否存在某一些变量上,这样可以通过做barplot来看。

> barplot(colMeans(is.na(A)),names.arg = 1:50)

这里写图片描述
可以看出,大部分的列都有缺失值(那当然,我们是随机生成的缺失值。)

缺失值处理

一般来说,处理缺失值有两种办法:直接把数据删掉,或者用补足。删掉的意思就是,如果某一行出现了缺失值,无论这一行中缺失值有多少,直接将其删除,整行删除。补充的意思是,用附近的一些数据的值,计算一个估计值去填补这一个数。

直接删除的优缺点分别是:方便快捷,代码好写,但是有可能太多信息都会被遗漏掉。
补足(impute):的优缺点分别是:尽量保持了信息,但是如果一行数据10个,有9个是NA,那么补出来的数据也不会有多高的质量。

所以,缺失值处理是一个比较需要经验的问题,一般来说我的处理办法是,如果样本数据很多,比如列有上百个,那就先对列做缺失值比例计算,将缺失达到10%的样本直接删除。然后再剩下的数据中,按行做缺失值比例调查,将比例高达一定阈值(比如20%)的删掉,然后对剩下的数据做impute过程。

impute过程可以使用imputeR包,其中的impute.knn()函数很好用:

完整代码如下:

> A <- matrix(rnorm(2000,0,1),40,50)
> A[sample(1:2000,200)] <- NA

> colRatio <- colMeans(is.na(A))
> col_remain <- which(colRatio < 0.2)
> length(col_remain)
[1] 49
> C <- A[,col_remain]
> 
> rowRatio <- rowMeans(is.na(C))
> row_remain <- which(rowRatio < 0.2)
> length(row_remain)
[1] 40
> 
> D <- C[row_remain,]
> dim(D)
[1] 40 49
> library(impute)
> Final <- impute.knn(D)

异常值

异常值顾名思义就是偏离了“寻常值”的数据。但是多“异常”的值才能成为异常值,这就得看研究项目而定了。有些时候,异常值才是一个科研项目中应该去研究的问题。一般来说,有一个想对通用的检测异常值的标准,就是均值±三倍标准差。这个很好理解,你的均值是数据大部分“寻常值”的所在位置,标准差是其差异程度。那么3倍标准差很明显就说明一个数据严重地偏离了均值了。

下面我们用代码来写一下:

A <- rnorm(1000,0,1)
outlier_above <- which(A > mean(A) + 3*sd(A))
outlier_below <- which(A < mean(A) - 3*sd(A))

这里写图片描述

我们可以看到,在我随机生成了1000个随机数以后(正态分布,均值为0,标准差为1),只有4个数达到了异常值上届,也只有3个数达到了异常值的下届。

下面我们尝试把这些异常值画出来,其实代码特别简单:

boxplot(A)

这里写图片描述
该图的中文名叫做箱线图,其中上下的小圆点就是异常值的意思。最上边的横线是上边界,最下边是下边界,中间的箱体,上边缘是上四分位数,下边缘是下四分位数,中间最粗的横线是中位数(不是均值)。

个人觉得,有一个特别简单找出异常值的办法,就是使用boxplot函数:

> tmp <- boxplot(A)
> tmp$out
 [1]  3.338426  2.854525  3.500505  3.071915  2.853435  3.009685 -3.315813 -3.564299
 [9] -3.374682  2.744321
> 

直接将boxplot存储成为一个变量tmp,tmp中的out子元素就是异常值。

对于异常值的处理也是花样繁多,有的人就直接把所有异常值设置成为NA,然后就回到了上边的缺失值部分。也有人保留他们,总之这方面算法很多,不一而足。异常值产生的原因很多,有很多时候,异常值其实不仅有意义,而且很重要:

比如,探查人流涌动,就是通过异常值来看那些地方突然人数激增?探查宇宙射线一类的科研,最关注的东西永远都是异常值。再大数定律横行其道的今天,几乎各种数据都是需要量化来达到规律总结的,这恰好令了“天鹅”一类事件越来越难以估计。所以对于异常值的处理和解读,其实正是数据分析人员的水平高下所在。

在这一部分,我简单介绍了一下R语言中的缺失值和异常值。

  • 5
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值