Как получить наивысший элемент по абсолютной величине в матрице numpy?

Вот что я сейчас делаю, это работает, но это немного громоздко:

x = np.matrix([[1, 1], [2, -3]])
xmax = x.flat[abs(x).argmax()]

Ответы

Ответ 1

Значение, которое вы ищете, должно быть либо x.max(), либо x.min(), чтобы вы могли сделать

max(x.min(), x.max(), key=abs)

который похож на решение aestrivex, но, возможно, более читабельным? Обратите внимание, что это вернет минимум в случае, когда x.min() и x.max() имеют одинаковое абсолютное значение, например. -5 и 5. Если у вас есть предпочтение, просто закажите входы на max соответственно.

Ответ 2

Я искал способ получить подписанные значения максимальных абсолютных значений N-мерного массива вдоль указанной оси, с которыми не справляется ни один из этих ответов. Итак, я собрал функцию для этого. Нет promises, но он работает, насколько я его протестировал:

def maxabs(a, axis=None):
    """Return slice of a, keeping only those values that are furthest away
    from 0 along axis"""
    maxa = a.max(axis=axis)
    mina = a.min(axis=axis)
    p = abs(maxa) > abs(mina) # bool, or indices where +ve values win
    n = abs(mina) > abs(maxa) # bool, or indices where -ve values win
    if axis == None:
        if p: return maxa
        else: return mina
    shape = list(a.shape)
    shape.pop(axis)
    out = np.zeros(shape, dtype=a.dtype)
    out[p] = maxa[p]
    out[n] = mina[n]
    return out

Ответ 3

ИЗМЕНИТЬ. Мой ответ не по теме, извините. Как отметил Офион, это вернет индекс, а не значение - вы должны использовать flat с моим "xmax" (который действительно "xmaxInd" ), чтобы получить правильное значение. Ergo Я думаю, что ваше решение лучше всего.


После нескольких экспериментов я понял, что вы можете просто сделать это:

x = np.matrix([[1,1], [2,-3]])
absX = abs(x)
xmax = argmax(absX)

Кажется, что numpy позволяет взять abs, а также argmax матрицы. Как удобно!

timeit проверяет:

def meth1():
    x = np.matrix([[1,1],[2,-3]])
    xmax = x.flat[abs(x).argmax()]

def meth2():
    x = np.matrix([[1,1],[2,-3]])
    xmax = argmax(abs(x))

t1 = timeit.Timer("meth1()","from __main__ import meth1")
t2 = timeit.Timer("meth2()","from __main__ import meth2")

mean(t1.repeat(1,100000)) дает Out[99]: 7.854323148727417 mean(t2.repeat(1,100000)) дает Out[98]: 7.7788529396057129

Итак, meth2() немного быстрее. Возможно, потому что это не связано с вызовом flat.

Ответ 4

Это вычисляет абсолютный максимум, соблюдая произвольный аргумент axis таким же образом, как и сами np.max и np.argmax.

def absmaxND(a, axis=None):
    amax = a.max(axis)
    amin = a.min(axis)
    return np.where(-amin > amax, amin, amax)

Для длинных массивов примерно в 2,5 раза быстрее, чем a.flat[abs(a).argmax()] даже для простого случая axis=None - потому что он не отображает abs() исходного большого массива.

Ответ 5

Единственное, о чем я мог думать, что выглядит еще хуже, это:

xmax=x[np.unravel_index(abs(x).argmax(), x.shape)]

Ответ 6

Я думаю, что это довольно простой способ, который может быть немного лучше, если читаемость кода является вашей главной задачей. Но на самом деле ваш путь столь же изящный.

np.min(x) if np.max(abs(x)) == abs(np.min(x)) else np.max(x)