0

I am trying to assign values to specific rows and columns of a matrix using Rcpp and Armadillo.

This is the sort of subsetting and assignments that I am trying to do:

mat = matrix(1:15, nr=3)
r = i = 1; j = 3

mat[r, i:j] = mat[r, j:i]
mat[r, c(i,j)] = mat[r, c(j,i)]

I have read the nice Rcpp tutorial here and the arma docs here but have failed to understand adequately and my attempts result in errors. How can I do this please?

Rcpp code:

// [[Rcpp::depends(RcppArmadillo)]]
#include <RcppArmadillo.h>
using namespace Rcpp;
using namespace arma;


//[[Rcpp::export]]
arma::mat fun() {

  arma::mat myMat = randu<mat>(3,5);
  int r = 1; int i = 1; int j = 3;

  // get indices to subset:
  // i:j and j:i
  arma::uvec v = regspace<arma::uvec>(i, 1, j);
  arma::uvec rv = reverse(v);
  // create c(i,j)  
  std::vector<int> ij;
  ij.push_back(i); 
  ij.push_back(j);

  // Try to update selected rows and columns
  // The following gives the error: 
  // ": no matching function for call to ‘arma::Mat<double>::submat(int&, arma::uvec&)’"
  //myMat.submat(r, v) = myMat.submat(r, rv); 

  // So try to coerce int r to uvec:
  // The following gives the error:
  // "no matching function for call to ‘arma::conv_to<arma::Col<unsigned int> >::from(int&)’"
  //arma::uvec kk = arma::conv_to<arma::uvec>::from(r);

  // Also tried the following with error: 
  // "no match for call to ‘(arma::mat {aka arma::Mat<double>}) (int&, arma::uvec&)’"
  // myMat(r, v) = myMat(r, rv); 

  return myMat;
}

Edit: I have something working -- by converting the integer r to an arma::uvec using r + arma::zeros<arma::uvec>(1). I assume there is a proper way to approach this.

// [[Rcpp::depends(RcppArmadillo)]]
#include <RcppArmadillo.h>
using namespace Rcpp;
using namespace arma;


//[[Rcpp::export]]
arma::mat fun(arma::mat myMat) {

  int r = 0; int i = 0; int j = 2;

  // get indices to subset:
  // i:j and j:i
  arma::uvec v = regspace<arma::uvec>(i, 1, j);
  arma::uvec rv = reverse(v);

  arma::uvec row_idx = r + arma::zeros<arma::uvec>(1);
  myMat.submat(row_idx, v) = myMat.submat(row_idx, rv); 

  return myMat;
}

user2957945
  • 2,353
  • 2
  • 21
  • 40
  • 1
    You are on the right track here -- see the Arma docs which show that `uvec` aka unsigned int is indeed what is used by Armadillo for indexing. There are few different subsetting signatures available. – Dirk Eddelbuettel Feb 02 '20 at 22:28
  • 1
    Thanks Dirk. I had initially tried `arma::conv_to::from(r);` (where `r` is an `int`) but it errored out. Using `r + arma::zeros(1)` to get a `uvec` worked but felt a bit horrible. Is there a more reasonable way? – user2957945 Feb 02 '20 at 22:32
  • 1
    Something like that sounds right. I think we have articles on subsetting, including (Rcpp)Armadillo, at the Rcpp Gallery. Maybe look at those too? – Dirk Eddelbuettel Feb 02 '20 at 22:36
  • 1
    okay will do. I do appreciate you taking the time to look in on these beginner questions -- top class of you. – user2957945 Feb 02 '20 at 22:39
  • 2
    My pleasure. Looks like you're on the right track so keep at it. – Dirk Eddelbuettel Feb 02 '20 at 22:40

0 Answers0