Home > OS >  NumPy: 2-D array tiled, converted to a 1-D array, and have to become a 2-D array again
NumPy: 2-D array tiled, converted to a 1-D array, and have to become a 2-D array again

Time:06-06

Ok, I am no an expert in numpy, so sorry if the answer is obvious, but this has been bugging me off for a few days now, so I have no other option than asking here. So, here is the input array I have:

a = np.array([
    [0, 0, 1, 3, 4,  5,  12, 0, 0,  0, 0,  0  ],
    [0, 0, 4, 0, 13, 0,  0,  2, 0,  0, 0,  0  ],
    [1, 2, 3, 4, 5,  6,  7,  8, 0,  0, 0,  0  ],
    [5, 4, 9, 0, 3,  0,  7,  2, 0,  0, 0,  0  ],
    [0, 0, 0, 0, 0,  0,  0,  0, 0,  0, 0,  0  ],
    [0, 0, 0, 0, 1,  0,  5,  7, 5,  0, 1,  0  ],
    [0, 0, 0, 0, 0,  5,  12, 3, 0,  4, 12, 3  ],
    [0, 0, 0, 0, 5,  14, 0,  9, 10, 2, 0,  15 ]
])

It needs to be split into tiles with a size of 4x4 (which means 16 elements per tile, you'll see why this is important). I tile it up (using Iosif Doundoulakis's np.reshape() method, explained here, big shoutout):

def tiling(arr):
    # 16 - total number of elements getting into a tile
    # 4 - width of a tile
    # 4 - height of a tile
    b = arr.reshape(arr.shape[0] // 4, 4, arr.shape[1] // 4, 4, 1)
    return b.swapaxes(1, 2)

... and, when I call tiles = tiling(a), I get a similar result:

*I've formatted the output for easier reading, the actual output looks different, but it is organised the same way.

[[
 [
  [[ 0] [ 0] [ 1] [ 3]]
  [[ 0] [ 0] [ 4] [ 0]]
  [[ 1] [ 2] [ 3] [ 4]]
  [[ 5] [ 4] [ 9] [ 0]]
 ]
.... this is one tile, there are 5 more ...
]]

which is exactly what I want my tiles to look like. Then, I flatten the tiled array, so it becomes

[ 0  0  1  3  0  0  4  0  1  2  3  4  5  4  9  0  4  5 12  0 13  0  0  2
  5  6  7  8  3  0  7  2  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  1  0  5  7
  0  5 12  3  5 14  0  9  0  0  0  0  5  0  1  0  0  4 12  3 10  2  0 15]

and every 16 numbers represent a tile. The next step is to pass the flatten array to an external program which returns an array with the same shape - 1 dimensional array. For now, the data is only passed to the external utility and returned by it, so the array keeps it's values.

Knowing the total number of array elements that go into a tile (16), as well as the shape of a tile (4, 4), how can I turn this 1-D array back into tiles and then create a 2-D array from those tiles, which looks like the one from the beginning?

CodePudding user response:

I think this is actually as simple as another swapaxes and reshape. First, you'll need to call swapaxes(1, 2) again to undo the last call. Then just reshape back to a's shape.

>>> tiles
array([[[[[ 0],
          [ 0],
          [ 1],
          [ 3]],

         [[ 0],
          [ 0],
          [ 4],
          [ 0]],
          ...
          ]]])

>>> tiles.swapaxes(1, 2).reshape(a.shape)
array([[ 0,  0,  1,  3,  4,  5, 12,  0,  0,  0,  0,  0],
       [ 0,  0,  4,  0, 13,  0,  0,  2,  0,  0,  0,  0],
       [ 1,  2,  3,  4,  5,  6,  7,  8,  0,  0,  0,  0],
       [ 5,  4,  9,  0,  3,  0,  7,  2,  0,  0,  0,  0],
       [ 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0],
       [ 0,  0,  0,  0,  1,  0,  5,  7,  5,  0,  1,  0],
       [ 0,  0,  0,  0,  0,  5, 12,  3,  0,  4, 12,  3],
       [ 0,  0,  0,  0,  5, 14,  0,  9, 10,  2,  0, 15]])

If you don't have a.shape, you can probably calculate it with something like (S[0]*S[2], S[1]*S[3]), where S is tiles.shape:

tiles.swapaxes(1, 2).reshape(x.shape[0] * x.shape[2], x.shape[1] * x.shape[3])

CodePudding user response:

I could not understand what you want exactly, but I guess you are searching for something like my previous answer (which get shape = (6, 4 ,4) for your example):

a.reshape(a.shape[0] // 4, 4, -1, 4).swapaxes(1, 2).reshape(a.size // (4 * 4), 4, 4)

You need to reshape the return array to a.size // (4 * 4), 4, 4) (if you sure about the shapes that can be divided by 4 or 16 …), so the tiling function must change to:

def tiling(arr):
    b = arr.reshape(arr.shape[0] // 4, 4, arr.shape[1] // 4, 4, 1)
    return b.swapaxes(1, 2).reshape(arr.size // (4 * 4), 4, 4)
  • Related