关于Rcpp的问题

关于Rcpp的问题,r,rcpp,R,Rcpp,我用R写了下面的计算。 然而,这在许多“for循环”中使用缓慢 我尝试使用Rcpp编写类似的计算。 但这是一个错误 请更正我的密码 # R data <- matrix(1: 100, ncol = 5, nrow = 20) Y <- 10 X <- Y - 1 Z <- matrix(ncol = 1, nrow = nrow(data) - X) for (i in 1:(nrow(data) - X)){ Z[i, ] <- sum(data[i:

我用R写了下面的计算。 然而,这在许多“for循环”中使用缓慢

我尝试使用Rcpp编写类似的计算。 但这是一个错误

请更正我的密码

# R
data <- matrix(1: 100, ncol = 5, nrow = 20)

Y <- 10
X <- Y - 1
Z <- matrix(ncol = 1, nrow = nrow(data) - X) 

for (i in 1:(nrow(data) - X)){
  Z[i, ] <- sum(data[i: (i + X), ])
} 
> data
      [,1] [,2] [,3] [,4] [,5]
 [1,]    1   21   41   61   81
 [2,]    2   22   42   62   82
 [3,]    3   23   43   63   83
 [4,]    4   24   44   64   84
 [5,]    5   25   45   65   85
 [6,]    6   26   46   66   86
 [7,]    7   27   47   67   87
 [8,]    8   28   48   68   88
 [9,]    9   29   49   69   89
[10,]   10   30   50   70   90
[11,]   11   31   51   71   91
[12,]   12   32   52   72   92
[13,]   13   33   53   73   93
[14,]   14   34   54   74   94
[15,]   15   35   55   75   95
[16,]   16   36   56   76   96
[17,]   17   37   57   77   97
[18,]   18   38   58   78   98
[19,]   19   39   59   79   99
[20,]   20   40   60   80  100

> Z
       [,1]
 [1,] 2275
 [2,] 2325
 [3,] 2375
 [4,] 2425
 [5,] 2475
 [6,] 2525
 [7,] 2575
 [8,] 2625
 [9,] 2675
[10,] 2725
[11,] 2775



// Rcpp
#include <Rcpp.h> 
using namespace Rcpp;

// [[Rcpp::export]]
NumericMatrix myRcpp(NumericMatrix data, NumericVector Y) {
  int X = Y - 1;
  int i;
  int nrow = data.nrow();
  Rcpp::NumericMatrix Z();

  for (i = 0; i < nrow - X; i++) {
    Z[i] = Rcpp::sum(data( Range(i, (i + X)) , _ ));
  }  

  return (Z);
}
#R

数据您有几个错误。大多数情况下,我建议解开复杂的表达式,这些表达式显然会产生编译器/模板错误

使用新代码,我得到:

R> sourceCpp("/tmp/so_question.cpp")

R> # R
R> data <- matrix(1: 100, ncol = 5, nrow = 20)

R> Y <- 10

R> X <- Y - 1

R> Z <- matrix(ncol = 1, nrow = nrow(data) - X) 

R> for (i in 1:(nrow(data) - X)) {
+   Z[i, ] <- sum(data[i: (i + X), ])
+ } 

R> #data
R> #Z
R> 
R> myRcpp(data, Y)
 [1] 2275 2325 2375 2425 2475 2525 2575 2625 2675 2725 2775
