Rcpp 中的 na.locf 和 inverse.rle [英] na.locf and inverse.rle in Rcpp

查看:34
本文介绍了Rcpp 中的 na.locf 和 inverse.rle的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想检查 na.locf(来自 zoo 包)、rle 是否有任何预先存在的技巧RCpp?

I wanted to check if there is any pre-existing trick for na.locf (from zoo package), rle and inverse.rle in RCpp?

我写了一个循环来实现,例如我做了na.locf(x, na.rm=FALSE, fromLast=FALSE)的实现如下:

I wrote a loop to implement, e.g. I did the implementation of na.locf(x, na.rm=FALSE, fromLast=FALSE) as follows:

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

我只是想知道,由于这些是非常基本的功能,有人可能已经在 RCpp 中以更好的方式(可能是避免循环)或更快的方式实现了它们?

I was just wondering that since these are quite basic functions, someone might have already implemented them in RCpp in a better way (may be avoid the loop) OR a faster way?

推荐答案

我唯一要说的是,当您只需要执行一次时,您要为每个值对 NA 进行两次测试.NA 的测试不是免费的操作.也许是这样的:

The only thing I'd say is that you are testing for NA twice for each value when you only need to do it once. Testing for NA is not a free operation. Perhaps something like this:

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

然而,这仍然会做一些不必要的事情,比如每次我们只能在最后一次看不到 NA 时设置 v.我们可以尝试这样的事情:

This still however does unnecessary things, like setting v every time when we could only do it for the last time we don't see NA. We can try something like this:

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

现在,我们可以尝试一些基准测试:

Now, we can try some 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

这篇关于Rcpp 中的 na.locf 和 inverse.rle的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