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.1726209 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.1726209 chr19 50949779 NA 0 1 0
2. 去除NA
非常暴力,直接使用函数na.omit() 就可以直接对向量或者数据框操作了。会直接返回一个去除NA 所在行的新向量或数据框:
> a=na.omit(c(1,2,3,NA,'sdas'))> a[1] "1" "2" "3" "sdas"attr(,"na.action")[1] 4attr(,"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> XX1 X21 A 12 B NA3 C 34 D 45 E 56 <NA> 6
很快啊~
> library(tidyr)> drop_na(X,X1)X1 X21 A 12 B NA3 C 34 D 45 E 5
虽然我们也可以使用基础包做到,方法有很多啦~
> X[X$X1 %in% as.character(na.omit(X$X1)),]X1 X21 A 12 B NA3 C 34 D 45 E 5
replace_na()
这个函数我很喜欢,可以将指定列中的NA 替换为指定的数值:
> XX1 X21 A 12 B NA3 C 34 D 45 E 56 <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 X21 A 12 B 13 C 34 D 45 E 56 E 6> XX1 X21 A 12 B NA3 C 34 D 45 E 56 <NA> 6
函数中参数设置
很多函数,都有参数na.rm 可以直接在对列表操作时去除NA 值,比如:
mean()
