有没有办法在RcppEigen中进行元素减法?

时间:2014-01-24 22:43:57

标签: r eigen rcpp

我正在尝试编写一个函数来计算(稀疏)矩阵中每一列的方差,但它似乎没有一个元素减法运算符。给定R矩阵XX,

typedef Eigen::SparseMatrix<double> SpMat;
SpMat A(Rcpp::as<SpMat>(XX));               //cast XX into Eigen matrix A
Eigen::VectorXd means(A.cols());            //a vector called means

for(int i=0;i<A.cols();i++){                //calculate row-wise means, put
        for(int j=0;j<A.col(i).size();j++){ // in the vector 'means'
                sum += A.coeffRef(j,i);
        }
        means[i] = sum/A.col(i).size();
        sum = 0;
}

for(int i=0;i<A.cols();i++){
    Eigen::VectorXd meanVal(A.col(i).size());
    meanVal.fill(means[i]);
    meanVal = A.col(i)-meanVal; // <=== This is what I want to do
}

我是否错过了这样的运营商,或者我必须重复一遍?我想我也可以投射到NumericVector但是创建很多SEXP效率似乎很低。

2 个答案:

答案 0 :(得分:1)

这是Eigen中的遗漏或错误。要解决它,请尝试:

meanVal -= A.col(i);
meanVal = - meanVal;

这也有效:

meanVal = - meanVal;
meanVal += A.col(i)

答案 1 :(得分:0)

似乎没有按列操作。我将迭代每列中的非零元素:

#include <RcppEigen.h>

typedef Eigen::MappedSparseMatrix< double > mappedSparseMatrix ;

// [[Rcpp::depends(RcppEigen)]]
// [[Rcpp::export]]
Eigen::VectorXd varianceSparse( const mappedSparseMatrix X ) {
    // Matrix dimensions
    const int nRows = X.rows() ;
    const int nCols = X.cols() ;

    // Column means and variances
    const Eigen::VectorXd colMeans = Eigen::RowVectorXd::Constant( nCols, 1.0 / nRows ) * X ;
    Eigen::VectorXd colVariances = Eigen::VectorXd::Zero( nCols ) ;

    // Iterate over nonzero elements
    for( int col = 0 ; col < X.outerSize() ; ++col ) {
        int nNonZero = 0 ;
        for( mappedSparseMatrix::InnerIterator iterRow( X, col ) ; iterRow ; ++iterRow ) {
            colVariances( col ) += std::pow( iterRow.value() - colMeans( col ), 2.0 ) ;
            ++nNonZero ;
        }
        colVariances( col ) += ( nRows - nNonZero ) * std::pow( colMeans( col ), 2.0 ) ;
    }

    return colVariances / ( nRows - 1 ) ;
}

与R的var()函数比较:

( X <- matrix( c( 0, 1, 9, 0, 5, 4, 0, 0, 3, 1, 0, 4 ), 4, 3, TRUE ) )
     [,1] [,2] [,3]
[1,]    0    1    9
[2,]    0    5    4
[3,]    0    0    3
[4,]    1    0    4

apply( X, 2, var )
[1] 0.250000 5.666667 7.333333

varianceSparse( as( X, 'dgCMatrix' ) )
[1] 0.250000 5.666667 7.333333