1

I've got a 4x3 matrix and I need to reshape it to a 2x6 matrix with a specific order:

Initial : |1 5 9| |2 6 10| |3 7 11| |4 8 12|

Wanted : |1 2 5 6 9 10| |3 4 7 8 11 12|

I tried tu use numpy but the order was not what I expected :

import numpy as np
a=np.array([[1,5,9],[2,6,10],[3,17,11],[4,8,12]])
b=a.reshape(2,6)
print(a)
print(b)
ITE
  • 67
  • 7
  • Did the posted solution work for you? Consider accepting it? More info on what it means to accept and how to - https://stackoverflow.com/help/someone-answers – Divakar May 19 '19 at 05:00

1 Answers1

2

Reshape, permute and reshape -

In [51]: n = 2 # no. of rows to select from input to form each row of output

In [52]: a.reshape(-1,n,a.shape[1]).swapaxes(1,2).reshape(-1,n*a.shape[1])
Out[52]: 
array([[ 1,  2,  5,  6,  9, 10],
       [ 3,  4, 17,  8, 11, 12]])

Sort of an explanation :

  1. Cut along the first axis to end up with 3D array such that we select n along the second one. Swap this second axis with the last(third) axis, so that we push back that second one to the end.

  2. Reshape to 2D to merge the last two axes. That's our output!

For more in-depth info, please refer to the linked Q&A.


If we are given the number of rows in output -

In [54]: nrows = 2 # number of rows in output

In [55]: a.reshape(nrows,-1,a.shape[1]).swapaxes(1,2).reshape(nrows,-1)
Out[55]: 
array([[ 1,  2,  5,  6,  9, 10],
       [ 3,  4, 17,  8, 11, 12]])
Divakar
  • 218,885
  • 19
  • 262
  • 358
  • Can you avoid the `swapaxes` with `order='F'` for the final reshape? `a.reshape(-1,n,a.shape[1]).reshape(-1,n*a.shape[1], order='F')` – user3483203 May 13 '19 at 18:50
  • @user3483203 Nope, we can't. That ravel('F') changes the entire order. – Divakar May 13 '19 at 18:51
  • Great! can you explain please because I want to tranpose your solution to a 8x3 => 2x12 Matrix. [[ 1 9 17] [ 2 10 18] [ 3 11 19] [ 4 12 20] [ 5 13 21] [ 6 14 22] [ 7 15 23] [ 8 16 24]] => [[ 1 9 17 2 10 18 3 11 19 4 12 20] [ 5 13 21 6 14 22 7 15 23 8 16 24]] – ITE May 13 '19 at 18:51
  • @Divakar, I'm sorry missed you link! – ITE May 13 '19 at 18:56
  • @Divakar, got it : import numpy as np a=np.array([[1,9,17],[2,10,18],[3,11,19],[4,12,20],[5,13,21],[6,14,22],[7,15,23],[8,16,24]]) b=a.reshape(-1,4,a.shape[1]).swapaxes(1,2).reshape(-1,4*a.shape[1]) print(a) print(b) – ITE May 13 '19 at 19:05
  • @user3483203 That works! Consider positing that one. I am skeptical about using ravel('F') though for memory and perf. I need to test out on that to actual make any conclusions though. – Divakar May 13 '19 at 19:18
  • I had assumed (incorrectly I think) that swap axes was going to be more overhead than the different re-ordering. I did some timing on larger arrays and the swapaxes always seems to be faster. – user3483203 May 13 '19 at 19:21
  • @user3483203 Which makes sense. `Ravel('F')` changes orders across all axes. So, basically it's `transpose(2,1,0)` and then reshape, while we can simply do - `swapaxes(1,2)` here i.e. re-order only 2 axes. To time it out, consider a 3D array and time - `a.transpose(2,1,0).copy()` and `a.swapaxes(1,2).copy()`. – Divakar May 13 '19 at 19:26