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

想知道最快的方法是检测一个向量是否至less有1个NA? 我一直在使用:
sum(is.na(data))> 0
但是这需要检查每个元素,强制和总和函数。

R的更新版本有anyNA()作为选项。 在primefaces向量上,这将在第一个NA之后停止,而不是像any(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 

请注意,即使修改vector的最后一个值,它的速度也会显着提高。 除了提早停止之外,储蓄的很大一部分是我们不需要为整个逻辑向量创build和分配内存,这个向量就是我们的数字向量的大小。

我在想:

 any(is.na(data)) 

应该稍微快一点。

我们在一些Rcpp演示中提到了这一点,并且实际上有一些基准testing,它们显示了embedded式C ++与Rcpp在R解决scheme上的巨大收益 ,因为

  • vector化R解决scheme仍然计算vectorexpression式的每个单个元素

  • 如果你的目标是满足any() ,那么你可以在第一次匹配之后中止 – 这就是我们的Rcpp糖 (实质上是一些C ++模板的魔法,使得C ++expression式看起来更像Rexpression式, )解决scheme呢。

所以通过编译专门的解决scheme,我们确实得到了一个快速的解决scheme。 我还要补充一点,虽然我没有把这个与这个SO问题中提供的解决scheme进行比较,但是我对这个性能相当有信心。

编辑并且Rcpp包在目录sugarPerformance包含示例。 对于any() ,它都增加了数千个“糖可以中止”的“R计算 – 完全向量expression式”,但是我应该补充说,这种情况不涉及is.na()而是一个简单的布尔expression式。

我们可以写一个for循环停在NA上,但是系统时间取决于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 

下面是从我的(慢)机器到目前为止讨论的各种方法的一些实际时间:

 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实现的。

你可以试试:

 d <- c(1,2,3,NA,5,3) which(is.na(d) == TRUE, arr.ind=TRUE)