Rcpp: Eliminating a column and a row from a matrix [duplicate]

喜你入骨 提交于 2019-12-23 03:16:38

问题


I am trying to create a function that takes a matrix, n x p, and an index, e, and returns the sub-matrix obtained by eliminating the e-th column and the e-th row from X. I thought that the easiest thing was to create an n -1 x p - 1 matrix and insert the corners around the cross formed by the e-th row and column in it. The same approach works fine with EigenRcpp using the Corner syntax. It seems that Rcpp doesn't like assignment to Ranges. I get the following Error message:

error: non-static reference member 'Rcpp::SubMatrix<14>::MATRIX& Rcpp::SubMatrix<14>::m', can't use default assignment operator

I copy the code below.

My questions: How do I assign values to a block of a matrix? Is there a better way to do this?

#include <Rcpp.h>
using namespace Rcpp;

NumericMatrix elimMat(NumericMatrix X, int e){

int p = X.cols() - 1;
int n = X.rows() - 1;
int f = e - 1;
NumericMatrix M = NumericMatrix(n, p);

M(Range(0, f - 1), Range(0, f - 1)) = X(Range(0, f - 1), Range(0, f - 1)); //TopLeft same
M(Range(0, f - 1), Range(f, p - 1)) = X(Range(0, f - 1), Range(f + 1, p)); //TopRight
M(Range(f, n - 1), Range(0, f - 1)) = X(Range(f + 1, n), Range(0, f - 1)); //BottomLeft
M(Range(f, n - 1), Range(f, p - 1)) = X(Range(f + 1, n), Range(f + 1, p)); //BottomRight

return M;
}

Thanks for any help, Marco


回答1:


Regarding this error,

error: non-static reference member ‘Rcpp::SubMatrix<14>::MATRIX& Rcpp::SubMatrix<14>::m’, can’t use default assignment operator

I don't think there is anything you (or anyone on the client side) can do about this since the problem is coming from the class definition of SubMatrix. According to the compiler,

private:
    MATRIX& m ;
    vec_iterator iter ;
    int m_nr, nc, nr ;

m should be a static member, and it's not, hence the error.


Although I can't give you a general work-around for using Range assignments in this manner, here is one possible approach to your specific question about "crossing out" a section of a NumericMatrix:

#include <Rcpp.h>

// [[Rcpp::export]]
Rcpp::NumericMatrix crossout(Rcpp::NumericMatrix X, int e) {
  Rcpp::NumericMatrix result = Rcpp::no_init_matrix(X.nrow() - 1, X.ncol() - 1);
  Rcpp::NumericMatrix::iterator src = X.begin(), dst = result.begin();

  while (src != X.end()) {
    if (((src - X.begin()) % X.nrow()) != e && ((src - X.begin()) / X.nrow()) != e) {
      *dst = *src;
      ++dst;
    }
    ++src;
  }

  return result;
}

/*** R

M <- matrix(1:9 + .5, nrow = 3)
R> all.equal(M[c(1, 3), c(1, 3)], crossout(M, 1))
#[1] TRUE

R> crossout(M, 1)
#     [,1] [,2]
#[1,]  1.5  7.5
#[2,]  3.5  9.5

M2 <- matrix(1:20 + .5, nrow = 4)
R> all.equal(M2[c(1:2, 4), c(1:2, 4:5)], crossout(M2, 2))
#[1] TRUE

R> crossout(M2, 2)
#     [,1] [,2] [,3] [,4]
#[1,]  1.5  5.5 13.5 17.5
#[2,]  2.5  6.5 14.5 18.5
#[3,]  4.5  8.5 16.5 20.5

R> any(unique(c(M2[3,], M2[,3])) %in% crossout(M2, 2))
#[1] FALSE

*/

Above, I'm copying the current value of the "source" iterator to the "destination" iterator if the source iterator's position does not fall within the column or row specified by e. The row index is obtained as (src - X.begin()) % X.nrow(), and the column index is obtained as (src - X.begin()) / X.nrow().


Edit: Regarding your comment below, it would be pretty straightforward to accomodate non-square matrices / differing indices for the row and column dimensions:

#include <Rcpp.h>

// [[Rcpp::export]]
Rcpp::NumericMatrix crossout2(Rcpp::NumericMatrix X, int r, int c) {
  if (r >= X.nrow() || c >= X.ncol()) {
    Rf_error("Invalid row or column index.\n");
  }

  Rcpp::NumericMatrix result = Rcpp::no_init_matrix(X.nrow() - 1, X.ncol() - 1);
  Rcpp::NumericMatrix::iterator src = X.begin(), dst = result.begin();

  while (src != X.end()) {
    if (((src - X.begin()) % X.nrow()) != r && ((src - X.begin()) / X.nrow()) != c) {
      *dst = *src;
      ++dst;
    }
    ++src;
  }
  return result;
}



来源:https://stackoverflow.com/questions/33119163/rcpp-eliminating-a-column-and-a-row-from-a-matrix

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!