问题描述
亲爱的程序员们,
为了在大学的一个研讨会上编写一个引导回归版本,我尝试将我的 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,(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
。
也许是一些简单的我看不到的东西,或者可能是缺乏经验,但是学习这些东西会很棒。所以如果你能帮我解决这个问题,那就太好了。 先感谢您 艾琳
编辑:我的自举回归函数现在看起来(和工作)的方式:
#include <RcppArmadillo.h>
// [[Rcpp::depends(RcppArmadillo)]]
// [[Rcpp::export]]
arma::mat betaBoot(arma::colvec& y,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;
}
感谢我收到的所有有用的评论。
解决方法
来自评论;函数 testrows
为索引采用 arma::Col
,但 Rcpp::NumericVector
传入 betaBoot
,因此出错。您还使用实数(随机统一)而不是整数索引进行子集化。 Rcpp
和 RcppArmadillo
提供了可以在此处使用的 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,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)
*/