2015-04-01 3 views
7

Мне нужно найти максимальное значение массива numpy, игнорируя диагональные элементы.Minimum of Numpy Array Игнорирование диагонали

np.amax() предоставляет способы, чтобы найти его, игнорируя конкретные оси. Как я могу добиться того же игнорирования всех диагональных элементов?

ответ

13

Вы можете использовать маску

mask = np.ones(a.shape, dtype=bool) 
np.fill_diagonal(mask, 0) 
max_value = a[mask].max() 

где a матрица вы хотите, чтобы найти макс. Маска выбирает недиагональные элементы, поэтому a[mask] будет длинным вектором всех недиагональных элементов. Тогда вы просто возьмете максимум.

Или, если вы не возражаете, модифицируя исходный массив

np.fill_diagonal(a, -np.inf) 
max_value = a.max() 

Конечно, вы всегда можете сделать копию, а затем сделать выше, не изменяя оригинал. Кроме того, предполагается, что a - это формат с плавающей запятой.

1

Это должно работать

>>> 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 
5

Другая возможность заключается в использовании NumPy-х as_strided подталкивать по диагонали к первому столбцу, а затем нарезать его:

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 

Если аргумент np.max является смещенной вид на 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]]) 

:

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]]) 
+1

Вау, это ' это здорово. Вероятно, быстрее, чем использование маски для больших массивов. – hunse