Search code examples
reigenrcpprcppeigen

RcppEigen column labels


How can one extract column labels from an Rcpp::Eigen matrix?

For example, here is some R matrix

mat           <- matrix(1:4,ncol=2)
colnames(mat) <- c("col1","col2")

With Rcpp::NumericMatrix, one can simply call colnames like so:

void fun_NM(const Rcpp::NumericMatrixXd& Mat)
{
  Rcpp::CharacterVector coln = colnames(Mat);
  Rcpp::Rcout << coln << "\n\n";  
}

Then fun_NM(mat) prints "col1" "col2" as it should. Is there a way to access these colnames when the matrix is passes as an Eigen::MatrixXd?

void fun_EM(const Eigen::MatrixXd& Mat)
{
  ?
}

I don't know how RcppEigen converts the R matrix passed to into the Rcpp code to a Eigen::MatrixXd. Does it first converts it to a Rcpp::NumericMatrix? In that case, one could use Rcpp::NumericMatrix as input, extract the columns, and then transform it to Eigen::MatrixXd manually in the code to use the function in the Eigen library.


Solution

  • It helps to step back. What are names? An attribute. So in R we'd do

    mat <- matrix(1:4,ncol=2)
    colnames(mat) <- c("col1","col2")
    attributes(mat)
    

    Well, turns out in C++ with Rcpp it is just about the same---see several articles at the Rcpp Gallery or answers here.

    But, and there is always a but, going to an Eigen matrix drops attributes as the Eigen C++ classes have no such notion. But if you wanted to, you start with a SEXP (or a NumericMatrix), access the attributes and then proceed. A really simple example is below.

    Code

    #include <RcppEigen.h>
    
    // [[Rcpp::depends(RcppEigen)]]
    
    // [[Rcpp::export]]
    void showNames(SEXP m) {
      Rcpp::NumericMatrix nm(m);     // to easily access attributes
      Rcpp::List dmnm = nm.attr("dimnames");
      print(dmnm);
    
      // continue as before
      Eigen::MatrixXd Mat = Rcpp::as<Eigen::MatrixXd>(m); // make Mat from m as before
      // ... some stuff with Mat
    }
    
    /*** R
    mat <- matrix(1:4,ncol=2)
    colnames(mat) <- c("col1","col2")
    attributes(mat)
    
    showNames(mat)
    */
    

    Output

    > Rcpp::sourceCpp("~/git/stackoverflow/65251442/answer.cpp")
    
    > 
    mat <- matrix(1:4,ncol=2)
    
    > 
    colnames(mat) <- c("col1","col2")
    
    > 
    attributes(mat)
    $dim
    [1] 2 2
    
    $dimnames
    $dimnames[[1]]
    NULL
    
    $dimnames[[2]]
    [1] "col1" "col2"
    
    
    
    > 
    showNames(mat)
    [[1]]
    NULL
    
    [[2]]
    [1] "col1" "col2"
    
    > 
    

    You could access just column names the same way.