Home > Back-end >  How to effienctly divide blocks of numpy array
How to effienctly divide blocks of numpy array

Time:10-27

I dont even know how to phrase what I am trying to do so I'm going straight to a simple example. I have a blocked array that looks something like this:

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

and I want as an output:

np.array([
          [1/9,2/9,0,0],
          [3/9,4/9,0,0],
          [9/9,9/9,0,0],
          [0,0,5/8,6/8],
          [0,0,7/8,8/8],
          [0,0,8/8,8/8]
          ])

Lets view this as two blocks

Block 1

np.array([
         [1,2,0,0],
         [3,4,0,0],
         [9,9,0,0],
         ])

Block 2

np.array([
         [0,0,5,6],
         [0,0,7,8],
         [0,0,8,8]
         ])

I want to normalize by the last row of each block. I.e I want to divide each block by the last row (plus epsilon for stability so the zeros are 0/(0 eps) = 0). I need an efficient way to do this.

My current inefficient solution is to create a new array of the same shape as a where block one in the new array is the last row of the corresponding block in a and the divide. As follows:

norming_indices = np.array([2,2,2,5,5,5])
divisors = a[norming_indices, :]
b = a / (divisors   1e-9)

In this example:

divisors = np.array([
            [9,9,0,0],
            [9,9,0,0],
            [9,9,0,0],
            [0,0,8,8],
            [0,0,8,8],
            [0,0,8,8]
            ])

This like a very inefficient way to do this, does anyone have a better approach?

CodePudding user response:

Reshape to three dimensions, apply the normalization for each block (last row (index 2) of each 3-row-block (step 3), then reshape back to original shape:

b = a.reshape(-1, 3, 4)
b = b / b[:,2::3].max(axis=2,keepdims=True)
b = b.reshape(a.shape)

CodePudding user response:

np.concatenate may help you

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

    b = np.concatenate((a[0:3, :] / (a[2, :]   1e-9),
                        a[3:, :] / (a[5, :]   1e-9)))
    print(b)

Output:

[[0.11111111 0.22222222 0.         0.        ]
 [0.33333333 0.44444444 0.         0.        ]
 [1.         1.         0.         0.        ]
 [0.         0.         0.625      0.75      ]
 [0.         0.         0.875      1.        ]
 [0.         0.         1.         1.        ]]
  • Related