Home > Software design >  How do I reduce the shape of my 4-d array to 3-d by merging the elements?
How do I reduce the shape of my 4-d array to 3-d by merging the elements?

Time:12-14

I have the 4-d array with shape (3,32,32,32) of 1bit and I want to reduce it to (3,32,32) with the elements becoming 32bit. The values in the array is 0s and 1s .The numbering in the array is just a way to visualize my question, it represents the nth bit of the resulting segment of 32-bit that I want.

[[[[ 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.,  1.,  1.,  ...,  1.,  1.,  1.],
           [ 1.,  1.,  1.,  ...,  1.,  1.,  1.],
           [ 1.,  1.,  1.,  ...,  1.,  1.,  1.],
           ...,
           [ 1.,  1.,  1.,  ...,  1.,  1.,  1.],
           [ 1.,  1.,  1.,  ...,  1.,  1.,  1.],
           [ 1.,  1.,  1.,  ...,  1.,  1.,  1.]],

          [[ 2.,  2.,  2.,  ...,  2.,  2.,  2.],
           [ 2.,  2.,  2.,  ...,  2.,  2.,  2.],
           [ 2.,  2.,  2.,  ...,  2.,  2.,  2.],
           ...,
           [ 2.,  2.,  2.,  ...,  2.,  2.,  2.],
           [ 2.,  2.,  2.,  ...,  2.,  2.,  2.],
           [ 2.,  2.,  2.,  ...,  2.,  2.,  2.]],

          ...,

          [[29., 29., 29.,  ..., 29., 29., 29.],
           [29., 29., 29.,  ..., 29., 29., 29.],
           [29., 29., 29.,  ..., 29., 29., 29.],
           ...,
           [29., 29., 29.,  ..., 29., 29., 29.],
           [29., 29., 29.,  ..., 29., 29., 29.],
           [29., 29., 29.,  ..., 29., 29., 29.]],

          [[30., 30., 30.,  ..., 30., 30., 30.],
           [30., 30., 30.,  ..., 30., 30., 30.],
           [30., 30., 30.,  ..., 30., 30., 30.],
           ...,
           [30., 30., 30.,  ..., 30., 30., 30.],
           [30., 30., 30.,  ..., 30., 30., 30.],
           [30., 30., 30.,  ..., 30., 30., 30.]],

          [[31., 31., 31.,  ..., 31., 31., 31.],
           [31., 31., 31.,  ..., 31., 31., 31.],
           [31., 31., 31.,  ..., 31., 31., 31.],
           ...,
           [31., 31., 31.,  ..., 31., 31., 31.],
           [31., 31., 31.,  ..., 31., 31., 31.],
           [31., 31., 31.,  ..., 31., 31., 31.]]], #1


         [[[ 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.,  1.,  1.,  ...,  1.,  1.,  1.],
           [ 1.,  1.,  1.,  ...,  1.,  1.,  1.],
           [ 1.,  1.,  1.,  ...,  1.,  1.,  1.],
           ...,
           [ 1.,  1.,  1.,  ...,  1.,  1.,  1.],
           [ 1.,  1.,  1.,  ...,  1.,  1.,  1.],
           [ 1.,  1.,  1.,  ...,  1.,  1.,  1.]],

          [[ 2.,  2.,  2.,  ...,  2.,  2.,  2.],
           [ 2.,  2.,  2.,  ...,  2.,  2.,  2.],
           [ 2.,  2.,  2.,  ...,  2.,  2.,  2.],
           ...,
           [ 2.,  2.,  2.,  ...,  2.,  2.,  2.],
           [ 2.,  2.,  2.,  ...,  2.,  2.,  2.],
           [ 2.,  2.,  2.,  ...,  2.,  2.,  2.]],

          ...,

          [[29., 29., 29.,  ..., 29., 29., 29.],
           [29., 29., 29.,  ..., 29., 29., 29.],
           [29., 29., 29.,  ..., 29., 29., 29.],
           ...,
           [29., 29., 29.,  ..., 29., 29., 29.],
           [29., 29., 29.,  ..., 29., 29., 29.],
           [29., 29., 29.,  ..., 29., 29., 29.]],

          [[30., 30., 30.,  ..., 30., 30., 30.],
           [30., 30., 30.,  ..., 30., 30., 30.],
           [30., 30., 30.,  ..., 30., 30., 30.],
           ...,
           [30., 30., 30.,  ..., 30., 30., 30.],
           [30., 30., 30.,  ..., 30., 30., 30.],
           [30., 30., 30.,  ..., 30., 30., 30.]],

          [[31., 31., 31.,  ..., 31., 31., 31.],
           [31., 31., 31.,  ..., 31., 31., 31.],
           [31., 31., 31.,  ..., 31., 31., 31.],
           ...,
           [31., 31., 31.,  ..., 31., 31., 31.],
           [31., 31., 31.,  ..., 31., 31., 31.],
           [31., 31., 31.,  ..., 31., 31., 31.]]], #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.,  1.,  1.,  ...,  1.,  1.,  1.],
           [ 1.,  1.,  1.,  ...,  1.,  1.,  1.],
           [ 1.,  1.,  1.,  ...,  1.,  1.,  1.],
           ...,
           [ 1.,  1.,  1.,  ...,  1.,  1.,  1.],
           [ 1.,  1.,  1.,  ...,  1.,  1.,  1.],
           [ 1.,  1.,  1.,  ...,  1.,  1.,  1.]],

          [[ 2.,  2.,  2.,  ...,  2.,  2.,  2.],
           [ 2.,  2.,  2.,  ...,  2.,  2.,  2.],
           [ 2.,  2.,  2.,  ...,  2.,  2.,  2.],
           ...,
           [ 2.,  2.,  2.,  ...,  2.,  2.,  2.],
           [ 2.,  2.,  2.,  ...,  2.,  2.,  2.],
           [ 2.,  2.,  2.,  ...,  2.,  2.,  2.]],

          ...,

          [[29., 29., 29.,  ..., 29., 29., 29.],
           [29., 29., 29.,  ..., 29., 29., 29.],
           [29., 29., 29.,  ..., 29., 29., 29.],
           ...,
           [29., 29., 29.,  ..., 29., 29., 29.],
           [29., 29., 29.,  ..., 29., 29., 29.],
           [29., 29., 29.,  ..., 29., 29., 29.]],

          [[30., 30., 30.,  ..., 30., 30., 30.],
           [30., 30., 30.,  ..., 30., 30., 30.],
           [30., 30., 30.,  ..., 30., 30., 30.],
           ...,
           [30., 30., 30.,  ..., 30., 30., 30.],
           [30., 30., 30.,  ..., 30., 30., 30.],
           [30., 30., 30.,  ..., 30., 30., 30.]],

          [[31., 31., 31.,  ..., 31., 31., 31.],
           [31., 31., 31.,  ..., 31., 31., 31.],
           [31., 31., 31.,  ..., 31., 31., 31.],
           ...,
           [31., 31., 31.,  ..., 31., 31., 31.],
           [31., 31., 31.,  ..., 31., 31., 31.],
           [31., 31., 31.,  ..., 31., 31., 31.]]]] #3

