我正在尝试编写一个函数来计算(稀疏)矩阵中每一列的方差,但它似乎没有一个元素减法运算符。给定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效率似乎很低。
答案 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