'get maximum of absolute along axis

I have a couple of ndarrays with same shape, and I would like to get one array (of same shape) with the maximum of the absolute values for each element. So I decided to stack all arrays, and then pick the values along the new stacked axis. But how to do this?

Example

Say we have two 1-D arrays with 4 elements each, so my stacked array looks like

>>> stack
array([[ 4,  1,  2,  3],
       [ 0, -5,  6,  7]])

If I would just be interested in the maximum I could just do

>>> numpy.amax(stack, axis=0)
array([4, 1, 6, 7])

But I need to consider negative values as well, so I was going for

>>> ind = numpy.argmax(numpy.absolute(stack), axis=0)
>>> ind
array([0, 1, 1, 1])

So now I have the indices I need, but how to apply this to the stacked array? If I just index stack by ind, numpy is doing something broadcasting stuff I don't need:

>>> stack[ind]
array([[ 4,  1,  2,  3],
       [ 0, -5,  6,  7],
       [ 0, -5,  6,  7],
       [ 0, -5,  6,  7]])

What I want to get is array([4, -5, 6, 7])

Or to ask from a slightly different perspective: How do I get the array numpy.amax(stack, axis=0) based on the indices returned by numpy.argmax(stack, axis=0)?



Solution 1:[1]

If you have 2D numpy ndarray, classical indexing no longer applies. So to achieve what you want, to avoid brodcatsting, you have to index with 2D array too:

>>> stack[[ind,np.arange(stack.shape[1])]]
array([ 4, -5,  6,  7])

Solution 2:[2]

The stacking operation would be inefficient. We can simply use np.where to do the choosing based on the absolute valued comparisons -

In [198]: a
Out[198]: array([4, 1, 2, 3])

In [199]: b
Out[199]: array([ 0, -5,  6,  7])

In [200]: np.where(np.abs(a) > np.abs(b), a, b)
Out[200]: array([ 4, -5,  6,  7])

This works on generic n-dim arrays without any modification.

Solution 3:[3]

For 'normal' Python:

>>> a=[[1,2],[3,4]]
>>> b=[0,1]
>>> [x[y] for x,y in zip(a,b)]
[1, 4]

Perhaps it can be applied to arrays too, I am not familiar enough with Numpy.

Solution 4:[4]

Find array of max and min and combine using where

maxs = np.amax(stack, axis=0)
mins = np.amin(stack, axis=0)
max_abs = np.where(np.abs(maxs) > np.abs(mins), maxs, mins)

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2
Solution 3 tevemadar
Solution 4 Deepak Soni