2

If I knew the dimensions of each square submatrix m (2x2), and that the dimensionality of a large square matrix M was evenly divisible by the dimensionality m: M modulo m == 0.

Is there an efficient way to rotate submatrices within the following matrix M:

M = array([[ 1.,  2.,  1.,  2.],
           [ 3.,  4.,  3.,  4.],
           [ 1.,  2.,  1.,  2.],
           [ 3.,  4.,  3.,  4.]])

Such that the result is:

M* = array([[ 2.,  4.,  2.,  4.],
            [ 1.,  3.,  1.,  3.],
            [ 2.,  4.,  2.,  4.],
            [ 1.,  3.,  1.,  3.]])

In particular, it would be useful to force the use a function like numpy.rot90(), such that other rotations can be achieved e.g.

180: rot90(x, 2)
270: rot90(x, 3)

etc.

user1658296
  • 1,398
  • 2
  • 18
  • 46

1 Answers1

2

Here's an approach using reshape and transpose -

m,n = M.shape
out = M.reshape(m//2,2,n//2,2)[...,::-1].transpose(0,3,2,1).reshape(m,n)

Sample run -

In [246]: M
Out[246]: 
array([[51, 70, 59, 38, 84, 18],
       [80, 25, 76, 43, 80, 48],
       [92, 98, 46, 14, 65, 47],
       [73, 31, 32, 79, 87, 70]])

In [247]: m,n = M.shape

In [248]: M.reshape(m//2,2,n//2,2)[...,::-1].transpose(0,3,2,1).reshape(m,n)
Out[248]: 
array([[70, 25, 38, 43, 18, 48],
       [51, 80, 59, 76, 84, 80],
       [98, 31, 14, 79, 47, 70],
       [92, 73, 46, 32, 65, 87]])

If you have to use np.rot90, which works only on the first two axes, we need to use transpose twice, like so -

rot_arr = np.rot90(M.reshape(m//2,2,n//2,2).transpose(1,3,0,2),1)
out = rot_arr.transpose(2,0,3,1).reshape(m,n)
Divakar
  • 218,885
  • 19
  • 262
  • 358
  • I'm finding it extremely difficult to apply this to other angles, such as 180, 270 etc. – user1658296 Oct 25 '16 at 11:23
  • @user1658296 Seems like there was a bug. Should be fixed in the edits just done. – Divakar Oct 25 '16 at 11:42
  • Thanks, this is great, however, I am battling to see how this might generalize for m == 3x3 or 11x11, not just 2x2. Having to calculate the transpose axes here gets quite tricky. – user1658296 Oct 25 '16 at 11:56
  • 1
    @user1658296 I would think you just need to change all 2's in `reshape(m//2,2,n//2,2)` to those new numbers. – Divakar Oct 25 '16 at 11:57