Rotate a Matrix in R by 90 degrees clockwise
Asked Answered
B

5

59

I have a matrix in R like this:

|1|2|3|
|1|2|3|
|1|2|3|

Is there an easy way to rotate the entire matrix by 90 degrees clockwise to get these results?

|1|1|1|
|2|2|2|
|3|3|3|

and again rotating 90 degrees:

|3|2|1|
|3|2|1|
|3|2|1|

?

Bygone answered 11/5, 2013 at 10:37 Comment(2)
It's called transposing a matrix. Try function t.Kanaka
Yeah but does t work 360 degrees around? or only 90 degrees to the right?Bygone
M
114

t does not rotate the entries, it flips along the diagonal:

x <- matrix(1:9, 3)
x
##      [,1] [,2] [,3]
## [1,]    1    4    7
## [2,]    2    5    8
## [3,]    3    6    9

t(x)
##      [,1] [,2] [,3]
## [1,]    1    2    3
## [2,]    4    5    6
## [3,]    7    8    9

90 degree clockwise rotation of R matrix:

You need to also reverse the columns prior to the transpose:

rotate <- function(x) t(apply(x, 2, rev))
rotate(x)
##      [,1] [,2] [,3]
## [1,]    3    2    1
## [2,]    6    5    4
## [3,]    9    8    7

rotate(rotate(x))
##      [,1] [,2] [,3]
## [1,]    9    6    3
## [2,]    8    5    2
## [3,]    7    4    1

rotate(rotate(rotate(x)))
##      [,1] [,2] [,3]
## [1,]    7    8    9
## [2,]    4    5    6
## [3,]    1    2    3

rotate(rotate(rotate(rotate(x))))
##      [,1] [,2] [,3]
## [1,]    1    4    7
## [2,]    2    5    8
## [3,]    3    6    9

90 degree counter clockwise rotation of R matrix:

Doing the transpose prior to the reverse is the same as rotate counter clockwise:

foo = matrix(1:9, 3)
foo
## [,1] [,2] [,3]
## [1,]    1    4    7
## [2,]    2    5    8
## [3,]    3    6    9

foo <- apply(t(foo),2,rev)
foo

## [,1] [,2] [,3]
## [1,]    7    8    9
## [2,]    4    5    6
## [3,]    1    2    3
Materiality answered 11/5, 2013 at 12:25 Comment(7)
nice and very intuitive. Thanks!Bygone
apply is perhaps not optimal; from R-help archives: rotate = function(mat) t(mat[nrow(mat):1,,drop=FALSE]) Krongold
Is there a forumla for anti-clockwise rotation other than 2 repeat operations? This is quite an intensive process for large matrices.Superincumbent
@Superincumbent Simply reverse the order of operations: apply(t(x), 2, rev)Materiality
Thanks. Or apparently apply(x, 1, rev), which I don't understand as how can a reordering function possibly change change matrix dimensions (albeit not in this case)?! If you don't know I'll post as a question.Superincumbent
Have posted it up: #21729810Superincumbent
@Krongold Is there anything about changing the columns at the same time in docs?Squire
C
31
m <- matrix(rep(1:3,each=3),3)

     [,1] [,2] [,3]
[1,]    1    2    3
[2,]    1    2    3
[3,]    1    2    3

t(m[nrow(m):1,])

     [,1] [,2] [,3]
[1,]    1    1    1
[2,]    2    2    2
[3,]    3    3    3

m[nrow(m):1,ncol(m):1]

     [,1] [,2] [,3]
[1,]    3    2    1
[2,]    3    2    1
[3,]    3    2    1

t(m)[ncol(m):1,]

     [,1] [,2] [,3]
[1,]    3    3    3
[2,]    2    2    2
[3,]    1    1    1
Carcassonne answered 11/5, 2013 at 10:43 Comment(0)
J
10

An easy way to rotate a matrix by 180° is this:

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


rot <- function(x) "[<-"(x, , rev(x))

rot(m)
#      [,1] [,2] [,3] [,4]
# [1,]    8    6    4    2
# [2,]    7    5    3    1

rot(rot(m))
#      [,1] [,2] [,3] [,4]
# [1,]    1    3    5    7
# [2,]    2    4    6    8
Jinnyjinrikisha answered 12/2, 2014 at 14:30 Comment(6)
A nice property of this function is that it preserves the sparseness if you're using Matrix classes. However, your code doesn't work (anymore?) in R 3.2.1, it complains about a missing value argument. Instead, this variation works: rotate <- function(x) {x[] <- rev(x); x}.Glyn
I should mention though, that even though this preserves sparseness, it does have to temporarily instantiate a non-sparse vector whose size is the product of the matrix dimensions.Glyn
@KenWilliams I cannot reproduce the problem. It still works on my machine with R 3.2.1.Jinnyjinrikisha
Oh - it looks like it only fails when m is a Matrix object. It indeed worked fine when m was a vanilla matrix.Glyn
@SvenHohenstein can you please explain the "[<-" partOxide
@PoGibas The function [<- is used for index replacement. In the code x[i] <- y, the object x will be altered. If you use "[<-"(x, i, y) instead, the modified object will be returned and x will not be changed.Jinnyjinrikisha
C
3

R methods to rotate a matrix 90 degrees and -90 degrees

#first reverse, then transpose, it's the same as rotate 90 degrees
rotate_clockwise         <- function(x) { t(     apply(x, 2, rev))}
#first transpose, then reverse, it's the same as rotate -90 degrees:
rotate_counter_clockwise <- function(x) { apply(     t(x),2, rev)}

#or if you want a library to help make things easier to read:
#install.packages("pracma")
library(pracma)
rotate_one_eighty <- function(x) { rot90(x, 2) }
rotate_two_seventy <- function(x) { rot90(x, -1) }

foo = matrix(1:9, 3)
foo

foo = rotate_clockwise(foo)
foo

foo = rotate_counter_clockwise(foo)
foo

foo = rotate_one_eighty(foo)
foo

Prints:

     [,1] [,2] [,3]
[1,]    1    4    7          #original matrix
[2,]    2    5    8
[3,]    3    6    9
     [,1] [,2] [,3]
[1,]    3    2    1
[2,]    6    5    4          #rotated 90 degrees
[3,]    9    8    7
     [,1] [,2] [,3]
[1,]    1    4    7
[2,]    2    5    8          #rotated -90 degrees
[3,]    3    6    9
     [,1] [,2] [,3]
[1,]    9    6    3
[2,]    8    5    2          #rotated 180 degrees
[3,]    7    4    1

Notice that rotating a matrix clockwise, then counterclockwise returns the numbers to their original position, then rotating by 180 is like rotating by 90 twice.

Caprification answered 19/3, 2017 at 3:41 Comment(0)
T
0

Or combined in a single function (based on Eric Leschinski):

rotate  <- function(x, clockwise=T) {
  if (clockwise) { t( apply(x, 2, rev))
  } else {apply( t(x),2, rev)} 
}
Taeniafuge answered 17/8, 2017 at 15:15 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.