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|

?

Vasilis Lemonidis
  • 636
  • 1
  • 7
  • 25
Johannes
  • 829
  • 2
  • 8
  • 10

5 Answers5

112

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
Eric Leschinski
  • 146,994
  • 96
  • 417
  • 335
Matthew Lundberg
  • 42,009
  • 6
  • 90
  • 112
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
Roland
  • 127,288
  • 10
  • 191
  • 288
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
Sven Hohenstein
  • 80,497
  • 17
  • 145
  • 168
  • 1
    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}`. – Ken Williams Sep 04 '15 at 14:51
  • 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. – Ken Williams Sep 04 '15 at 14:54
  • @KenWilliams I cannot reproduce the problem. It still works on my machine with R 3.2.1. – Sven Hohenstein Sep 04 '15 at 18:04
  • 1
    Oh - it looks like it only fails when `m` is a `Matrix` object. It indeed worked fine when `m` was a vanilla `matrix`. – Ken Williams Sep 04 '15 at 19:08
  • @SvenHohenstein can you please explain the `"[<-"` part – pogibas Nov 07 '17 at 23:03
  • 2
    @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. – Sven Hohenstein Nov 08 '17 at 05:18
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.

Eric Leschinski
  • 146,994
  • 96
  • 417
  • 335
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)} 
}
bud.dugong
  • 689
  • 7
  • 16