检测向量是否至少有1个NA的最快方法?

时间:2011-07-01 18:26:41

标签: r na

检测向量在R中是否至少有NA的最快方法是什么?我一直在用:

sum( is.na( data ) ) > 0

但这需要检查每个元素,强制和和函数。

6 个答案:

答案 0 :(得分:67)

我在想:

any(is.na(data))

应该稍快一些。

答案 1 :(得分:50)

从R 3.1.0开始anyNA()就是这样做的方法。在原子向量上,这将在第一个NA之后停止,而不是像any(is.na())那样通过整个向量。此外,这可以避免创建一个立即丢弃is.na的中间逻辑向量。借用乔兰的例子:

x <- y <- runif(1e7)
x[1e4] <- NA
y[1e7] <- NA
microbenchmark::microbenchmark(any(is.na(x)), anyNA(x), any(is.na(y)), anyNA(y), times=10)
# Unit: microseconds
#           expr        min         lq        mean      median         uq
#  any(is.na(x))  13444.674  13509.454  21191.9025  13639.3065  13917.592
#       anyNA(x)      6.840     13.187     13.5283     14.1705     14.774
#  any(is.na(y)) 165030.942 168258.159 178954.6499 169966.1440 197591.168
#       anyNA(y)   7193.784   7285.107   7694.1785   7497.9265   7865.064

注意即使我们修改向量的最后一个值,它也会大大加快;这部分是因为避免了中间逻辑向量。

答案 2 :(得分:16)

我们在一些Rcpp演示文稿中提到了这一点,并且实际上有一些基准测试显示嵌入式C ++中Rcpp超过R解决方案的非常大增益,因为

  • 矢量化R解决方案仍计算矢量表达式的每个元素

  • 如果您的目标只是满足any(),那么您可以在第一场比赛后中止 - 这就是我们的 Rcpp糖(实质上是一些C ++模板魔术要使C ++表达式看起来更像R表达式,请参阅this vignette以获取更多信息)解决方案。

因此,通过使用已编译的专用解决方案,我们确实可以获得快速解决方案。我应该补充一点,虽然我没有将此与此SO问题中提供的解决方案进行比较,但我对性能有了相当的信心。

编辑并且Rcpp包中包含目录sugarPerformance中的示例。对any()的'R-computes-full-vector-expression'进行了几千次'即可中止'的增加,但我应该补充一点,那个案例不涉及{{} 1}}但是一个简单的布尔表达式。

答案 3 :(得分:8)

可以在NA处写一个for循环停止,但是system.time然后取决于NA的位置......(如果没有,则需要looooong)

set.seed(1234)
x <- sample(c(1:5, NA), 100000000, replace = TRUE)

nacount <- function(x){
  for(i in 1:length(x)){
    if(is.na(x[i])) {
      print(TRUE)
      break}
}}

system.time(
  nacount(x)
)
[1] TRUE
       User      System verstrichen 
       0.14        0.04        0.18 

system.time(
  any(is.na(x))
) 
       User      System verstrichen 
       0.28        0.08        0.37 

system.time(
  sum(is.na(x)) > 0
)
       User      System verstrichen 
       0.45        0.07        0.53 

答案 4 :(得分:6)

以下是我(慢)机器的一些实际时间,用于讨论到目前为止所讨论的各种方法:

x <- runif(1e7)
x[1e4] <- NA

system.time(sum(is.na(x)) > 0)
> system.time(sum(is.na(x)) > 0)
   user  system elapsed 
  0.065   0.001   0.065 

system.time(any(is.na(x)))  
> system.time(any(is.na(x)))
   user  system elapsed 
  0.035   0.000   0.034

system.time(match(NA,x)) 
> system.time(match(NA,x))
  user  system elapsed 
 1.824   0.112   1.918

system.time(NA %in% x) 
> system.time(NA %in% x)
  user  system elapsed 
 1.828   0.115   1.925 

system.time(which(is.na(x) == TRUE))
> system.time(which(is.na(x) == TRUE))
  user  system elapsed 
 0.099   0.029   0.127

match%in%相似并不奇怪,因为%in%是使用match实现的。

答案 5 :(得分:3)

您可以尝试:

d <- c(1,2,3,NA,5,3)

which(is.na(d) == TRUE, arr.ind=TRUE)