28. R 数据整理(三:缺失值NA 的处理方法汇总)
1. 获得NA 位置
可以使用is.na() 函数对向量进行遍历,如果存在NA,则会返回TRUE,反之。
> is.na(c(1,2,3,NA,'sdas'))
[1] FALSE FALSE FALSE TRUE FALSE
# 我们可以直接用which 获取TRUE 所在的index
但是,这个函数并不能很好的使用在数据框中,比如我们想要获得缺失值所在行呢?其会返回一个矩阵,对应的缺失值会在对应位置返回一个TRUE,如果这时候通过which 获取,其只会返回一个坐标,这是因为数据框经过is.na 后返回一个矩阵,而矩阵的坐标关系和向量又非常的微妙,其本质也就是向量的不同的排列,可以通过下面例子感受一下:
> matrix(c(1,2,3,NA,'sdas',4),ncol=2, byrow = 2)
[,1] [,2]
[1,] "1" "2"
[2,] "3" NA
[3,] "sdas" "4"
> which(is.na(matrix(c(1,2,3,NA,'sdas',4),ncol=2, byrow = 2)))
[1] 5
> matrix(c(1,2,3,NA,'sdas',4),ncol=2)
[,1] [,2]
[1,] "1" NA
[2,] "2" "sdas"
[3,] "3" "4"
> which(is.na(matrix(c(1,2,3,NA,'sdas',4),ncol=2)))
[1] 4
会自动按照行来进行重组,比如矩阵:
[,1] [,2]
[1,] "1" NA
[2,] "2" "sdas"
[3,] "3" "4"
就相当于在1,2,3,NA... 中找了第四个NA(按照行)。
如果你是个数学鬼才,可以计算一下,也就是所在坐标对行数取余,这个余就是NA所在的行数:
> which(is.na(rcmat))
[1] 205214
> 205214%%70544
[1] 64126
> rcmat[64126,]
CHROM POS dp ad dp.1 ad.1
726209 chr19 50949779 NA 0 1 0
亦或是,你可以写个循环,对每行判断,一旦有any(存在TRUE) ,则该行存在NA值。
还有一个不错的方法,就是通过rowSums 函数,对行求和。我们都知道,布尔值实际就是0和1,我们可以利用这个特性,获得那些经过is.na 后,行和不是0 的行,那就代表其存在表示TRUE(NA)的数据了:
> rcmat[!rowSums(is.na(rcmat)) == 0, ]
CHROM POS dp ad dp.1 ad.1
726209 chr19 50949779 NA 0 1 0
2. 去除NA
非常暴力,直接使用函数na.omit() 就可以直接对向量或者数据框操作了。会直接返回一个去除NA 所在行的新向量或数据框:
> a=na.omit(c(1,2,3,NA,'sdas'))
[1] "1" "2" "3" "sdas"
attr(,"na.action")
[1] 4
attr(,"class")
[1] "omit"
> class(a)
[1] "character"
> as.character(a)
[1] "1" "2" "3" "sdas"
3. tidyverse 中的高级函数
drop_na()
效果和na.omit 一样,但是高级之处在于,其可以指定列,对数据框某列存在NA 的行直接删除:
> X[2,2] = NA;X[6,1] = NA
X1 X2
1 A 1
2 B NA
3 C 3
4 D 4
5 E 5
6 <NA> 6
很快啊~
> library(tidyr)
> drop_na(X,X1)
X1 X2
1 A 1
2 B NA
3 C 3
4 D 4
5 E 5
虽然我们也可以使用基础包做到,方法有很多啦~
> X[X$X1 %in% as.character(na.omit(X$X1)),]
X1 X2
1 A 1
2 B NA
3 C 3
4 D 4
5 E 5
replace_na()
这个函数我很喜欢,可以将指定列中的NA 替换为指定的数值:
> X
X1 X2
1 A 1
2 B NA
3 C 3
4 D 4
5 E 5
6 <NA> 6
> replace_na(X$X1,0)
[1] "A" "B" "C" "D" "E" "0"
> replace_na(X$X2,6)
[1] 1 6 3 4 5 6
fill()
不同于drop_na 的直接暴力删除,fill 非常贴心的将缺失值替换为其所在列的上一行数值的值:
> fill(X,X1,X2)
X1 X2
1 A 1
2 B 1
3 C 3
4 D 4
5 E 5
6 E 6
X1 X2
1 A 1
2 B NA
3 C 3
4 D 4
5 E 5
6 <NA> 6