1. 获得NA 位置

可以使用is.na() 函数对向量进行遍历,如果存在NA,则会返回TRUE,反之。

  1. > is.na(c(1,2,3,NA,'sdas'))
  2. [1] FALSE FALSE FALSE TRUE FALSE
  3. # 我们可以直接用which 获取TRUE 所在的index

但是,这个函数并不能很好的使用在数据框中,比如我们想要获得缺失值所在行呢?其会返回一个矩阵,对应的缺失值会在对应位置返回一个TRUE,如果这时候通过which 获取,其只会返回一个坐标,这是因为数据框经过is.na 后返回一个矩阵,而矩阵的坐标关系和向量又非常的微妙,其本质也就是向量的不同的排列,可以通过下面例子感受一下:

  1. > matrix(c(1,2,3,NA,'sdas',4),ncol=2, byrow = 2)
  2. [,1] [,2]
  3. [1,] "1" "2"
  4. [2,] "3" NA
  5. [3,] "sdas" "4"
  6. > which(is.na(matrix(c(1,2,3,NA,'sdas',4),ncol=2, byrow = 2)))
  7. [1] 5
  8. > matrix(c(1,2,3,NA,'sdas',4),ncol=2)
  9. [,1] [,2]
  10. [1,] "1" NA
  11. [2,] "2" "sdas"
  12. [3,] "3" "4"
  13. > which(is.na(matrix(c(1,2,3,NA,'sdas',4),ncol=2)))
  14. [1] 4

会自动按照行来进行重组,比如矩阵:

  1. [,1] [,2]
  2. [1,] "1" NA
  3. [2,] "2" "sdas"
  4. [3,] "3" "4"

就相当于在1,2,3,NA… 中找了第四个NA(按照行)。

如果你是个数学鬼才,可以计算一下,也就是所在坐标对行数取余,这个余就是NA所在的行数:

  1. > which(is.na(rcmat))
  2. [1] 205214
  3. > 205214%%70544
  4. [1] 64126
  5. > rcmat[64126,]
  6. CHROM POS dp ad dp.1 ad.1
  7. 726209 chr19 50949779 NA 0 1 0

亦或是,你可以写个循环,对每行判断,一旦有any(存在TRUE) ,则该行存在NA值。

还有一个不错的方法,就是通过rowSums 函数,对行求和。我们都知道,布尔值实际就是0和1,我们可以利用这个特性,获得那些经过is.na 后,行和不是0 的行,那就代表其存在表示TRUE(NA)的数据了:

  1. > rcmat[!rowSums(is.na(rcmat)) == 0, ]
  2. CHROM POS dp ad dp.1 ad.1
  3. 726209 chr19 50949779 NA 0 1 0

2. 去除NA

非常暴力,直接使用函数na.omit() 就可以直接对向量或者数据框操作了。会直接返回一个去除NA 所在行的新向量或数据框:

  1. > a=na.omit(c(1,2,3,NA,'sdas'))
  2. > a
  3. [1] "1" "2" "3" "sdas"
  4. attr(,"na.action")
  5. [1] 4
  6. attr(,"class")
  7. [1] "omit"
  8. > class(a)
  9. [1] "character"
  10. > as.character(a)
  11. [1] "1" "2" "3" "sdas"

3. tidyverse 中的高级函数

drop_na()

效果和na.omit 一样,但是高级之处在于,其可以指定列,对数据框某列存在NA 的行直接删除:

  1. > X[2,2] = NA;X[6,1] = NA
  2. > X
  3. X1 X2
  4. 1 A 1
  5. 2 B NA
  6. 3 C 3
  7. 4 D 4
  8. 5 E 5
  9. 6 <NA> 6

很快啊~

  1. > library(tidyr)
  2. > drop_na(X,X1)
  3. X1 X2
  4. 1 A 1
  5. 2 B NA
  6. 3 C 3
  7. 4 D 4
  8. 5 E 5

虽然我们也可以使用基础包做到,方法有很多啦~

  1. > X[X$X1 %in% as.character(na.omit(X$X1)),]
  2. X1 X2
  3. 1 A 1
  4. 2 B NA
  5. 3 C 3
  6. 4 D 4
  7. 5 E 5

replace_na()

这个函数我很喜欢,可以将指定列中的NA 替换为指定的数值:

  1. > X
  2. X1 X2
  3. 1 A 1
  4. 2 B NA
  5. 3 C 3
  6. 4 D 4
  7. 5 E 5
  8. 6 <NA> 6
  9. > replace_na(X$X1,0)
  10. [1] "A" "B" "C" "D" "E" "0"
  11. > replace_na(X$X2,6)
  12. [1] 1 6 3 4 5 6

fill()

不同于drop_na 的直接暴力删除,fill 非常贴心的将缺失值替换为其所在列的上一行数值的值:

  1. > fill(X,X1,X2)
  2. X1 X2
  3. 1 A 1
  4. 2 B 1
  5. 3 C 3
  6. 4 D 4
  7. 5 E 5
  8. 6 E 6
  9. > X
  10. X1 X2
  11. 1 A 1
  12. 2 B NA
  13. 3 C 3
  14. 4 D 4
  15. 5 E 5
  16. 6 <NA> 6

函数中参数设置

很多函数,都有参数na.rm 可以直接在对列表操作时去除NA 值,比如:

  1. mean()