Search code examples
rcpprcpp11

In Rcpp How to create a NumericMatrix by a NumbericaVector?


In Rcpp How to create a NumericMatrix by a NumbericaVector?

Something like

// vector_1 has 16 element

NumericMatrix mat = NumericMatrix(vector_1, nrow = 4);

Thanks.


Solution

  • Edit: I knew we had something better. See below for update.


    Looks like we do not have a matching convenience constructor for this. But you can just drop in a helper function -- the following is minimally viable (one should check that n + k == length(vector)) and taken from one of the unit tests:

    // [[Rcpp::export]]
    Rcpp::NumericMatrix vec2mat(Rcpp::NumericVector vec, int n, int k) {
        Rcpp::NumericMatrix mat = Rcpp::no_init(n, k);
        for (auto i = 0; i < n * k; i++) mat[i] = vec[i];
        return mat;
    }
    

    Another constructor takes the explicit dimensions and then copies the payload for you (via memcpy()), removing the need for the loop:

    // [[Rcpp::export]]
    Rcpp::NumericMatrix vec2mat2(Rcpp::NumericVector s, int n, int k) {
        Rcpp::NumericMatrix mat(n, k, s.begin());
        return mat;
    }
    

    Full example below:

    > Rcpp::sourceCpp("~/git/stackoverflow/66720922/answer.cpp")
    
    > v <- (1:9) * 1.0  # numeric
    
    > vec2mat(v, 3, 3)
         [,1] [,2] [,3]
    [1,]    1    4    7
    [2,]    2    5    8
    [3,]    3    6    9
     
    > vec2mat2(v, 3, 3)
         [,1] [,2] [,3]
    [1,]    1    4    7
    [2,]    2    5    8
    [3,]    3    6    9
    > 
    

    Full source code below.

    #include <Rcpp.h>
    
    // [[Rcpp::export]]
    Rcpp::NumericMatrix vec2mat(Rcpp::NumericVector vec, int n, int k) {
        Rcpp::NumericMatrix mat = Rcpp::no_init(n, k);
        for (auto i = 0; i < n * k; i++) mat[i] = vec[i];
        return mat;
    }
    
    // [[Rcpp::export]]
    Rcpp::NumericMatrix vec2mat2(Rcpp::NumericVector s, int n, int k) {
        Rcpp::NumericMatrix mat(n, k, s.begin());
        return mat;
    }
    
    /*** R
    v <- (1:9) * 1.0  # numeric
    vec2mat(v, 3, 3)
    vec2mat2(v, 3, 3)
    */
    

    Depending on what you want to do with the matrix object (linear algrebra?) you may want to consider RcppArmadillo (or RcppEigen) as those packages also have plenty of vector/matrix converters.