使用 Rcpp 代码访问和修改类 arma::sp_mat 的稀疏矩阵的非零元素 [英] Access and modify the non zero elements of sparse matrix of class arma::sp_mat using Rcpp code
问题描述
我在使用 RcppArmadillo 访问和更新犰狳中 arma:sp_mat
类的稀疏矩阵的非零元素时遇到了麻烦.例如,在 Matrix R 包中,如果 B
是 dgCMatrix
类的稀疏矩阵,则可以通过执行以下操作访问和修改其非零元素:
I'm suffering about accessing and updating the non zero elements of sparse matrix of class arma:sp_mat
in Armadillo using RcppArmadillo. For example, in the Matrix R package, if B
is a sparse matrix of class dgCMatrix
, one can access and modify its non zero elements by doing:
B@x[] = xx
其中 xx
是包含实际非零元素的新向量.有人可以帮我用 Armadillo 代码做同样的事情吗?
where xx
is the new vector containing the actual non-zero elements. Can someone help me doing the same thing with Armadillo code?
推荐答案
不幸的是,没有很好的访问器可以返回 sp_mat
中条目的位置.
Unfortunately, there is no nice accessor that returns the location of entries in sp_mat
.
为了得到这个信息,我们首先计算列表中元素的个数,创建一个位置umat
,然后构造一个新的sp_mat
使用 API 文档推荐的批处理构造函数.
To get this information, we first calculate the number of elements in the list, create a location umat
, and then construct a new sp_mat
using a batch constructor as recommended by the API docs.
#include <RcppArmadillo.h>
using namespace Rcpp;
// [[Rcpp::depends(RcppArmadillo)]]
// Obtains a list of coordinates from the sparse matrix by using iterators
// First calculates total number of points and, then, obtains list.
// [[Rcpp::export]]
arma::umat get_locations(arma::sp_mat& B)
{
// Make const iterator
arma::sp_mat::const_iterator start = B.begin();
arma::sp_mat::const_iterator end = B.end();
// Calculate number of points
int n = std::distance(start, end);
// Kill process if no values are found (very sparse matrix)
if (n <= 0) { Rcpp::stop("No values found!"); }
// Build a location storage matrix
arma::umat locs(2, n);
// Create a vector to store each row information in. (Row, Col)
arma::uvec temp(2);
// Start collecting locations
arma::sp_mat::const_iterator it = start;
for(int i = 0; i < n; ++i)
{
temp(0) = it.row();
temp(1) = it.col();
locs.col(i) = temp;
++it; // increment
}
return locs;
}
// Updates the sparse matrix by constructing a new one
// [[Rcpp::export]]
arma::sp_mat update_sp_matrix(arma::sp_mat& B, arma::vec values)
{
// Get all the locatoins
arma::umat locs = get_locations(B);
// Make sure we have the correct number
if (locs.n_rows != values.n_elem) {
Rcpp::stop("Length mismatch between locations and supplied values!");
}
// The documentation recommends using batch constructor to rebuild matrix
B = arma::sp_mat(locs, values, B.n_rows, B.n_cols);
return B;
}
测试功能
// Generates a sparse matrix interally to test with
// Dimensions are 10 x 10 with only 2 points filled in.
arma::sp_mat make_test_sp()
{
// creates a matrix C++98 style
arma::umat locs;
locs << 4 << 7 << arma::endr
<< 6 << 7 << arma::endr;
// creates a vector C++98 style
arma::vec vals;
vals << 4.5 << 8.2 << arma::endr;
arma::sp_mat B(locs, vals, 10, 10);
return B;
}
// Main runner calls the built in test generation function.
// [[Rcpp::export]]
arma::sp_mat test_me()
{
arma::sp_mat B = make_test_sp();
arma::vec temp = arma::ones<arma::vec>(2);
return update_sp_matrix(B, temp);
}
编辑
更改了 get_location()
代码以反映
2×N
代替
N x 2
感谢@EricH 的评论
Thanks to @EricH's comment
这篇关于使用 Rcpp 代码访问和修改类 arma::sp_mat 的稀疏矩阵的非零元素的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!