Самый быстрый способ определить, имеет ли вектор хотя бы 1 NA?
каков самый быстрый способ определить, имеет ли вектор хотя бы 1 NA
в R? Я использую:
sum( is.na( data ) ) > 0
но это требует изучения каждого элемента, принуждения и функцию сумм.
6 ответов:
начиная с 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
обратите внимание, как это существенно быстрее, даже когда мы изменяем последнее значение вектора; это отчасти из-за избежания промежуточный логический вектор.
мы упоминаем об этом в некоторых из наших Rcpp презентации и на самом деле есть некоторые критерии, которые показывают довольно большие выгоды из встроенного C++ с Rcpp над решением R, потому что
векторизованное решение R все еще вычисляет каждый элемент векторного выражения
если ваша цель состоит в том, чтобы просто удовлетворить
any()
, то вы можете прервать после первого матча - что и наш Rcpp сахара (в сущности: некоторые c++ шаблон магии, чтобы сделать c++ выражения больше похожи на R выражения, см. эта виньетка дополнительные) решение.таким образом, получая скомпилированное специализированное решение для работы, мы действительно получаем быстрое решение. Я должен добавить, что, хотя я не сравнивал это с решениями, предлагаемыми в этом вопросе SO здесь, я достаточно уверен в производительности.
Edit и Пакет Rcpp содержит примеры в каталоге
sugarPerformance
. Он имеет увеличение на несколько тысяч "сахар-может-прервать-скоро" над "R-вычисляет-полное векторное выражение" дляany()
, но я должен добавить, что этот случай не предполагаетis.na()
но простое логическое выражение.
можно было бы написать цикл for, останавливающийся на 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
.