What is the fastest way to detect if a vector has at least 1 NA
in R? I've been using:
sum( is.na( data ) ) > 0
But that requires examining each element, coercion, and the sum function.
As of R 3.1.0 anyNA()
is the way to do this. On atomic vectors this will stop after the first NA instead of going through the entire vector as would be the case with any(is.na())
. Additionally, this avoids creating an intermediate logical vector with is.na
that is immediately discarded. Borrowing Joran's example:
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
Beachten Sie, dass es wesentlich schneller ist, selbst wenn wir den letzten Wert des Vektors ändern. Dies ist teilweise auf die Vermeidung des logischen Zwischenvektors zurückzuführen.
any()
aufhöre, nachdem es eine FALSCHE gefunden hat. In jedem Fall ist der Moment, inany(...)
dem die Verarbeitung zu langsam wird, wahrscheinlich vorbei an dem Moment, in dem Ihr RAM leer ist.all()
Funktion, die übrigens wie erwartet funktioniert. Könnte nützlich sein (nicht für dieses Problem, aber im Allgemeinen).any
und hörenall
Sie auf zu iterieren, wenn sie aTRUE
bzw. aFALSE
erreichen; siehecheckValues
in svn.r-project.org/R/trunk/src/main/logic.c ; dasis.na
zwingt aber immer noch alles.is.na(data)
which gets computed first, and for all elements of data irrespective of whether an early one is in fact NA. We do improve on that with the Rcpp sugar version ofis.na()
(which is implemented in C++ for use via Rcpp). See my answer for more.We mention this in some of our Rcpp presentations and actually have some benchmarks which show a pretty large gain from embedded C++ with Rcpp over the R solution because
a vectorised R solution still computes every single element of the vector expression
Wenn es Ihr Ziel ist, nur zu befriedigen
any()
, können Sie nach dem ersten Match abbrechen - genau das bewirkt unsere Rcpp-Zuckerlösung (im Wesentlichen: etwas C ++ - Vorlagenmagie, damit C ++ - Ausdrücke eher wie R-Ausdrücke aussehen, siehe diese Vignette für mehr) .Wenn wir also eine kompilierte, spezialisierte Lösung zum Laufen bringen, erhalten wir tatsächlich eine schnelle Lösung. Ich sollte hinzufügen, dass ich dies zwar nicht mit den in dieser SO-Frage hier angebotenen Lösungen verglichen habe, aber hinsichtlich der Leistung einigermaßen zuversichtlich bin.
Edit And the Rcpp package contains examples in the directory
sugarPerformance
. It has an increase of the several thousand of the 'sugar-can-abort-soon' over 'R-computes-full-vector-expression' forany()
, but I should add that that case does not involveis.na()
but a simple boolean expression.quelle
any
computes every single element, rather than stopping at the first instance?any
doesn't know what's inside it; it just evaluates whatever its argument is (all of it) and then appliesany
to it, which does stop at the firstFALSE
, but again, only after evaluating all of its argument. Dirk's Rcpp sugar version ofany
(as I understand it) does know how to evaluate what's inside of it term by term (at least for some expressions, anyway) so it can check each term for TRUE/FALSE as it's evaluated in turn.Man könnte eine for-Schleife schreiben, die bei NA stoppt, aber die Systemzeit hängt dann davon ab, wo sich die NA befindet ... (wenn es keine gibt, dauert es ziemlich lange)
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
quelle
Hier sind einige aktuelle Zeiten von meiner (langsamen) Maschine für einige der verschiedenen Methoden, die bisher besprochen wurden:
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
Es ist nicht überraschend, dass
match
und%in%
sind ähnlich, da%in%
mit implementiert wirdmatch
.quelle
Du kannst es versuchen:
d <- c(1,2,3,NA,5,3) which(is.na(d) == TRUE, arr.ind=TRUE)
quelle