如何通过在 Rcpp 或 Armadillo 中将矩阵乘以向量元素来复制 R 的功能?

Posted

技术标签:

【中文标题】如何通过在 Rcpp 或 Armadillo 中将矩阵乘以向量元素来复制 R 的功能?【英文标题】:How can I replicate R's functionality with multiplying a matrix by a vector element-wise in Rcpp or Armadillo? 【发布时间】:2021-07-12 16:42:30 【问题描述】:

在 R 中,默认情况下将矩阵乘以向量是逐元素的,其工作原理如下:

A <- matrix(c(1,2,3,4,5,6), nrow=2)
b <- c(1,3)
A * b
     [,1] [,2] [,3]
[1,]    1    3    5
[2,]    6   12   18

本质上,矩阵的每个元素都乘以向量循环的一个元素。我想在 C++ 中重新创建此功能,使用 Rcpp 或其扩展,如 RcppEigen 或 RcppArmadillo。

对于犰狳,我尝试了以下方法:

arma::mat X ;
arma::vec beta ;

beta.resize ( 2 ) ;

beta (0) = 1.0 ;
beta (1) = 3.0 ;

X.resize ( 3, 2 ) ;

X (0,0) = 1.0 ;
X (0,1) = 2.0 ;
X (1,0) = 3.0 ;
X (1,1) = 4.0 ;
X (2,0) = 5.0 ;
X (2,1) = 6.0 ;

Rcout << X * beta << std::endl ;

这会产生一个向量:[7, 15, 23],就好像这是矩阵乘法一样。将 * 替换为 % 进行元素乘法会导致错误:“错误:元素乘法:不兼容的矩阵尺寸:3x2 和 2x1”

这种类似 R 的行为是否有任何内置函数,或者我需要创建自己的函数(我有,但我更喜欢“官方”的方式)

NumericMatrix matrixTimesVector(NumericMatrix mat, NumericVector vec)
    NumericMatrix res(mat.rows(), mat.cols());
    int index = 0;
    for (int i = 0; i < mat.cols(); ++i)
        for (int j = 0; j < mat.rows(); ++j)
            res( j , i ) = mat( j , i ) * vec[index++ % vec.size()];
        
    
    return res;

【问题讨论】:

【参考方案1】:

这里有几个选项。我想第三个最接近你想要的——记录在http://arma.sourceforge.net/docs.html#each_colrow

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

// looping through each column and element wise multiplication
// [[Rcpp::export]]
arma::mat matTimesVec(arma::mat mat, arma::vec v) 
  for(int i; i < mat.n_cols; i++)
    mat.col(i)  %=  v;
  
  return mat;


// form a diagonal matrix with the vector and then use matrix multiplication
// [[Rcpp::export]]
arma::mat matTimesVec2(arma::mat mat, arma::vec v) 
  return arma::diagmat(v) * mat;


// use the functionality described at http://arma.sourceforge.net/docs.html#each_colrow 
// to "Apply a vector operation to each column or row of a matrix "
// [[Rcpp::export]]
arma::mat matTimesVec3(arma::mat mat, arma::vec v) 
  mat.each_col() %= v;
  return mat; 


/*** R
A <- matrix(c(1,2,3,4,5,6), nrow=2)
b <- c(1,3)
A * b
matTimesVec(A, b)
matTimesVec2(A, b)
matTimesVec3(A, b)
*/

【讨论】:

以上是关于如何通过在 Rcpp 或 Armadillo 中将矩阵乘以向量元素来复制 R 的功能?的主要内容,如果未能解决你的问题,请参考以下文章

(Rcpp, armadillo) 将 arma::vec 转换为 arma::mat

在 Rcpp (Armadillo) 函数中使用数字序列作为默认参数

RCPP Armadillo:在函数中打印整数值

Rcpp Armadillo:RStudio 说“exp”不明确

Parallel 和 Rcpp Armadillo 的问题:集群工作人员之间可能存在变量损坏

稀疏 x 密集矩阵乘以 Armadillo 出乎意料地慢