Le moyen le plus rapide de détecter si le vecteur a au moins 1 NA?

Quel est le moyen le plus rapide de détecter si un vecteur a au moins 1 NA dans R? J’ai utilisé:

 sum( is.na( data ) ) > 0 

Mais cela nécessite d’examiner chaque élément, la coercition et la fonction de sum.

À partir de R 3.1.0, anyNA() est la manière de procéder. Sur les vecteurs atomiques, cela s’arrêtera après le premier NA au lieu de parcourir le vecteur entier comme ce serait le cas avec any(is.na()) . De plus, cela évite de créer un vecteur logique intermédiaire avec is.na qui est immédiatement ignoré. Emprunter l’exemple de Joran:

 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 

Remarquez comment il est sensiblement plus rapide même lorsque nous modifions la dernière valeur du vecteur; ceci est en partie dû à l’évitement du vecteur logique intermédiaire.

Je pense:

 any(is.na(data)) 

devrait être légèrement plus rapide.

Nous mentionnons cela dans certaines de nos présentations Rcpp et avons en fait quelques tests de performances qui montrent un gain considérable par rapport au C ++ intégré avec Rcpp sur la solution R car

  • une solution R vectorisée calcule toujours chaque élément de l’expression vectorielle

  • Si votre objective est de simplement satisfaire any() , alors vous pouvez abandonner après la première correspondance – ce qui est ce que notre sucre Rcpp (essentiellement: un modèle de C ++ magique pour que les expressions C ++ ressemblent plus à des expressions R, voir cette vignette pour plus ) solution fait.

Ainsi, en faisant fonctionner une solution spécialisée compilée, nous obtenons en effet une solution rapide. Je dois append que même si je n’ai pas comparé cela aux solutions proposées dans cette question SO, je suis raisonnablement confiant quant à la performance.

Edit Et le package Rcpp contient des exemples dans l’annuaire sugarPerformance . Il a une augmentation de plusieurs milliers de «sucre-can-abort-soon» sur «R-computes-full-vector-expression» pour any() , mais je dois append que ce cas n’implique pas is.na() mais une simple expression booléenne.

On pourrait écrire une boucle d’arrêt sur NA, mais le system.time dépend alors de l’endroit où se trouve l’AN (s’il n’y en a pas, cela prend 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 verssortingchen 0.45 0.07 0.53 

Voici quelques temps réels de ma machine (lente) pour certaines des différentes méthodes abordées jusqu’ici:

 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 

Il n’est pas surprenant que match et %in% soient similaires, puisque %in% est implémenté en utilisant match .

Tu peux essayer:

 d <- c(1,2,3,NA,5,3) which(is.na(d) == TRUE, arr.ind=TRUE)