Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Understanding passing armadillo matrices to R functions via RInside

I'm trying to use R within C++ via RInside. I'm having trouble passing armadillo matrices to R and returning a result. Below I am able to return a results from an R library function, however I get the wrong result. I'm using the skewness function from the moments package as an example which works as should in R. I checked the examples from RInside and i'm still unsure how to use RcppArmadillo. How do I properly pass an armadillo matrix in c++ to R?

    #include <RInside.h>                   
    #include <RcppArmadillo.h>

    using namespace std;
    using namespace arma;

    int main(int argc, char *argv[]) {
        RInside R(argc, argv);  


        string R_libs = "suppressMessages(library(moments));";

        R.parseEvalQ(R_libs);

        mat A = randu<mat>(5,5);

        R["A"] = A;

        string R_skewness = "B <- skewness(A);";
        //this fails
        mat B = Rcpp::as<mat>(R.parseEval(R_skewness)); //terminate called after throwing an instance of 'Rcpp::not_a_matrix'   

        //this works but wrong
        mat B = Rcpp::as<vec>(R.parseEval(R_skewness)); // returns only 1 number, should be 5 ( 1 for each columnn), same result if i change mat B to vec B
        exit(0);
 }
like image 608
pyCthon Avatar asked Jan 15 '23 01:01

pyCthon


2 Answers

The way we implemented as<mat> requires that the R object you pass is a matrix. And in your example B is a vector:

> A <- matrix( runif(25), ncol = 5)
> A
           [,1]      [,2]       [,3]       [,4]      [,5]
[1,] 0.19215339 0.5857249 0.14345222 0.32154176 0.6162155
[2,] 0.95753898 0.9618379 0.06239842 0.06200197 0.7044018
[3,] 0.33575790 0.1372804 0.03027635 0.62662467 0.9778451
[4,] 0.16504957 0.1919765 0.49176372 0.94841456 0.2914772
[5,] 0.01570709 0.8055231 0.51218581 0.79562809 0.6939380
> B <- skewness( A )
> B
[1]  1.15196587 -0.04547576  0.32186257 -0.30788111 -0.29251009

For conversion to arma::vec I don't reproduce the behavior you see. The arma::vec has 3 elements:

require( RcppArmadillo )    ## and make sure you have Rcpp 0.10.0 or later

sourceCpp( code = '
// [[Rcpp::depends("RcppArmadillo")]]

#include <RcppArmadillo.h>

using namespace arma ; 
using namespace Rcpp ;

// [[Rcpp::export]]
List foo( NumericVector x){
    vec B = Rcpp::as<vec>(x); 

    return List::create( 
        _["nrows"] = B.n_rows,
        _["ncols"] = B.n_cols
    ) ;

}
')
foo( c(1, 2, 3 ) )
# $nrows
# [1] 3
# 
# $ncols
# [1] 1
like image 150
Romain Francois Avatar answered Jan 27 '23 04:01

Romain Francois


You are trying compound expression involving several heavily templated libraries. That can go wrong. I;d recommended to do it in pieces:

  1. Make sure you have the matrix A you expect passed down to the embedded R

  2. Make sure the function calls worked right, check the result.

  3. Important: check the result type. A matrix should come back fine.

  4. Get the result back to C++.

  5. Get it to Rcpp.

  6. Use RcppArmadillo marshaling to get to Armadillo.

In principle, this should work. The devil is in the detail, as always.

like image 33
Dirk Eddelbuettel Avatar answered Jan 27 '23 04:01

Dirk Eddelbuettel