1
votes

I'm brand new to Rcpp and trying to determine how to access the dimension names of an input so that I can use them later in the script. Specifically, I'm trying to grab the column names off of a sparse matrix in Armadillo and use them to name the rows in a separate object.

An example to clarify: Let's start by generating a trivial sparse matrix.

   input_mat <- Matrix::Matrix(sample(c(0,1), 35, replace =T)
                        ,nrow = 5
                        ,ncol = 7
                        ,dimnames = list(LETTERS[1:5], letters[1:7]))

Next, let's use that to do something in Rcpp. We will output a numeric matrix filled with some random numbers. nrow of the output = ncol of the input.

cppFunction('NumericMatrix map_columns(arma::sp_mat x, int k) {
              int n = x.n_cols;
              NumericMatrix new_mat = NumericMatrix(n, k);
              for(int i = 0; i < n; i++) {
                for(int j = 0; j < k; j++) {
                    new_mat(i,j) = rand() % 100 + 1; 
                }
              }
              rownames(new_mat) = CharacterVector::create("a", "b", "c", "d", "e", "f", "g");
              return(new_mat);
              }', depends = "RcppArmadillo"
              )

map_columns(input_mat, 4)

Instead of manually specifying the rownames of new_mat, I want to grab the colnames of x and assign the names on the fly. I've tried accessing slot names of the sparse matrix and have tried to assign them the same way I would in R, but no luck.

I'm guessing that I'm making a simple nube mistake. Can someone help me solve this? Any assistance will be greatly appreciated.

1

1 Answers

0
votes

I do not know a possibility to access S4 slots after the conversion to an Armadillo object, However, you can pass the sparse matrix as an S4 object to the function and handle the conversion explicitly:

input_mat <- Matrix::rsparsematrix(5, 7, 0.2)
input_mat@Dimnames <- list(LETTERS[1:5], letters[1:7])


Rcpp::cppFunction('NumericMatrix map_columns(Rcpp::S4 y, int k) {
              arma::sp_mat x = Rcpp::as<arma::sp_mat>(y);
              int n = x.n_cols;
              NumericMatrix new_mat = NumericMatrix(n, k);
              for(int i = 0; i < n; i++) {
                for(int j = 0; j < k; j++) {
                    new_mat(i,j) = rand() % 100 + 1; 
                }
              }
              Rcpp::List dimnames = y.slot("Dimnames");
              Rcpp::CharacterVector colnames = dimnames[1];
              rownames(new_mat) = colnames;
              return(new_mat);
              }', depends = "RcppArmadillo"
)

map_columns(input_mat, 4)

Note that I am creating a sparse matrix instead of a dense matrix found in your example code.

Side note: Don't use rand(). Use R's RNG, <random> from C++11 or ...