bio
bio

Reputation: 511

Numpy normalize multi dim (>=3) array

I have a 5 dim array (comes from binning operations) and would like to have it normed (sum == 1 for the last dimension).

I thought I found the answer here but it says: ValueError: Found array with dim 5. the normalize function expected <= 2.

I achieve the result with 5 nested loops, like:

 for en in range(en_bin.nb):
    for zd in range(zd_bin.nb):
        for az in range(az_bin.nb):
            for oa in range(oa_bin.nb):
                # reduce fifth dimension (en reco) for normalization
                b = np.sum(a[en][zd][az][oa])
                for er in range(er_bin.nb):
                    a[en][zd][az][oa][er] /= b

but I want to vectorise operations.

For example:

In [18]: a.shape
Out[18]: (3, 1, 1, 2, 4)
In [20]: b.shape
Out[20]: (3, 1, 1, 2)

In [22]: a
Out[22]:
array([[[[[ 0.90290316,  0.00953237,  0.57925688,  0.65402645],
      [ 0.68826638,  0.04982717,  0.30458093,  0.0025204 ]]]],



   [[[[ 0.7973917 ,  0.93050739,  0.79963614,  0.75142376],
      [ 0.50401287,  0.81916812,  0.23491561,  0.77206141]]]],



   [[[[ 0.44507296,  0.06625994,  0.6196917 ,  0.6808444 ],
      [ 0.8199077 ,  0.02179789,  0.24627425,  0.43382448]]]]])

In [23]: b
Out[23]:
array([[[[ 2.14571886,  1.04519487]]],


   [[[ 3.27895899,  2.33015801]]],


   [[[ 1.81186899,  1.52180432]]]])

Upvotes: 3

Views: 3095

Answers (1)

Divakar
Divakar

Reputation: 221574

Sum along the last axis by listing axis=-1 with numpy.sum, keeping dimensions and then simply divide by the array itself, thus bringing in NumPy broadcasting -

a/a.sum(axis=-1,keepdims=True)

This should be applicable for ndarrays of generic number of dimensions.

Alternatively, we could sum with axis-reduction and then add a new axis with None/np.newaxis to match up with the input array shape and then divide -

a/(a.sum(axis=-1)[...,None])

Upvotes: 4

Related Questions