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())