Reputation: 69
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
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
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