迭代MappedSparseMatrix中的非零元素

时间:2017-03-02 12:24:01

标签: c++ r sparse-matrix eigen rcpp

我将一个小的稀疏矩阵(用于测试)从R传递给C ++函数。矩阵属于类dgCMatrix,如下所示:

5 x 5 sparse Matrix of class "dgCMatrix"

[1,] . . . . .
[2,] 1 1 . . .
[3,] . . . . .
[4,] . . 1 . .
[5,] . 1 . . .

我按照文档here中的提法迭代此矩阵。 我的函数打印出迭代器的值和行索引列索引。

c ++函数定义如下:

#include <RcppEigen.h>
// [[Rcpp::depends(RcppEigen)]]
using Eigen::MappedSparseMatrix;
using Eigen::SparseMatrix;
using Eigen::VectorXi;
using Eigen::Map;
using namespace Rcpp;
using namespace std;

// [[Rcpp::export]]
void createRec(RObject sparse_mat, IntegerVector sparse_vec) {

const MappedSparseMatrix<int> spmat(as<MappedSparseMatrix<int> >(sparse_mat));
long int nrow = spmat.rows();
long int ncol = spmat.cols();
NumericVector sim(nrow);

for(int k=0;k<spmat.outerSize();k++){
    for(SparseMatrix<int,Eigen::ColMajor>::InnerIterator it(spmat,k);it;++it){
        cout<<"k="<<k<<endl;
        cout<<"value="<<it.value()<<endl;
        cout<<"it.row="<<it.row()<<endl;
        cout<<"it.col="<<it.col()<<endl;
        cout<<"index="<<it.index()<<endl;
    }
}
}

对于上面给出的矩阵,打印出以下结果:

k=0
value=156148016
it.row=66211520
it.col=0
index=66211520
k=1
value=0
it.row=0
it.col=1
index=0
k=1
value=1
it.row=4
it.col=1
index=4
k=2
value=1
it.row=3
it.col=2
index=3

1。)对应于k = 0的值的任何解释?这可能是由于以错误的方式传递矩阵吗?

2。)k迭代在outerSize上,它等于5,为什么它不迭代k = 3,4?考虑到它是一个sparseMatrix,这个行为是迭代器所期望的。

1 个答案:

答案 0 :(得分:4)

每当您看到非常大的数字(例如15614801666211520)时,您可能有未定义的行为(UB)或未正确初始化的值。在这种情况下,它是后来的。具体而言,dgCMatrix class&#39;基础类型是double而不是int

  

dgCMatrix类是压缩的,稀疏的,面向列的格式的一类稀疏数值矩阵。在此实现中,列中的非零元素被分类为递增的行顺序。 dgCMatrix是&#34;标准&#34; Matrix包中稀疏数值矩阵的类。

因此,当您尝试创建基础RObject的内存位置的地图时,需要执行额外步骤以在请求的不同类型中重新创建对象。添加const术语后,我愿意按照预期打赌这些条目,因为编译器可能会在内存中保留中间对象。

所以,改变了以下几点:

MappedSparseMatrix<int> spmat(as<MappedSparseMatrix<int> >(sparse_mat));

为:

MappedSparseMatrix<double> spmat(as<MappedSparseMatrix<double> >(sparse_mat));

应该足够了。

linked example使用SparseMatrix矩阵,您使用的是MappedSparseMatrix,但没有为第二个循环设置合适的MappedSparseMatrix::InnerIterator

因此,我们有:

for(SparseMatrix<int,Eigen::ColMajor>::InnerIterator it(spmat,k);it;++it){

转到:

for(MappedSparseMatrix<double>::InnerIterator it(spmat,k);it;++it){

另请注意,Eigen::ColMajorSparseMatrix<int, Eigen::ColMajor>::InnerIterator不需要使用k作为that is the default initialization。所以,我已经删除了这个陈述。

关于你的第二个问题,关于k的迭代。

k=3,4k进行迭代,但这些列中没有元素。因此,输出k的内部循环被调用。

如果我们在外部循环和内部循环中放置两个for(int k = 0; k < spmat.outerSize(); ++k) { Rcpp::Rcout << "Overall k = " << k << std::endl << std::endl; for(MappedSparseMatrix<double>::InnerIterator it(spmat,k); it; ++it) { Rcpp::Rcout << "Inner k = " << k << std::endl; } } 声明性输出语句,这很容易看出。

e.g。

using namespace std;

避免使用std

添加命名空间有时会产生意想不到的后果,尤其是像#include <RcppEigen.h> // [[Rcpp::depends(RcppEigen)]] using Eigen::MappedSparseMatrix; using Eigen::SparseMatrix; using Eigen::VectorXi; using Eigen::Map; // [[Rcpp::export]] void createRec(Rcpp::RObject sparse_mat) { MappedSparseMatrix<double> spmat(Rcpp::as<MappedSparseMatrix<double> >(sparse_mat)); long int nrow = spmat.rows(); Rcpp::NumericVector sim(nrow); for(int k = 0; k < spmat.outerSize(); ++k) { Rcpp::Rcout << "Overall k = " << k << std::endl << std::endl; for(MappedSparseMatrix<double>::InnerIterator it(spmat,k); it; ++it) { Rcpp::Rcout << "Inner k = " << k << std::endl << "value = " << it.value() << std::endl << "it.row = " << it.row() << std::endl << "it.col = " << it.col() << std::endl << "index = " << it.index() << std::endl; } } } /***R # Setup values id_row = c(2, 2, 4, 5) id_col = c(1, 2, 3, 2) vals = rep(1,4) # Make the matrix x = sparseMatrix(id_row, id_col, x = vals, dims = c(5, 5)) # Test the function createRec(x) */ 那样大的内容。

从上面的观点中略微简化你的例子,我们有以下几个简单的工作示例:

Overall k = 0

Inner k = 0
value = 1
it.row = 1
it.col = 0
index = 1
Overall k = 1

Inner k = 1
value = 1
it.row = 1
it.col = 1
index = 1
Inner k = 1
value = 1
it.row = 4
it.col = 1
index = 4
Overall k = 2

Inner k = 2
value = 1
it.row = 3
it.col = 2
index = 3
Overall k = 3

Overall k = 4

输出:

<role_select>
<username>User1</username>
<first_name>First1</first_name>
<last_name>Last1</last_name>
<middle_name>T</middle_name>
<company_id>020550</company_id>
<clinic_id>00122</clinic_id>
</role_select>

<role_select>
<username>User2</username>
<first_name>First2</first_name>
<last_name>Last2</last_name>
<middle_name>T</middle_name>
<company_id>020551</company_id>
<clinic_id>00123</clinic_id>
</role_select>

<role_select>
<username>User3</username>
<first_name>First3</first_name>
<last_name>Last3</last_name>
<middle_name>T</middle_name>
<company_id>020553</company_id>
<clinic_id>00124</clinic_id>
</role_select>

有关Eigen和Rcpp中稀疏矩阵的更多详细信息,您可能希望阅读Soren Hojsgaard和Doug Bates的Rcpp Gallery: Using iterators for sparse vectors and matrices