识别所有元素缺失值的行-R

时间:2016-03-27 15:52:11

标签: r

我有一个缺少值的数据框(df):

DF:

head1   head2   head3
-----   -----   -----
34      32      6
NA      NA      NA
45      NA      11
54      15      98
45      56      NA
3       1       78
NA      5       NA

我想返回这样一个列(head4)

head1   head2   head3  head4
-----   -----   -----  -----
34      32      6      0
NA      NA      NA     1
45      NA      11     0
54      15      98     0
45      56      NA     0
3       1       78     0
NA      5       NA     0

即,如果行的所有元素都是一个缺失值(NA),那么相关的行将返回1,否则为0.我如何使用R?我会很高兴得到任何帮助。非常感谢。

3 个答案:

答案 0 :(得分:4)

你可以尝试

df$head4 <- +(rowSums(is.na(df))==ncol(df))
#  head1 head2 head3 head4
#1    34    32     6     0
#2    NA    NA    NA     1
#3    45    NA    11     0
#4    54    15    98     0
#5    45    56    NA     0
#6     3     1    78     0
#7    NA     5    NA     0

在这种情况下,rowSums()计算每行中的NA值。如果该行中的所有条目均为NA,则此总和等于data.frame的总列数,并且与==ncol(df)的比较将返回TRUE。否则结果为FALSE。通过在前面添加+符号,可以将布尔向量强制转换为数值(0/1),在这种情况下,这是as.numeric()的简写符号。

希望这有帮助。

由于@RichardTelford就不同答案的速度发表了评论,我试图根据其中一个答案的速度来判断他的声明是否是这个答案的两倍。

m <- matrix(runif(1e6),ncol=4)
nas <- sample(1e6,0.3*1.e6)
m[nas] <- NA
df <- as.data.frame(m)
library(microbenchmark)
frowsums <- function(x) {+(rowSums(is.na(x))==ncol(x))}
flapply <- function(x) {Reduce(`&`, lapply(x, is.na)) + 0L}
frowmeans <- function(x) {1*(rowMeans(is.na(x)) == 1)}
res <- microbenchmark(
  frowsums(df),
  flapply(df),
  frowmeans(df), times=1000L)
res  
Unit: milliseconds

          expr      min       lq     mean   median       uq      max neval cld
  frowsums(df) 15.75257 16.63475 20.23377 17.14405 17.82396 80.63485  1000   b
   flapply(df) 15.16721 15.23180 18.19778 16.13413 16.60948 88.92303  1000  a 
 frowmeans(df) 16.61643 17.56909 20.69433 18.03498 18.83867 81.54057  1000   b

结果显示,@ RichardTelford的说法不正确。三种解决方案之间的速度几乎没有任何差异,这意味着从程序员的角度来看,最简单的版本和更容易理解的版本应该是优选的。

答案 1 :(得分:4)

我建议Reduce&amp; lapply组合可避免矩阵转换并立即将整个对象复制到内存中。

Reduce(`&`, lapply(df, is.na)) + 0L
# [1] 0 1 0 0 0 0 0

答案 2 :(得分:3)

您可以使用is.na()找到NA,然后在rowMeans()的帮助下测试行中的所有元素是否为1

df$head4 <- 1*(rowMeans(is.na(df)) == 1)

乘以1会将逻辑向量强制转换为数字向量(您可能不需要这样做)