Search code examples
rrcpp

Rcpp: transform matrix to vector


Generally I want to transform a 2-D matrix from Rcpp to a vector in R, it should be very simple by using "as(m)", however, I still get a matrix from R, I wonder why? SHould I remove the attr manually in Rcpp?

#include <Rcpp.h>
#include <string>
using namespace Rcpp;
// [[Rcpp::export]]
NumericVector matrix2vector(NumericMatrix m, const bool byrow=false){
  NumericVector x;
  if(byrow){
    Rcout<< "warning: default by column\n";
    m = transpose(m);
    x = as<NumericVector>(m);
  }else{
    x = as<NumericVector>(m);
  }
  return(x);
}

/*** R
m=matrix(1:15,5,3)
matrix2vector(m,byrow=T)
*/


Solution

  • I am not sure I understand the question, or the attempted answer. You are still returning matrices here. And Rcpp has limited support for reshaping and more advanced Matrix operations.

    A slighly simplified version of your code:

    Code
    #include <Rcpp.h>
    using namespace Rcpp;
    // [[Rcpp::export]]
    NumericVector matrix2vector(NumericMatrix m, const bool byrow=false){
      if (byrow){
        Rcout << "warning: default by column\n";
        m = transpose(m);
      }
      return NumericVector(m);
    }
    
    /*** R
    m <- matrix(1:15,5,3)
    print(matrix2vector(m, byrow = TRUE))
    print(matrix2vector(m, byrow = FALSE))
    */
    
    Output
    R> Rcpp::sourceCpp("~/git/stackoverflow/61036707/question.cpp")
    
    R> m <- matrix(1:15,5,3)
    
    R> print(matrix2vector(m, byrow = TRUE))
    warning: default by column
         [,1] [,2] [,3] [,4] [,5]
    [1,]    1    2    3    4    5
    [2,]    6    7    8    9   10
    [3,]   11   12   13   14   15
    
    R> print(matrix2vector(m, byrow = FALSE))
         [,1] [,2] [,3]
    [1,]    1    6   11
    [2,]    2    7   12
    [3,]    3    8   13
    [4,]    4    9   14
    [5,]    5   10   15
    R> 
    

    All you are executing here, really, is a transpose.

    I would try RcppArmadillo which does have explicit rowvec and colvec types, with the latter being aliased to vec. I would have to check what it suggest in terms of reshaping "rows by columns" elements into a rows by columns vector.

    Edit: Indeed (as so often) easier in RcppArmadillo.

    Code
    #include <RcppArmadillo.h>
    
    // [[Rcpp::depends(RcppArmadillo)]]
    
    // [[Rcpp::export]]
    arma::mat matrix2vector(arma::mat m, const bool byrow=false){
      if (byrow) {
        return m.as_row();
      } else {
        return m.as_col();
      }
    }
    
    /*** R
    m <- matrix(1:15,5,3)
    print(matrix2vector(m, byrow = TRUE))
    print(matrix2vector(m, byrow = FALSE))
    */
    
    Output
    R> Rcpp::sourceCpp("~/git/stackoverflow/61036707/answer.cpp")
    
    R> m <- matrix(1:15,5,3)
    
    R> print(matrix2vector(m, byrow = TRUE))
         [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12] [,13] [,14] [,15]
    [1,]    1    6   11    2    7   12    3    8   13     4     9    14     5    10    15
    
    R> print(matrix2vector(m, byrow = FALSE))
          [,1]
     [1,]    1
     [2,]    2
     [3,]    3
     [4,]    4
     [5,]    5
     [6,]    6
     [7,]    7
     [8,]    8
     [9,]    9
    [10,]   10
    [11,]   11
    [12,]   12
    [13,]   13
    [14,]   14
    [15,]   15
    R> 
    

    Note that I am using arma::mat as the return type to not conflict with either colvec or rowvec. You could pick either but then you could not return the answer.

    Edit 2: And per the comment below: if you really just want to reshape content you already have there is no need for Rcpp. Just nuke the dim attribute. Works at the R (and C++ if you want) level:

    R> m
         [,1] [,2] [,3]
    [1,]    1    6   11
    [2,]    2    7   12
    [3,]    3    8   13
    [4,]    4    9   14
    [5,]    5   10   15
    R> dim(m)
    [1] 5 3
    R> dim(m) <- NULL
    R> m
     [1]  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15
    R>