1

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.

Justin
  • 327
  • 3
  • 13

1 Answers1

3

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.

Dirk Eddelbuettel
  • 360,940
  • 56
  • 644
  • 725
  • I think `vec.attr("dim") = Rcpp::Dimension( n_row, n_col );` is also valid to convert a vector to a matrix - reference: https://teuder.github.io/rcpp4everyone_en/100_matrix.html#creating-matrix-object – SymbolixAU Mar 22 '21 at 21:36
  • Nice, yes, I think I have done that too. It is slightly dirty in the sense that the (C++) class is then still a vector. – Dirk Eddelbuettel Mar 22 '21 at 21:38
  • yeah, I made the return type `SEXP`, because I don't think it liked returning a `Matrix<>`. – SymbolixAU Mar 22 '21 at 21:39
  • and it even states that in the linked reference - "Thus, if you want to convert it to Matrix type in Rcpp, you need to use as() function." – SymbolixAU Mar 22 '21 at 21:43