Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In Rcpp - how to return a vector with names

Tags:

r

rcpp

Suppose I have the following matrix:

testM <- as.matrix(read.table(textConnection("
1  5  4  1  3  2
2  1  5  4  1  3
2  2  1  5  4  1
3  2  2  1  5  4
1  3  2  2  1  5
4  1  3  2  2  1
1  5  4  1  3  2
2  1  5  4  1  3
2  2  1  5  4  1
3  2  2  1  5  4
1  3  2  2  1  5
4  1  3  2  2  1
")))

This matrix has column names V1 to V6

Suppose that there is another matrix where I remove the column name:

> testM2<-testM
> colnames(testM2)<-NULL

Then if I try colMeans on testM and testM2 R returns a numeric class in both cases, except in the first case the answer has colnames.

> colMeans(testM)
      V1       V2       V3       V4       V5       V6 
2.166667 2.333333 2.833333 2.500000 2.666667 2.666667 
> colMeans(testM2)
[1] 2.166667 2.333333 2.833333 2.500000 2.666667 2.666667

Now suppose I have the same function written in RCpp as follows:

double do_mean(NumericVector x) {
  return mean(na_omit(x));
}

//[[Rcpp::export]]
NumericVector colMeansCppMt(NumericMatrix& x) {
  int nCols=x.ncol();
  NumericVector out=no_init(nCols);
  for (int i=0;i<nCols;i++) {
    NumericMatrix::Column tmp=x(_,i);
    out[i]=do_mean(tmp);
  }
  return out;
}

The output for colMeansCppMt for both testM and testM2 return numeric vectors, but the one for testM does not contain the colnames as it hasn't been set.

Now, suppose I change the colMeansCppMt function to include attributes like this:

//[[Rcpp::export]]
NumericVector colMeansCppMt(NumericMatrix& x) {
  int nCols=x.ncol();
  NumericVector out=no_init(nCols);
  for (int i=0;i<nCols;i++) {
    NumericMatrix::Column tmp=x(_,i);
    out[i]=do_mean(tmp);
  }
  out.attr("names")=x.attr("names");
  return out;
}

The output for testM is still a vector that doesn't contain the column names.

I also tried out.attr("names")=x.attr("colnames") and out.attr("colnames")=x.attr("colnames").

a). How can I check in RCpp where the colnames of a matrix (e.g. x in the example function above) has been set or not?

b). How can I return a numeric vector in R with names in Rcpp?

like image 952
uday Avatar asked Oct 01 '22 11:10

uday


1 Answers

To set the landscape:

  1. Regular R vectors have an (optional) names attribute,
  2. data.frames have a row.names attribute for rows, and names attribute for columns, and
  3. matrixs have an (optional) dimnames attribute; this attribute is a list containing 2 character vectors (rows then columns).

So what you want is the column names of x attached to the 'names' attribute of out, so something like:

out.attr("names") = VECTOR_ELT(x.attr("dimnames"), 1);

would work.

(I cannot recall if Rcpp has a nice API for getting / setting dimension names in arrays...)

like image 171
Kevin Ushey Avatar answered Oct 03 '22 15:10

Kevin Ushey