web-dev-qa-db-fra.com

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'utilise:

sum( is.na( data ) ) > 0

Mais cela nécessite d'examiner chaque élément, la contrainte et la fonction de somme.

65
SFun28

Depuis R 3.1.0 anyNA() est le moyen de le faire. Sur les vecteurs atomiques, cela s'arrêtera après la première NA au lieu de parcourir tout le vecteur 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 rejeté. 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.

54
BrodieG

Je pense:

any(is.na(data))

devrait être légèrement plus rapide.

68
Sacha Epskamp

On pourrait écrire une boucle for s'arrêtant à NA, mais le system.time dépend alors de l'endroit où se trouve le NA ... (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 verstrichen 
       0.45        0.07        0.53 
8
EDi

Voici quelques temps réels de ma machine (lente) pour certaines des différentes méthodes discutées jusqu'à présent:

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% sont similaires, puisque %in% est implémenté à l'aide de match.

6
joran

Tu peux essayer:

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

which(is.na(d) == TRUE, arr.ind=TRUE)
3
Manuel Ramón