如何将Armadillo矩阵与从qnorm获得的NumericVector相乘?

问题描述

当我尝试使用operator *在Rcpp中将arma :: mat和NumericVector相乘时,出现以下错误

no match for operator*

以下是我要乘以的示例:

NumericVector exampleNumericVector(L-1);
arma::mat exampleMatrix(L-1,L-1);
exampleMatrix*(Rcpp::qnorm(exampleNumericVector,1,true,false));

我尝试浏览过 excellent Armadillo文档,而我能找到的最接近解决方案的是prod()函数,但这并不能解决我的问题。我也尝试重载运算符*。但是,这也不成功。

更新:可复制的示例

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

using namespace Rcpp;
using namespace arma;

// [[Rcpp::export]]
arma::vec foo(Rcpp::NumericVector x) {
  // [[Rcpp::depends(RcppArmadillo)]]
  Rcpp::NumericVector y = Rcpp::qnorm(x,false);
  int n = y.size();
  arma::mat M(n,n);
  M.fill(1.0);                  // nonsense content,we don't care
  arma::vec v(y);               // instantiate Arma vec from Rcpp vec
  arma::vec res = M * v;
  return res;
}

// [[Rcpp::export]]
Rcpp::List foo(const int n,const int M,const int L,const double mu){
  
  // initialize variables
  arma::mat P = arma::zeros(M,L);
  arma::mat SigInvTmp = arma::zeros(L-1,L-1);
  double muTmp = 0;
  double s2Tmp = 0;
  arma::mat Sig = arma::zeros(L,L);
  arma::mat Sigee = arma::zeros(L-1,L-1);
  arma::mat Sigie = arma::zeros(1,L-1);
  arma::mat Sigei = arma::zeros(L-1,1);
  Rcpp::NumericVector Pie(L-1);
  
  for(int i = 0; i < M; i++){
    
    arma::uvec iIdx(1); // vector of index to take for i
    iIdx(0) = i;
    
    for(int l = 0; l < L; L++){
      
      srand(time(0)); 
      
      // We need to get the vector of indices excluding l
      arma::uvec idx(L-1); // vector of indices to subset by
      arma::uword ii = 0;  // the integer we'll add at each elem of idx
      for (arma::uword j = 0; j < (L-1); ++j) {
        if (ii == l) {   // if ii equals l,we need to skip l
          ii += 1;     
        }
        idx[j] = ii;     // then we store ii for this elem
        ii += 1;         // and increment ii
      }
      
      // Single index for l
      arma::uvec lIdx(1); // vector of index to take for l
      lIdx(0) = l;
      
      Sigee = Sig.submat(idx,idx);
      Sigie = Sig.submat(lIdx,idx);
      Sigei = Sig.submat(idx,lIdx);
      Pie = P.submat(iIdx,idx);
      
      SigInvTmp = inv(Sigee);
      arma::vec qnormVec = foo(Pie);
      muTmp = mu + as_scalar(Sigie*SigInvTmP*(qnormVec-mu));
      s2Tmp = sqrt(as_scalar(Sig(l,l)-Sigie*SigInvTmP*Sigei));
    }
  }
  return Rcpp::List::create(Rcpp::Named("mu") = muTmp,Rcpp::Named("s2") = s2Tmp);
}

解决方法

您的示例既不完整,也不简单,也不可重复。

因此,为了通过这个例子,我们举了一个完整的例子。您输入的是p值的向量,以获取其分位数,它会创建一个适当尺寸的(无意义的)矩阵,从Rcpp向量创建一个arma向量(键:它们都与SEXP转换)并相乘。返回结果。

#include <RcppArmadillo.h>

// [[Rcpp::depends(RcppArmadillo)]]

// [[Rcpp::export]]
arma::vec foo(Rcpp::NumericVector x) {
  Rcpp::NumericVector y = Rcpp::qnorm(x,1,true,false);
  int n = y.size();
  arma::mat M(n,n);
  M.fill(1.0);                  // nonsense content,we don't care
  arma::vec v(y);               // instantiate Arma vec from Rcpp vec
  arma::vec res = M * v;
  return res;
}

/*** R
foo(c(0.95,0.975))
*/
演示版
R> sourceCpp("~/git/stackoverflow/63641766/answer.cpp")

R> foo(c(0.95,0.975))
        [,1]
[1,] 3.60482
[2,] 3.60482
R>