thiagoveloso
thiagoveloso

Reputation: 2763

R - Convert matrix to vector from the bottom and row wise

I have the following matrix:

m <- matrix(1:9, ncol=3, byrow=TRUE)
m
     [,1] [,2] [,3]
[1,]    1    2    3
[2,]    4    5    6
[3,]    7    8    9

that I need to flatten, i.e., convert to a vector.

However, instead of going along the columns:

as.vector(m)
[1] 7 4 1 8 5 2 9 6 3

I need the resulting vector to go along the rows and from the bottom and to the right, e.g.:

[1] 7 8 9 4 5 6 1 2 3

How can I do that?

Upvotes: 3

Views: 857

Answers (3)

G. Grothendieck
G. Grothendieck

Reputation: 269852

1) Reverse the first dimension, tranpose and then unravel:

c(t(m[nrow(m):1, ]))
## [1] 7 8 9 4 5 6 1 2 3

2) Here is a second approach which computes the indices and then applies them. It is longer but avoids the transpose:

nr <- nrow(m)
nc <- ncol(m)
c(m[cbind(rep(nr:1, each = nc), 1:nc)])
## [1] 7 8 9 4 5 6 1 2 3

2a) A variation of (2) is to use a 1d index:

m[rep(nr:1, each = nc) + nr * (0:(nc - 1))]
## [1] 7 8 9 4 5 6 1 2 3

Note

I tried it for a 100x100 and a 1000x1000 matrix. In the first case (1) was the fastest and in the second case (2) and (2a) were the fastest thus if speed is a concern the actual dimensions seem to make a difference as to which to choose.

Upvotes: 6

tmfmnk
tmfmnk

Reputation: 40091

One option could be also using asplit():

unlist(rev(asplit(m, 1)))

[1] 7 8 9 4 5 6 1 2 3

Upvotes: 1

ThomasIsCoding
ThomasIsCoding

Reputation: 102241

Maybe you can use the following ways:

  • Solution 1:

    as.vector(t(apply(m, 2, rev)))
    

    which gives:

    > as.vector(t(apply(m, 2, rev)))
    [1] 7 8 9 4 5 6 1 2 3
    
  • Solution 2:

    unlist(rev(data.frame(t(m))),use.names = F)
    

    which gives:

    > unlist(rev(data.frame(t(m))),use.names = F)
    [1] 7 8 9 4 5 6 1 2 3
    

Upvotes: 0

Related Questions