Sorry if this is such an obvious question as I am still learning.

I want my resulting array to be of size (3,32,32) with the following arrangements:

 [[[bit0bit1bit2...bit30bit31, bit0bit1bit2...bit30bit31, ..., bit0bit1bit2...bit30bit31],
  [bit0bit1bit2...bit30bit31, bit0bit1bit2...bit30bit31, ..., bit0bit1bit2...bit30bit31],
  ..., 
  [bit0bit1bit2...bit30bit31, bit0bit1bit2...bit30bit31, ..., bit0bit1bit2...bit30bit31],
  [bit0bit1bit2...bit30bit31, bit0bit1bit2...bit30bit31, ..., bit0bit1bit2...bit30bit31]], #1


[[[bit0bit1bit2...bit30bit31, bit0bit1bit2...bit30bit31, ..., bit0bit1bit2...bit30bit31],
  [bit0bit1bit2...bit30bit31, bit0bit1bit2...bit30bit31, ..., bit0bit1bit2...bit30bit31],
  ..., 
  [bit0bit1bit2...bit30bit31, bit0bit1bit2...bit30bit31, ..., bit0bit1bit2...bit30bit31],
  [bit0bit1bit2...bit30bit31, bit0bit1bit2...bit30bit31, ..., bit0bit1bit2...bit30bit31]], #2



[[[bit0bit1bit2...bit30bit31, bit0bit1bit2...bit30bit31, ..., bit0bit1bit2...bit30bit31],
  [bit0bit1bit2...bit30bit31, bit0bit1bit2...bit30bit31, ..., bit0bit1bit2...bit30bit31],
  ..., 
  [bit0bit1bit2...bit30bit31, bit0bit1bit2...bit30bit31, ..., bit0bit1bit2...bit30bit31],
  [bit0bit1bit2...bit30bit31, bit0bit1bit2...bit30bit31, ..., bit0bit1bit2...bit30bit31]]] #3







CodePudding user response:

The fastest way, I think (and also one of the shortest to write, tho not to understand if you are not used to this function) is probably using einsum

import numpy as np
# Just for the example, I build it backward
x = np.random.randint(0,2000000000, (3, 32, 32))
# So x is the result we expect to find. 

# Let build the 3,32,32,32 array of 1/0
bits = np.stack([(x//(2**k))%2 for k in range(32)], axis=1)

# So now, what we want is to create x back from bits
# For that we need a array of multiplicators
coef = np.array([2**k for k in range(32)])

# And now the magic one liner
xx=np.einsum('ijkl,j', bits, coef)

# And the test to check if we found back x
np.abs(xx-x).max()
# 0 

So, one-liner is np.einsum('ijkl,j', bits, [2**k for k in range(32)])

As used here, einsum means that you iterate for all possible values of i, j, k, l (so 4 nested loops, but done efficiently in numpy. Anyway, you need to read all values, so that is a minimum in terms of number of operations). And along the repeated index (here, j), result is the sum of product of values from both array. So here, with ijkl,j, it means

res=np.empty((3,32,32))
for i in range(3):
    for k in range(32):
        for l in range(32):
            res[i,k,l] = 0 
            for j in range(32):
                res[i,k,l]  = bits[i,j,k,l]*coef[j]

But really, really fast. Generally, you can't beat np.einsum.

(Note: I am not sure which bit is the most significant from your point of view. You may need to revert coef. For example, by passing coef[::-1] to einsum)

  • Related