使用Rcpp代码访问和修改arma::sp_mat类稀疏矩阵的非零元素

使用Rcpp代码访问和修改arma::sp_mat类稀疏矩阵的非零元素,rcpp,armadillo,Rcpp,Armadillo,我正在痛苦地使用RcppArmadillo访问和更新arma:sp_mat类的稀疏矩阵的非零元素。例如,在矩阵R包中,如果B是类dgCMatrix的稀疏矩阵,则可以通过执行以下操作来访问和修改其非零元素: B@x[] = xx 其中,xx是包含实际非零元素的新向量。有人能帮我用犰狳代码做同样的事情吗?不幸的是,没有一个好的访问器可以返回sp\u mat中条目的位置 为了获得这些信息,我们首先计算列表中的元素数量,创建一个位置umat,然后构建一个新的sp_mat 进近代码 #包括 使用名称空间

我正在痛苦地使用RcppArmadillo访问和更新arma:sp_mat类的稀疏矩阵的非零元素。例如,在矩阵R包中,如果
B
是类
dgCMatrix
的稀疏矩阵,则可以通过执行以下操作来访问和修改其非零元素:

B@x[] = xx

其中,
xx
是包含实际非零元素的新向量。有人能帮我用犰狳代码做同样的事情吗?

不幸的是,没有一个好的访问器可以返回
sp\u mat
中条目的位置

为了获得这些信息,我们首先计算列表中的元素数量,创建一个位置
umat
,然后构建一个新的
sp_mat

进近代码
#包括
使用名称空间Rcpp;
//[[Rcpp::depends(RcppArmadillo)]]
//使用迭代器从稀疏矩阵中获取坐标列表
//首先计算总点数,然后获得列表。
//[[Rcpp::导出]]
arma::umat get_位置(arma::sp_mat&B)
{
//生成常量迭代器
arma::sp_mat::const_迭代器start=B.begin();
arma::sp_mat::const_迭代器end=B.end();
//计算点数
int n=标准::距离(起点、终点);
//如果未找到值(非常稀疏矩阵),则终止进程

如果(n不幸的是,没有nice访问器返回
sp_mat
中条目的位置

为了获得这些信息,我们首先计算列表中的元素数量,创建一个位置
umat
,然后构建一个新的
sp_mat

进近代码
#包括
使用名称空间Rcpp;
//[[Rcpp::depends(RcppArmadillo)]]
//使用迭代器从稀疏矩阵中获取坐标列表
//首先计算总点数,然后获得列表。
//[[Rcpp::导出]]
arma::umat get_位置(arma::sp_mat&B)
{
//生成常量迭代器
arma::sp_mat::const_迭代器start=B.begin();
arma::sp_mat::const_迭代器end=B.end();
//计算点数
int n=标准::距离(起点、终点);
//如果未找到值(非常稀疏矩阵),则终止进程

if(n非常感谢Coatless!这是一个非常有用的代码!!但是我在名为update_sp_matrix的函数的返回命令之前纠正了一个稍小的错误。参数locs需要用它的转置替换:B=arma::sp_mat(trans(locs),values,B.n_rows,B.n_cols)@EricH,请查看上面的编辑。问题应该已经解决。请随意投票并接受答案。非常感谢Coatless!这是一个非常有用的代码!!但我在名为update_sp_matrix的函数返回命令之前更正了一个稍小的错误。参数locs需要用它的转置替换:B=arma::sp_mat(trans(locs),values,B.n_rows,B.n_cols);@EricH,请查看上面的编辑。问题应该得到解决。请随意投票并接受答案。
#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);
}