【问题标题】:Access and modify the non zero elements of sparse matrix of class arma::sp_mat using Rcpp code使用 Rcpp 代码访问和修改 arma::sp_mat 类稀疏矩阵的非零元素
【发布时间】:2016-10-24 15:26:06
【问题描述】:

我正在为使用 RcppArmadillo 在犰狳中访问和更新 arma:sp_mat 类稀疏矩阵的非零元素而苦恼。例如,在 Matrix R 包中,如果 B 是类 dgCMatrix 的稀疏矩阵,则可以通过以下方式访问和修改其非零元素:

B@x[] = xx

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

【问题讨论】:

    标签: rcpp armadillo


    【解决方案1】:

    不幸的是,没有很好的访问器可以返回 sp_mat 中条目的位置。

    为了得到这些信息,我们首先计算列表中的元素个数,创建一个位置umat,然后构造一个新的sp_matusing 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() 代码以反映

    sp_mat 结构

    2×N

    而不是

    N x 2

    感谢@EricH 的评论

    【讨论】:

    • 非常感谢 Coatless !这是一个非常有用的代码!但是我在 update_sp_matrix 函数的返回命令之前纠正了一个很小的错误。需要将参数 locs 替换为其转置:
    • B = arma::sp_mat(trans(locs), values, B.n_rows, B.n_cols);
    • @EricH,请参阅上面的编辑。问题应该得到解决。请随意投票并接受答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-30
    • 2016-02-03
    • 2015-05-02
    • 2013-02-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多