Numpy: argmax over multiple axes without loop
You could do something like this -
# Reshape input array to a 2D array with rows being kept as with original array.
# Then, get idnices of max values along the columns.
max_idx = A.reshape(A.shape[0],-1).argmax(1)
# Get unravel indices corresponding to original shape of A
maxpos_vect = np.column_stack(np.unravel_index(max_idx, A[0,:,:].shape))
Sample run -
In [214]: # Input array
...: A = np.random.rand(5,4,3,7,8)
In [215]: # Setup output array and use original loopy code
...: maxpos=np.empty(shape=(5,4)) # 4 because ndims in A is 5
...: for n in range(0, 5):
...: maxpos[n,:]=np.unravel_index(np.argmax(A[n,:,:,:,:]), A[n,:,:,:,:].shape)
...:
In [216]: # Proposed approach
...: max_idx = A.reshape(A.shape[0],-1).argmax(1)
...: maxpos_vect = np.column_stack(np.unravel_index(max_idx, A[0,:,:].shape))
...:
In [219]: # Verify results
...: np.array_equal(maxpos.astype(int),maxpos_vect)
Out[219]: True
Generalize to n-dim array
We could generalize to solve for n-dim array to get argmax
for last N
axes combined with something like this -
def argmax_lastNaxes(A, N):
s = A.shape
new_shp = s[:-N] + (np.prod(s[-N:]),)
max_idx = A.reshape(new_shp).argmax(-1)
return np.unravel_index(max_idx, s[-N:])
The result would a tuple of arrays of indices. If you need the final output as an array, we can use np.stack
or np.concatenate
.