r - 在 R 中编写一个滚动 sd 函数并在 C++ 中实现

我必须为 C++ 编写实现 R 函数。例如,我正在尝试计算滚动 SD,但下面的代码不起作用。任何帮助将不胜感激。 #下面的代码工作正常

library(roll)

n <- 150
x <- rnorm(n)
x
weights <- 0.9 ^ (n:1)
weights
roll_sd(x, width = 5)

#但是当我通过 CPPFunction 传递它时它不起作用

cppFunction("roll_sd(x, width = 5)")

回答1

这不是 cppFunction 的工作方式。您不能简单地将 R 调用传递给它并期望它神奇地转换为 C++。

事实上,它更像是反过来。您用 C++ 编写函数,cppFunction 使该函数在 R 中可用。

roll_sd 匹配的滚动标准差的粗略实现如下所示:

cppFunction("NumericVector rolling_sd(NumericVector x, int width) {
   NumericVector y = clone(x);
   for(int i = 0; i < (int)x.size(); i++) {
     if(i < (width - 1)) {
       y[i] = NA_REAL;
     } else {
        double sum = 0.0;
        double total = 0.0;
        for(int j = i - (width - 1); j <= i; j++) {
          sum += x[j];
        }
        
        double mean = sum / width;
        
        for(int j = i - (width - 1); j <= i; j++) {
          total += pow(x[j] - mean, 2);
        }
        y[i] = sqrt(total / (width - 1));
      }
   }
   return y;
}")

运行这段代码后,函数 rolling_sd 现在在 R 中可供我们使用,并给出与 roll_sd 相同的结果:

set.seed(1)

x <- rnorm(10)

roll::roll_sd(x, width = 5)
#> [1]        NA        NA        NA        NA 0.9610394 1.0022155 1.0183545
#> [8] 0.8694145 0.6229882 0.6688342

rolling_sd(x, width = 5)
#> [1]        NA        NA        NA        NA 0.9610394 1.0022155 1.0183545
#> [8] 0.8694145 0.6229882 0.6688342

但是,我们的 C++ 版本要快 10 倍以上,如下面的基准测试所示。

microbenchmark::microbenchmark(roll_sd(x, width = 5), rolling_sd(x, width = 5))
#> Unit: microseconds
#>                      expr  min   lq   mean median   uq   max neval cld
#>     roll_sd(x, width = 5) 38.7 41.4 44.310   42.2 44.3 154.5   100   b
#>  rolling_sd(x, width = 5)  2.1  2.6  3.346    3.3  3.7  15.0   100  a

相似文章

随机推荐

最新文章