I have to find the maximum value of a numpy array ignoring the diagonal elements.
np.amax() provides ways to find it ignoring specific axes. How can I achieve the same ignoring all the diagonal elements?
I have to find the maximum value of a numpy array ignoring the diagonal elements.
np.amax() provides ways to find it ignoring specific axes. How can I achieve the same ignoring all the diagonal elements?
You could use a mask
mask = np.ones(a.shape, dtype=bool)
np.fill_diagonal(mask, 0)
max_value = a[mask].max()
where a
is the matrix you want to find the max of. The mask selects the off-diagonal elements, so a[mask]
will be a long vector of all the off-diagonal elements. Then you just take the max.
Or, if you don't mind modifying the original array
np.fill_diagonal(a, -np.inf)
max_value = a.max()
Of course, you can always make a copy and then do the above without modifying the original. Also, this is assuming that a
is some floating point format.
Another possibility is to use NumPy's as_strided
to push the diagonal to the first column and then slice it off:
In [1]: import numpy as np
In [2]: from numpy.lib.stride_tricks import as_strided
In [3]: b = np.arange(0,25,1).reshape((5,5))
In [4]: b
Out[4]: array([[ 0, 1, 2, 3, 4],
[ 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14],
[15, 16, 17, 18, 19],
[20, 21, 22, 23, 24]])
In [5]: n = b.shape[0]
In [6]: np.max(as_strided(b, (n-1,n+1), (b.itemsize*(n+1), b.itemsize))[:,1:])
Out[6]: 23
Where the argument to np.max
is the shifted view on b
:
In [7]: as_strided(b, (n-1,n+1), (b.itemsize*(n+1), b.itemsize))
Out[7]: array([[ 0, 1, 2, 3, 4, 5],
[ 6, 7, 8, 9, 10, 11],
[12, 13, 14, 15, 16, 17],
[18, 19, 20, 21, 22, 23]])
so that:
In [8]: as_strided(b, (n-1,n+1), (b.itemsize*(n+1), b.itemsize))[:,1:]
Out[8]: array([[ 1, 2, 3, 4, 5],
[ 7, 8, 9, 10, 11],
[13, 14, 15, 16, 17],
[19, 20, 21, 22, 23]])
This should work
>>> import numpy as np
>>> import numpy.random
# create sample matrix
>>> a = numpy.random.randint(10,size=(8,8))
>>> a[0,0] = 100
>>> a
array([[100, 8, 6, 5, 5, 7, 4, 5],
[4, 6, 1, 7, 4, 5, 8, 5],
[0, 2, 0, 7, 4, 2, 7, 9],
[5, 7, 5, 9, 8, 3, 2, 8],
[2, 1, 3, 4, 0, 7, 8, 1],
[6, 6, 7, 6, 0, 6, 6, 8],
[6, 0, 1, 9, 7, 7, 9, 3],
[0, 5, 5, 5, 1, 5, 4, 4]])
# create mask
>>> mask = np.ones((8,8))
>>> mask = (mask - np.diag(np.ones(8))).astype(np.bool)
>>> mask
array([[False, True, True, True, True, True, True, True],
[ True, False, True, True, True, True, True, True],
[ True, True, False, True, True, True, True, True],
[ True, True, True, False, True, True, True, True],
[ True, True, True, True, False, True, True, True],
[ True, True, True, True, True, False, True, True],
[ True, True, True, True, True, True, False, True],
[ True, True, True, True, True, True, True, False]], dtype=bool)
# calculate the maximum
>>> np.amax(a[mask])
9