我将一个小的稀疏矩阵(用于测试)从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,这个行为是迭代器所期望的。
答案 0 :(得分:4)
每当您看到非常大的数字(例如156148016
或66211520
)时,您可能有未定义的行为(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::ColMajor
中SparseMatrix<int, Eigen::ColMajor>::InnerIterator
不需要使用k
作为that is the default initialization。所以,我已经删除了这个陈述。
关于你的第二个问题,关于k
的迭代。
k=3,4
对k
进行迭代,但这些列中没有元素。因此,输出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。