Rcpp Armadilllo 中的模板类 arma::Col

Posted

技术标签:

【中文标题】Rcpp Armadilllo 中的模板类 arma::Col【英文标题】:Template classes arma::Col in Rcpp Armadilllo 【发布时间】:2020-12-24 02:08:21 【问题描述】:

亲爱的程序员们,

为了为大学研讨会编写自举回归版本,我尝试将我的 R 版本实现为 Rcpp(这是为了比较 R 与 C++/Rcpp)。但是,我对收到的错误消息感到困惑,因为我并不真正理解那些(刚接触 C++ 尤其是犰狳的挣扎)。

这是我正在使用的代码。第一个函数是我从互联网上复制来获取矩阵的适当行子集的函数(以实现适当的非参数引导程序):

    #include <RcppArmadillo.h>
// [[Rcpp::depends(RcppArmadillo)]]
// [[Rcpp::export]]

arma::mat testrows(arma::mat x, arma::Col idx) 
  arma::mat xsub;
  xsub = x.rows(idx-1);
  return xsub;

此外,这是我为实际引导版本编写的代码:

   #include <RcppArmadillo.h>
// [[Rcpp::depends(RcppArmadillo)]]
// [[Rcpp::export]]
arma::mat betaBoot(arma::colvec& y, const arma::mat& X, const int nboot) 
    int n = X.n_rows, k = X.n_cols;
    arma::mat betaHat(k,nboot);
    for(int i = 0; i < nboot; i++)
        Rcpp::NumericVector colId = Rcpp::runif(n, 0, (n-1));
        arma::mat X_boot = testrows(X, colId);
        arma::colvec y_boot = y(colId);
        betaHat.col(i) = arma::solve(X_boot, y_boot);
    
    return betaHat;

betaHat 是一个包含自举系数向量(在每一列中)的矩阵,该矩阵的维度应为 k x nboot。 X_boot(在循环内)应该是自举数据,y_boot 应该是相应的相关观察。 colId 应该是引导过程的随机索引。最后,应该返回betaHat

附上我在使用 sourceCpp 时收到的错误图片。

也许这是我看不到的简单东西,或者也许是缺乏经验,但是学习这些东西会很棒。所以如果你能帮助我,那就太好了。 先感谢您 艾琳

编辑:我的自举回归函数现在看起来(和工作)的方式:

#include <RcppArmadillo.h>
// [[Rcpp::depends(RcppArmadillo)]]
// [[Rcpp::export]]
arma::mat betaBoot(arma::colvec& y, const arma::mat& X, const int nboot) 
    int n = X.n_rows, k = X.n_cols;
    arma::mat betaHat(k,nboot);
    for(int i = 0; i < nboot; i++)
        arma::uvec colId = arma::randi<arma::uvec>(n, arma::distr_param(0,n-1));
      
        arma::mat X_boot = X.rows(colId);
        arma::colvec y_boot = y(colId);
        betaHat.col(i) = arma::solve(X_boot, y_boot);
    
    return betaHat;

感谢我收到的所有有用的 cmets。

【问题讨论】:

快速查看testrows 为索引采用arma::Col,但您在betaBoot 中传递了Rcpp::NumericVector。您似乎还使用真实(随机统一)而不是整数索引进行子集(它们应该是 uvec 吗?) Rcpp 和 RcppArmadillo 都有示例函数 作为一般规则,我建议从最简单的工作构建块开始。在这里,您显然对testrows 有问题,所以我建议您在继续之前能够调用它来随机选择行。 Re: Dirk 建议以testrows() 开头,我认为您应该能够通过not 使用arma::Col 来解决这个问题。如果您查看 excellent Armadillo 文档here,您会发现该规范需要arma::Col&lt;double&gt; 之类的东西;你可能想要arma::vec(相当于arma::Col&lt;double&gt; 非常感谢大家。事实上,我发现我根本不需要我的(被盗的)辅助函数 testrows,但是我也误解了 .rows 的工作方式(我认为它的工作方式类似于 R 中的 A[n:p,],而不是 A[c(. ..),])。现在,我直接实现了建议的采样和 .rows 函数。如果你写一个答案,我肯定会接受。再次感谢所有的duckmayr、Dirk 和@user20650。 【参考方案1】:

来自 cmets;函数testrows 采用arma::Col 作为索引,但Rcpp::NumericVectorbetaBoot 中传递,因此出错。您还使用实数(随机统一)而不是整数索引进行子集化。 RcppRcppArmadillo 提供了可以在这里使用的 sample 函数。 (同样来自犰狳帮助页面应该是uvec)。

您可以使用Rcpp 糖函数生成索引以选择行:

Rcpp::IntegerVector x = Rcpp::seq(0, n-1);
arma::uvec idx = Rcpp::as<arma::uvec>(Rcpp::sample(x, n, true)) ;

或者你可以直接用arma::randi:

arma::uvec idx = arma::randi<arma::uvec>(n,  arma::distr_param(0,n-1));

使用第二种方法的一些代码,将testrows 省略为“我发现我不需要我的(被盗)帮手 函数测试行":

#include <RcppArmadillo.h>

// [[Rcpp::depends(RcppArmadillo)]]
        
// [[Rcpp::export]]
arma::mat betaBoot( arma::mat X, arma::vec y, int nboot)
  
  int n = X.n_rows,  k = X.n_cols;
  arma::mat betaHat(k, nboot);
  
  for(int i=0; i < nboot; i++)
    arma::uvec idx = arma::randi<arma::uvec>(n,  arma::distr_param(0,n-1));
    arma::mat X_boot = X.rows(idx);
    arma::vec y_boot = y.elem(idx);
    betaHat.col(i) = arma::solve(X_boot, y_boot);
    
  return betaHat;


/***R
set.seed(1)
n = 25
nc = 2
x = cbind(1, matrix(rnorm(n*nc), nc=nc))
y = rnorm(n)

sim = betaBoot(x, y, 2000)
*/

【讨论】:

以上是关于Rcpp Armadilllo 中的模板类 arma::Col的主要内容,如果未能解决你的问题,请参考以下文章

Rcpp犰狳中的样本

使用 Rcpp 模块公开 C++ 类

Azure 流分析 - ARM 模板中的“继承分区”

降价中的 Rcpp

犰狳中的 Rcpp 糖命令

ARM - 如何从存储帐户获取访问密钥,以便稍后在模板中的 AppSettings 中使用?