Search code examples
rrcpp

How to get column names even if it is NULL in Rcpp?


I want to get column names of a matrix to set another one, but if matrix does not have column names (or is set to NULL), the following code crashes my R session.

CharacterVector cn = colnames(x);

The following code is the way how I get column names of a matrix even if it does not have.

#include <Rcpp.h>
using namespace Rcpp;

// Get column names or empty
// [[Rcpp::export]]
CharacterVector get_colnames(const NumericMatrix &x) {
   CharacterVector cn;

   SEXP cnm = colnames(x);
   if (!Rf_isNull(cnm)) cn = cnm;

   return(cn);
}

Is there a more elegant way?


Solution

  • I had started this and then got distracted. @coatless covered it, this is simply shorter.

    Code

    #include <Rcpp.h>
    
    // [[Rcpp::plugins(cpp11)]]
    using namespace Rcpp;
    
    // [[Rcpp::export]]
    CharacterVector getColnames(const NumericMatrix &x) {
      size_t nc = x.cols();
      SEXP s = x.attr("dimnames");  // could be nil or list
      if (Rf_isNull(s)) {           // no dimnames, need to construct names
        CharacterVector res(nc);
        for (size_t i=0; i<nc; i++) {
          res[i] = std::string("V") + std::to_string(i);
        }
        return(res);
      } else {                      // have names, return colnames part
        List dn(s);
        return(dn[1]);
      }
    
    }
    
    /*** R
    m <- matrix(1:9,3,3)
    getColnames(m)
    colnames(m) <- c("tic", "tac", "toe")
    getColnames(m)
    */
    

    Output

    R> Rcpp::sourceCpp("~/git/stackoverflow/55850510/answer.cpp")
    
    R> m <- matrix(1:9,3,3)
    
    R> getColnames(m)
    [1] "V0" "V1" "V2"
    
    R> colnames(m) <- c("tic", "tac", "toe")
    
    R> getColnames(m)
    [1] "tic" "tac" "toe"
    R>