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)