R> 
R>sourceCpp(“/tmp/so\u question.cpp”)
R> #R
R> 数据Y X Z(i在1中:(nrow(数据)-X)){
+Z[i,]#数据
R> #Z
R>
R> myRcpp(数据,Y)
[1] 2275 2325 2375 2425 2475 2525 2575 2625 2675 2725 2775
R>

代码在下面——我把R和C++结合成一个文件。

#include <Rcpp.h> 
using namespace Rcpp;

// [[Rcpp::export]]
NumericVector myRcpp(NumericMatrix data, int y) {
  int x = y - 1;
  int i;
  int n = data.nrow();
  Rcpp::NumericVector z(n - x);

  for (i = 0; i < n - x; i++) {
    Rcpp::SubMatrix<REALSXP> sm = data( Range(i, (i + x)) , _ );
    Rcpp::NumericMatrix m(sm);
    double s = Rcpp::sum(m);
    z[i] = s;
  }  

  return z;
}


/*** R
# R
data <- matrix(1: 100, ncol = 5, nrow = 20)

Y <- 10
X <- Y - 1
Z <- matrix(ncol = 1, nrow = nrow(data) - X) 

for (i in 1:(nrow(data) - X)) {
  Z[i, ] <- sum(data[i: (i + X), ])
} 

#data
#Z

myRcpp(data, Y)
*/
#包括
使用名称空间Rcpp;
//[[Rcpp::导出]]
数值向量myRcpp(数值矩阵数据,整数y){
int x=y-1;
int i;
int n=data.nrow();
Rcpp::数值向量z(n-x);
对于(i=0;i数据在我看来,你和答案对每一行重复相同的计算(行和)Y次。所以一个向量化的解决方案

data %>%
  rowSums %>%
  cumsum %>%
  {. - lag(., Y)}
((>%来自包magrittr,来自dplyr的lag方法)应该做您想要做的事情,它甚至比Rcpp快一点

Unit: milliseconds
             expr       min        lq      mean    median        uq       max neval cld
  myArma(data, Y) 10.363077 11.633387 17.963248 12.233787 14.772540 131.67896   100   b
 vectorized(data)  3.172276  3.284239  5.492879  3.441609  4.664644  63.96084   100  a 
您提到,您最终希望使用sd而不是sum,但即使在这种情况下,缓存平方和也会节省大量时间

data %>%
  {(. - mu)^2} %>%
  rowSums %>%
  cumsum %>%
  {. - lag(.,Y)} %>%
  divide_by( Y*NCOL(data) - 1 )
mu作为一个组意味着你得到了另一个解决方案

一个C++实现,当然,它比R还要快,但我认为你不能为了简洁而超越上面的代码。 再见, 斯特凡

编辑:根据数据的结构和大小,您可能会遇到从累积和减去滞后累积和的减法取消问题(即,如果累积和比没有有效数字的单行和大16个数量级)。在这种情况下,您可以使用RcppRoll的roll_sum替换该步骤

作为一个解决方案,它实际上更短,我只是没有RcppRoll的经验,也不能说是否存在问题或陷阱

data %>%
  rowSums %>%
  roll_sum(Y)

你能详细说明你看到的错误吗?我已经附加了一条错误消息。谢谢。谢谢。在我显示的代码中,使用“sum”可以在RcppRoll中解决。但是,我有时想使用“sd”而不是“sum”。RcppRoll似乎无法应用“sd”在多个列中。如果zoo中的
rollapply
足够,则它可以根据
by.column=
参数按列或跨列应用函数。另外,请随意“向上投票”(单击向上箭头)问题,并且,作为提问者,也可以“接受”(单击勾号)。这就是StackOverflow的工作原理。但是,这需要将数据复制到
m
。如果
sum
知道如何处理矩阵糖表达式,那就更好了。当然,但运行时的成本很小。更紧凑的表达式有帮助,请查看更新后的答案及其Armadillo一行解决方案。这太好了,不可能是真的性能方面的ld get可能是
rowsum(roll\u sum(data,Y))
其中
roll\u sum
来自
RcppRoll
。你的
向量化的
解决方案是计算一个完全不同的东西。诚然,
滞后(,Y,默认值=0)
是必需的,但是
all.equal(向量化的(data),myArma(data,Y))
返回
TRUE
。你从哪里知道我们计算不同的东西?抱歉。我在没有加载dplyr的情况下运行了你的代码。很好的解决方案。我发现性能取决于
求和
的效率。然而,并不是所有的滚动操作都是
求和
,因此它的泛化能力有限。我怀疑你的
sde> 示例工作。谢谢。您的解决方案也很有帮助。
Unit: milliseconds
             expr       min        lq      mean    median        uq       max neval cld
  myArma(data, Y) 10.363077 11.633387 17.963248 12.233787 14.772540 131.67896   100   b
 vectorized(data)  3.172276  3.284239  5.492879  3.441609  4.664644  63.96084   100  a 
data %>%
  {(. - mu)^2} %>%
  rowSums %>%
  cumsum %>%
  {. - lag(.,Y)} %>%
  divide_by( Y*NCOL(data) - 1 )
data %>%
  rowSums %>%
  roll_sum(Y)