Самый быстрый способ определить, имеет ли вектор хотя бы 1 NA? - PullRequest
64 голосов
/ 01 июля 2011

Какой самый быстрый способ обнаружить, если вектор имеет по крайней мере 1 NA в R?Я использовал:

sum( is.na( data ) ) > 0

Но для этого нужно изучить каждый элемент, принуждение и функцию суммы.

Ответы [ 6 ]

68 голосов
/ 01 июля 2011

Я думаю:

any(is.na(data))

должно быть немного быстрее.

51 голосов
/ 01 марта 2016

Начиная с 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

Обратите внимание, что это существенно быстрее, даже если мы изменим последнее значение вектора;это частично из-за избежания промежуточного логического вектора.

16 голосов
/ 02 июля 2011

Мы упоминаем об этом в некоторых наших Rcpp презентациях и на самом деле есть некоторые тесты, которые показывают довольно большой выигрыш от встроенного C ++ с Rcpp над решением R, потому что

  • векторизованное решение R по-прежнему вычисляет каждый элемент векторного выражения

  • если ваша цель состоит в том, чтобы просто удовлетворить any(), то вы можете прервать выполнение после первого совпадения - это то, что наш Rcpp sugar (по сути: некоторая магия шаблона C ++ для создания C ++ выражения больше похожи на выражения R, см. эту виньетку ) решение делает.

Так что, заставляя работать скомпилированное специализированное решение, мы действительно получаем быстрое решение. Я должен добавить, что хотя я не сравнивал это с решениями, предлагаемыми здесь в этом вопросе, я достаточно уверен в производительности.

Редактировать И пакет Rcpp содержит примеры в каталоге sugarPerformance. Он имеет увеличение на несколько тысяч 'сахар-может-прервать-скоро' по сравнению с 'R-computes-full-vector-expression' для any(), но я должен добавить, что этот случай не включает is.na(), но простое логическое выражение.

8 голосов
/ 01 июля 2011

Можно написать остановку цикла for в NA, но тогда system.time зависит от того, где находится NA ... (если его нет, это занимает слишком много времени)

6 голосов
/ 01 июля 2011

Вот некоторые фактические времена из моей (медленной) машины для некоторых из различных методов, обсуждавшихся до сих пор:

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.

3 голосов
/ 01 июля 2011

Вы можете попробовать:

d <- c(1,2,3,NA,5,3)

which(is.na(d) == TRUE, arr.ind=TRUE)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...