yacola
yacola

Reputation: 3013

Numpy blocks reshaping

I am looking for a way to reshape the following 1d-numpy array:

# dimensions
n = 2 # int : 1 ... N
h = 2 # int : 1 ... N
m = n*(2*h+1)

input_data = np.arange(0,(n*(2*h+1))**2)

The expected output should be reshaped into (2*h+1)**2 blocks of shape (n,n) such as:

input_data.reshape(((2*h+1)**2,n,n))
>>> array([[[ 0  1]
            [ 2  3]]

           [[ 4  5]
            [ 6  7]]
              ...

           [[92 93]
            [94 95]]

           [[96 97]
            [98 99]]]

These blocks finally need to be reshaped into a (m,m) matrix so that they are stacked in rows of 2*h+1 blocks:

>>> array([[ 0,  1,  4,  5,  8,  9, 12, 13, 16, 17],
           [ 2,  3,  6,  7, 10, 11, 14, 15, 18, 19],
                              ...
           [80, 81, 84, 85, 88, 89, 92, 93, 96, 97],
           [82, 83, 86, 87, 90, 91, 94, 95, 98, 99]])

My problem is that I can't seem to find proper axis permutations after the first reshape into (n,n) blocks. I have looked at several answers such as this one but in vain.

As the real dimensions n and h are quite bigger and this operation takes place in an iterative process, I am looking for an efficient reshaping operation.

Upvotes: 1

Views: 185

Answers (1)

Daniel F
Daniel F

Reputation: 14399

I don't think you can do this with reshape and transpose alone (although I'd love to be proven wrong). Using np.block works, but it's a bit messy:

np.block([list(i) for i in input_data.reshape( (2*h+1), (2*h+1), n, n )])

array([[ 0,  1,  4,  5,  8,  9, 12, 13, 16, 17],
       [ 2,  3,  6,  7, 10, 11, 14, 15, 18, 19],
       [20, 21, 24, 25, 28, 29, 32, 33, 36, 37],
       [22, 23, 26, 27, 30, 31, 34, 35, 38, 39],
       [40, 41, 44, 45, 48, 49, 52, 53, 56, 57],
       [42, 43, 46, 47, 50, 51, 54, 55, 58, 59],
       [60, 61, 64, 65, 68, 69, 72, 73, 76, 77],
       [62, 63, 66, 67, 70, 71, 74, 75, 78, 79],
       [80, 81, 84, 85, 88, 89, 92, 93, 96, 97],
       [82, 83, 86, 87, 90, 91, 94, 95, 98, 99]])

EDIT: Never mind, you can do without np.block:

input_data.reshape( (2*h+1), (2*h+1), n, n).transpose(0, 2, 1, 3).reshape(10, 10)

array([[ 0,  1,  4,  5,  8,  9, 12, 13, 16, 17],
       [ 2,  3,  6,  7, 10, 11, 14, 15, 18, 19],
       [20, 21, 24, 25, 28, 29, 32, 33, 36, 37],
       [22, 23, 26, 27, 30, 31, 34, 35, 38, 39],
       [40, 41, 44, 45, 48, 49, 52, 53, 56, 57],
       [42, 43, 46, 47, 50, 51, 54, 55, 58, 59],
       [60, 61, 64, 65, 68, 69, 72, 73, 76, 77],
       [62, 63, 66, 67, 70, 71, 74, 75, 78, 79],
       [80, 81, 84, 85, 88, 89, 92, 93, 96, 97],
       [82, 83, 86, 87, 90, 91, 94, 95, 98, 99]])

Upvotes: 3

Related Questions