Pregunta

Quería comprobar si existe algún truco preexistente para na.locf (de zoo paquete), rle y inverse.rle en RCpp?

Escribí un bucle para implementar, p.e.Hice la implementación de na.locf(x, na.rm=FALSE, fromLast=FALSE) como sigue:

#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;
}

Me preguntaba si, dado que se trata de funciones bastante básicas, es posible que alguien ya las haya implementado en RCpp ¿De una manera mejor (puede evitar el bucle) O de una manera más rápida?

¿Fue útil?

Solución

Lo único que diría es que estás probando NA dos veces para cada valor cuando solo necesitas hacerlo una vez.Pruebas para NA No es una operación gratuita.Quizás algo como esto:

//[[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;
}

Sin embargo, esto todavía hace cosas innecesarias, como configurar v cada vez que solo pudimos hacerlo por última vez no vemos NA.Podemos probar algo como esto:

//[[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;
}

Ahora, podemos probar algunos puntos de referencia:

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
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top