timbo1988
timbo1988

Reputation: 69

Rcpp (Eigen), duplicate or repeat rows

I was wondering if there’s a method in Rcpp, c++ or Eigen to duplicate or repeat each row of a given matrix n times?

For example, if I have a 2 x 2 matrix...:

(1,2
 3,4)

...to turn it into a 4 x 2 matrix like:

(1,2
 1,2
 3,4
 3,4)

I did not find any method or question like this on stackoverflow or anywhere in the docs of Eigen or Rcpp.

I’m aware, that I could use a for loop or an R-function from within Rcpp, but I’m worried, that this would cost a lot of performance.

Can anyone provide a hint on how to do this?

EDIT: This seems like an easy case for R, but it does not work with large matrices that cause memory to exceed. I am passing the data to a compiled Rcpp function anyway, so I would like to do it in there.

Regards Tim

Upvotes: 0

Views: 416

Answers (2)

ThomasIsCoding
ThomasIsCoding

Reputation: 102609

Perhaps kronecker is an option for you when with base R

> kronecker(mat, rep(1, 2))
     [,1] [,2]
[1,]    1    2
[2,]    1    2
[3,]    3    4
[4,]    3    4

Upvotes: 1

Allan Cameron
Allan Cameron

Reputation: 174468

You probably don't need Rcpp or Eigen for this. The following is vectorized natively in R and doesn't require loops, so it should be quick enough.

mat[rep(seq(nrow(mat)), each = 2),]
#>      [,1] [,2]
#> [1,]    1    2
#> [2,]    1    2
#> [3,]    3    4
#> [4,]    3    4

You may get a bit of a performance boost from writing an equivalent in C++, but I would be surprised if it made a huge difference. If in doubt you could always profile.

If you want an Rcpp function that does the same thing, then you could try:

Rcpp::cppFunction("NumericMatrix double_matrix(NumericMatrix m) {
   int nrow = 2 * m.rows();
   NumericMatrix res(nrow, m.ncol());
   for(int i = 0; i < nrow; ++i){
     res(i, _) = m((int) i / 2, _);
   }
   return res;
}")

So you can do:

double_matrix(mat)
#>      [,1] [,2]
#> [1,]    1    2
#> [2,]    1    2
#> [3,]    3    4
#> [4,]    3    4

Data

mat <- matrix(c(1, 3, 2, 4), ncol = 2)

mat
#>      [,1] [,2]
#> [1,]    1    2
#> [2,]    3    4

Upvotes: 3

Related Questions