移動平均は stats::filter で行える。 これを,inline で書いて見ようというのが今回のお題。
NA は NA_REAL を使う(IntegerVector なら,NA_INTEGER。他に,Inf, -Inf は R_PosInf, R_NegInf。)
ポインターは double *pz; ... pz = REAL(z); のように使う。(ので,いいのかな?)
かなりいい加減に書いたプログラムだけど,filter より 6 倍ほど速い。もっとも,要素数が 1000000 と大きいのに,実行時間が 0.15 秒というのだから,ほとんど意味がない。
src <- '
Rcpp::NumericVector x(X);
int n = x.length();
Rcpp::NumericVector z(n, NA_REAL);
double *pz;
int m = as<int>(M);
int i, j;
pz = REAL(z)+m/2;
for (i = 0; i <= n-m; i++) {
double ans = 0;
for (j = 0; j < m; j++) {
ans += x[i+j];
}
*pz++ = ans/m;
}
return wrap(z);
'
moving.average <- cxxfunction(signature(X="numeric", M="integer"), src, plugin="Rcpp")
実行例
> set.seed(777)
> x <- rnorm(1000000)
> system.time(a <- filter(x, rep(1/7, 7)))
ユーザ システム 経過
0.150 0.011 0.159
> system.time(b <- moving.average(x, 7))
ユーザ システム 経過
0.026 0.000 0.027
> all.equal(as.vector(a), b)
[1] TRUE