10

A novice question as I learn the Rcpp classes / data structures: Is there a member function to erase a row / column for an object of class Rcpp::NumericMatrix? (Or other types of type **Matrix -- I'm assuming it's a template class)?

library(Rcpp)
cppFunction('
  NumericMatrix sub1 {NumericMatrix x, int& rowID, int& colID) {
    // let's assume separate functions for rowID or colID
    // but for the example case here
    x.row(rowID).erase(); // ??? does this type of member function exist?
    x.col(colID).erase(); // ???
    return x;
}')

If this type of member function doesn't exist, how about this?

cppFunction('NumericMatrix row_erase (NumericMatrix& x, int& rowID) {
  // a similar function would exist for removing a column.
  NumericMatrix x2(Dimension(x.nrow()-1, x.ncol());
  int iter = 0; // possibly make this a pointer?
  for (int i = 0; i < x.nrow(); i++) {
    if (i != rowID) {
      x2.row(iter) = x.row(i);
      iter++;
    }
  }
  return x2;
}')

Or perhaps we wish to remove a set of rows/columns:

cppFunction('NumericMatrix row_erase (NumericMatrix& x, IntegerVector& rowID) {
  // a similar function would exist for removing a column.
  rowID = rowID.sort();

  NumericMatrix x2(Dimension(x.nrow()- rowID.size(), x.ncol());
  int iter = 0; // possibly make this a pointer?
  int del = 1; // to count deleted elements
  for (int i = 0; i < x.nrow(); i++) {
    if (i != rowID[del - 1])
      x2.row(iter) = x.row(i);
      iter++;
    } else {
      del++;
    }
  }
  return x2;
}')
alexwhitworth
  • 4,839
  • 5
  • 32
  • 59
  • 1
    I answered a similar question [here](http://stackoverflow.com/questions/33119163/rcpp-eliminating-a-column-and-a-row-from-a-matrix) that (I think) combines both of your objectives into one function. If so, you should easily be able to adapt it into two separate functions for row and column elimination, respectively. – nrussell Nov 04 '15 at 01:10
  • @nrussell -- thanks, I'll take a look – alexwhitworth Nov 04 '15 at 16:37

2 Answers2

5

How about using RcppArmadillo? I think the intention of the code would be much clearer...

#include <RcppArmadillo.h>
// [[Rcpp::depends(RcppArmadillo)]]

using namespace arma;

// [[Rcpp::export]]
mat sub1( mat x, uword e) {
  x.shed_col(e-1);
  x.shed_row(e-1);
  return x;
}

/*** R
sub1( matrix(1:9,3), 2 )
*/

> sub1( matrix(1:9,3), 2 )
     [,1] [,2]
[1,]    1    7
[2,]    3    9
Thell
  • 5,883
  • 31
  • 55
  • 1
    Thanks! Any chance you can provide a similar answer with Eigen? – alexwhitworth Dec 09 '15 at 22:18
  • Eigen doesn't provide a convience function for this type of operation as far as I know... If I need to _manipulate_ data stored in a matrix I choose Armadillo over Eigen every time. – Thell Dec 09 '15 at 22:58
  • Hmm---good to know. I still have Eigen/Armadillo on my to-study list. Do you have a preference? The searching I've done has been inconclusive – alexwhitworth Dec 09 '15 at 23:35
  • Preference? R w/ Rcpp(Armadillo). I like the ease of expressiveness. – Thell Dec 09 '15 at 23:57
  • Very nice. I was interested to see that the `uword` typedef is automagically recognized as corresponding to an R `numeric` vector. Besides just reading examples like yours, is there a good way for me to find which Armadillo types are bound (presumably via implicit/templated `as` and `wrap` calls) to which R SEXP types? – Josh O'Brien Dec 10 '15 at 22:52
  • @JoshO'Brien I think the various as and wrap functions in the source serve as the mapping documentation. – Thell Dec 11 '15 at 16:23
1

Yes, both of these do work (fixing my typos above). I got a conversion error trying to replace int iter with Rcpp::NumericMatrix::iterator iter though. Any fix for this?

Note that we do not need the row_erase(NumericMatrix& x, int& ref) since this is a special case of row_erase(NumericMatrix& x, IntegerVector& ref).

NumericMatrix row_erase (NumericMatrix& x, IntegerVector& rowID) {
  rowID = rowID.sort();

  NumericMatrix x2(Dimension(x.nrow()- rowID.size(), x.ncol()));
  int iter = 0; 
  int del = 1; // to count deleted elements
  for (int i = 0; i < x.nrow(); i++) {
    if (i != rowID[del - 1]) {
      x2.row(iter) = x.row(i);
      iter++;
    } else {
      del++;
    }
  }
  return x2;
}

NumericMatrix col_erase (NumericMatrix& x, IntegerVector& colID) {
  colID = colID.sort();

  NumericMatrix x2(Dimension(x.nrow(), x.ncol()- colID.size()));
  int iter = 0; 
  int del = 1; 
  for (int i = 0; i < x.ncol(); i++) {
    if (i != colID[del - 1]) {
      x2.col(iter) = x.column(i);
      iter++;
    } else {
      del++;
    }
  }
  return x2;
}
alexwhitworth
  • 4,839
  • 5
  • 32
  • 59