Finding extremal values in a nd-array
Sometimes, you need to pick up the $N$-th extremal values in a mutli-dimensional matrix.
Let's suppose it is represented as a nd-array (here, I further suppose you are using the numpy library from the python language). Finding extremal values is easy with argmax, argmin or argsort but this function operated on 1d vectors... Juggling around indices is sometimes not such an easy task, but luckily, we have the unravel_index function.
For those in a hurry, one quick application is that given an np.ndarray, it's eeasy to get the index of the maximal value in that array :
import numpy as np
x = np.arange(2*3*4).reshape((4, 3, 2))
x = np.random.permutation(np.arange(2*3*4)).reshape((4, 3, 2))
print ('input ndarray', x)
idx = np.unravel_index(np.argmax(x.ravel()), x.shape)
print ('index of maximal value = ', idx, ' and we verify that ', x[idx], '=', x.max())
Let's unwrap how we found such an easy solution...
Let's first initialize the notebook with all we need, numpy:
import numpy as np
To work out on "real-like" data, let's first define a dummy 3-D array:
x = np.arange(2*3*4).reshape((4, 3, 2))
x = np.random.permutation(np.arange(2*3*4)).reshape((4, 3, 2))
print (x)
We wish to find the indices of the sorted values of this matrix. For this, we will use the np.argsort function which operates on 1-D vectors.
Indeed, we can represent as a 1-d array (a vector):
print (x.ravel())
We may now find the list of indices to sort it:
print (np.argsort(x.ravel()))
And we verify that the entries are indeed sorted:
print (x.ravel()[np.argsort(x.ravel())])
To go back to the coordinates of the initial np.ndarray, we use the unraval_index function:
help(np.unravel_index)
print (np.unravel_index(np.argsort(x.ravel()), x.shape))
Such that we can now sort the whole array from the lowest to highest index. We verify that:
print (x[np.unravel_index(np.argsort(x.ravel()), x.shape)])
Some applications: We can now pick just the datapoints extremal values of interest :
datapoints = 10
print (np.unravel_index(np.argsort(x.ravel())[:datapoints], x.shape))
Let's now try with a more generic example :
x = np.random.rand(4, 3, 2)
print (x)
The indices for the datapoints extremal values of interest are :
print (np.unravel_index(np.argsort(x.ravel())[:datapoints], x.shape))
... which correspond to the minimal values of interest :
print (x[np.unravel_index(np.argsort(x.ravel())[:datapoints], x.shape)])
Note that it is also easy to pick the maximal values :
print (np.unravel_index(np.argsort(-x.ravel())[:datapoints], x.shape))
Another application: Get the index of the maximal value of an array :
idx = np.unravel_index(np.argmax(x.ravel()), x.shape)
print ('index of maximal value = ', idx, ' and we verify that ', x[idx], '=', x.max())