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.
Antworten:
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.
Ich denke:
any(is.na(data))
sollte etwas schneller sein.
any()
aufhöre, nachdem es eine FALSCHE gefunden hat. In jedem Fall ist der Moment, in any(...)
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ören all
Sie auf zu iterieren, wenn sie a TRUE
bzw. a FALSE
erreichen; siehe checkValues
in svn.r-project.org/R/trunk/src/main/logic.c ; das is.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 of is.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' for any()
, but I should add that that case does not involve is.na()
but a simple boolean expression.
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 applies any
to it, which does stop at the first FALSE
, but again, only after evaluating all of its argument. Dirk's Rcpp sugar version of any
(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
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 wird match
.
Du kannst es versuchen:
d <- c(1,2,3,NA,5,3)
which(is.na(d) == TRUE, arr.ind=TRUE)