Frage
Ich wollte überprüfen, ob es eine bereits bestehende trick für na.locf
(aus zoo
- Paket), rle
und inverse.rle
in RCpp
?
Ich schrieb eine Schleife zu implementieren, z.B.Ich habe die Implementierung von na.locf(x, na.rm=FALSE, fromLast=FALSE)
wie folgt:
#include <Rcpp.h>
using namespace Rcpp;
//[[Rcpp::export]]
NumericVector naLocf(NumericVector x) {
int n=x.size();
for (int i=1;i<n;i++) {
if (R_IsNA(x[i]) & !R_IsNA(x[i-1])) {
x[i]=x[i-1];
}
}
return x;
}
Ich Frage mich nur, dass da diese sehr grundlegenden Funktionen, die jemand haben könnte, bereits umgesetzt in RCpp
in einer besseren Art und Weise (kann vermeiden die Schleife), ODER einen schnelleren Weg?
Lösung
Das einzige, was ich sagen würde ist, dass Sie Tests für NA
zweimal für jeden Wert, wenn Sie brauchen nur zu tun es einmal.Prüfung für NA
ist nicht eine Kostenlose operation.Vielleicht so etwas wie dieses:
//[[Rcpp::export]]
NumericVector naLocf(NumericVector x) {
int n = x.size() ;
double v = x[0]
for( int i=1; i<n; i++){
if( NumericVector::is_na(x[i]) ) {
x[i] = v ;
} else {
v = x[i] ;
}
}
return x;
}
Dies jedoch immer noch nicht unnötige Dinge, wie die Einstellung v
jedes mal, wenn wir es nur tun, für die Letzte Zeit, die wir nicht sehen NA
.Wir können versuchen, so etwas wie dieses:
//[[Rcpp::export]]
NumericVector naLocf3(NumericVector x) {
double *p=x.begin(), *end = x.end() ;
double v = *p ; p++ ;
while( p < end ){
while( p<end && !NumericVector::is_na(*p) ) p++ ;
v = *(p-1) ;
while( p<end && NumericVector::is_na(*p) ) {
*p = v ;
p++ ;
}
}
return x;
}
Nun, wir können versuchen, einige benchmarks:
x <- rnorm(1e6)
x[sample(1:1e6, 1000)] <- NA
require(microbenchmark)
microbenchmark( naLocf1(x), naLocf2(x), naLocf3(x) )
# Unit: milliseconds
# expr min lq median uq max neval
# naLocf1(x) 6.296135 6.323142 6.339132 6.354798 6.749864 100
# naLocf2(x) 4.097829 4.123418 4.139589 4.151527 4.266292 100
# naLocf3(x) 3.467858 3.486582 3.507802 3.521673 3.569041 100