18

This is an Rcpp conversion related Q. I'm looking to convert a long std::vector into a Rcpp matrix object, but want to know if there is an easy conversion format. Naturally, you could loop over each element and fill an empty Rcpp matrix, but this seems error prone and possibly needless if a more convenient approach is possible.

The reason I'm asking is I would like to utilize OpenMP in some existing C++ code, but storing element in the Rcpp matrix object directly in an OpenMP loop doesn't appear to work well (whereas loading a std::vector object and converting to a matrix after the OpenMP loop is complete seems to be a decent approach to the problem).

Any help would be greatly appreciated!

Dirk Eddelbuettel
  • 360,940
  • 56
  • 644
  • 725
philchalmers
  • 727
  • 7
  • 19

2 Answers2

23

To expand on Dirk's answer; R matrices are really just vectors with a dim attribute set

> x <- 1
> y <- as.matrix(x)
> .Internal( inspect(x) )
@7f81a6c80568 14 REALSXP g0c1 [MARK,NAM(2)] (len=1, tl=0) 1 ## data
> .Internal( inspect(y) )
@7f81a3ea86c8 14 REALSXP g0c1 [NAM(2),ATT] (len=1, tl=0) 1 ## data
ATTRIB:
  @7f81a3e68e08 02 LISTSXP g0c0 [] 
    TAG: @7f81a30013f8 01 SYMSXP g1c0 [MARK,LCK,gp=0x4000] "dim" (has value) 
    @7f81a3ea8668 13 INTSXP g0c1 [NAM(2)] (len=2, tl=0) 1,1

Notice how the 'data' component of x and y are just REALSXPs, but you have this extra dim component on the matrix. Using this, we can easily convert a NumericVector to a matrix in Rcpp.

(Note: in the example below, I use SEXP in the attributes just so the conversions between types are explicit):

#include <Rcpp.h>
using namespace Rcpp;

// [[Rcpp::export]]
SEXP vec_to_mat(SEXP x_) {
  std::vector<double> x = as< std::vector<double> >(x_);
  /* ... do something with x ... */
  NumericVector output = wrap(x);
  output.attr("dim") = Dimension(x.size(), 1);
  return output;
}

/*** R
m <- c(1, 2, 3)
vec_to_mat(m)
*/

gives me

> m <- c(1, 2, 3)

> vec_to_mat(m)
     [,1]
[1,]    1
[2,]    2
[3,]    3

So, you can use the Dimension class and assign it to the dim attribute of a vector to make a matrix 'by hand' in Rcpp.

Kevin Ushey
  • 20,530
  • 5
  • 56
  • 88
16

You chose a good approach. In the OpenMP context, you have to stay away from the single-threaded R. So std::vector is good.

And yes, we have constructors from std::vector to Rcpp::NumericVector and Rcpp::NumericMatrix (which is after all just a vector with a dimensions attribute) as well as the Rcoo:Integer* variants, as well as the usual as<> and wrap converters.

There should be plenty of examples in the Rcpp unit tests, the Rcpp examples, and of course on the Rcpp Gallery site.

Edit: Here is an overly simple example:

 R> cppFunction('NumericVector phil(int n) { std::vector<double> x(n);
 +              return wrap(x); }') 
 R> phil(4)  
 [1] 0 0 0 0    
 R>    
Dirk Eddelbuettel
  • 360,940
  • 56
  • 644
  • 725
  • Great, thanks so much Dirk. I didn't see any in the Rcpp gallery or the examples that ship with the package, but maybe I just wasn't looking hard enough... – philchalmers Nov 08 '13 at 16:58
  • I see. Yes I understand that std::vector's are easily converted to Rcpp vectors, but I was more wondering about the most optimal way to fill a NumericMatrix given a std::vector and known dimensions (I guess something more like `NumericMatrix ret = vector2NumericMatrix(x, n, m);`, where `n` and `m` are the number of rows and columns. Easy to write a function to do this of course, but I was more wondering if something like this has been done already. Thanks! And sorry if I'm pestering you about trivial things :) – philchalmers Nov 08 '13 at 17:11
  • You can also consider RcppArmadillo which, as a linear algebra / matrix library, has a tons of subsetting, joining, combining, ... operators. That would probably be my choice. We may be missing a converter or two. Contributions welcome. – Dirk Eddelbuettel Nov 08 '13 at 17:12