Подтвердить что ты не робот

R - самый быстрый способ определить, имеет ли вектор по крайней мере 1 NA?

Интересно, что самый быстрый способ определить, имеет ли вектор хотя бы 1 NA? Я использую:
sum (is.na(данные)) > 0
Но это требует изучения каждого элемента, принуждения и функции суммы.

4b9b3361

Ответ 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)