检测向量在R中是否至少有NA
的最快方法是什么?我一直在用:
sum( is.na( data ) ) > 0
但这需要检查每个元素,强制和和函数。
答案 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)