kaitokid
kaitokid

Reputation: 57

Reshape matrix by rows

I have a matrix with size 18000 x 54. I would like to reshape it as a matrix with size 54000 x 18, in which each row of my initial matrix becomes a matrix which has 3 rows.

Let's take an example. I have a matrix as follow:

a = matrix(1:18, nrow = 2, ncol = 9, byrow = T)
a
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9]
   1    2    3    4    5    6    7    8    9
  10   11   12   13   14   15   16   17   18

I would like to reshape this matrix so that it becomes:

[,1]  [,2]  [,3]    
  1      4    7  
  2      5    8
  3      6    9
  10    13   16
  11    14   17
  12    15   18 

I tried two following ways, but they do not work. The first is as follows:

dim(a) = c(6,3)

The second one is to create a function and then apply to each row:

reshapeX = function(x){
   dim(x) = c(3,as.integer(length(x)/3))
   return(as.matrix(x))
}
rbind(apply(a, 1, reshapeX))

But it does not work neither. Can someone help please?

Upvotes: 3

Views: 449

Answers (3)

akrun
akrun

Reputation: 887951

An option would be

out <- sapply(split.default(as.data.frame(a), as.integer(gl(ncol(a), 3, 
          ncol(a)))), function(x) c(t(x)))
colnames(out) <- NULL
out
#     [,1] [,2] [,3]
#[1,]    1    4    7
#[2,]    2    5    8
#[3,]    3    6    9
#[4,]   10   13   16
#[5,]   11   14   17
#[6,]   12   15   18

Or in shorter form of the above

sapply(split(a,(col(a)-1) %/%3), function(x) c(matrix(x, nrow = 3, byrow = TRUE)))

Or this can be done more compactly with array

apply(array(c(t(a)), c(3, 3, 2)), 2, c)
#      [,1] [,2] [,3]
#[1,]    1    4    7
#[2,]    2    5    8
#[3,]    3    6    9
#[4,]   10   13   16
#[5,]   11   14   17
#[6,]   12   15   18

Upvotes: 3

Sotos
Sotos

Reputation: 51612

Here is a loop free method,

m1 <- matrix(c(a), ncol = 3, nrow = 6)
rbind(m1[c(TRUE, FALSE),], m1[c(FALSE, TRUE),])

#     [,1] [,2] [,3]
#[1,]    1    4    7
#[2,]    2    5    8
#[3,]    3    6    9
#[4,]   10   13   16
#[5,]   11   14   17
#[6,]   12   15   18

Upvotes: 5

jogo
jogo

Reputation: 12569

You can do:

do.call(rbind, lapply(1:nrow(a), function(i) matrix(a[i, ], nrow=3)))

with your data:

a <- matrix(1:18, nrow = 2, ncol = 9, byrow = TRUE)
do.call(rbind, lapply(1:nrow(a), function(i) matrix(a[i, ], nrow=3)))
#      [,1] [,2] [,3]
# [1,]    1    4    7
# [2,]    2    5    8
# [3,]    3    6    9
# [4,]   10   13   16
# [5,]   11   14   17
# [6,]   12   15   18

Upvotes: 5

Related Questions