Интересно, что самый быстрый способ определить, имеет ли вектор хотя бы 1 NA? Я использую:
sum (is.na(данные)) > 0
Но это требует изучения каждого элемента, принуждения и функции суммы.
R - самый быстрый способ определить, имеет ли вектор по крайней мере 1 NA?
Ответ 1
В новых версиях R есть anyNA()
в качестве опции. На атомных векторах это остановится после первого NA вместо того, чтобы проходить через весь вектор, как в случае с t21. Заимствование примера Джорана:
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
Я думаю:
any(is.na(data))
должен быть немного быстрее.
Ответ 3
Мы упомянем об этом в некоторых из наших Rcpp презентаций и фактически имеем некоторые ориентиры, которые показывают довольно большой выигрыш от встроенного С++ с Rcpp over решение R, потому что
-
векторное решение R все еще вычисляет каждый отдельный элемент векторного выражения
-
если ваша цель состоит в том, чтобы просто удовлетворить
any()
, то вы можете прервать после первого совпадения - это то, что наш сахар Rcpp (по существу: некоторые магии шаблонов С++ для выражения С++ больше похожи на выражения R, см. эту виньетку для большего).
Таким образом, получая скомпилированное специализированное решение для работы, мы действительно получаем быстрое решение. Я должен добавить, что, хотя я не сравнивал это с решениями, предлагаемыми в этом SO-вопросе здесь, я достаточно уверен в производительности.
Изменить И пакет Rcpp содержит примеры в каталоге sugarPerformance
. У этого есть увеличение нескольких тысяч "сахара-can-abort-soon" над "R-computes-full-vector-expression" для any()
, но я должен добавить, что этот случай не включает is.na()
, но простое булево выражение.
Ответ 4
Можно написать остановку цикла для NA, но время 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
Ответ 5
Вот несколько фактических времен от моей (медленной) машины для некоторых из обсуждаемых до сих пор методов:
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
.
Ответ 6
Вы можете попробовать:
d <- c(1,2,3,NA,5,3)
which(is.na(d) == TRUE, arr.ind=TRUE)