Подтвердить что ты не робот

Поиск ближайшего значения и возврат индекса массива в Python

Я нашел этот пост: Python: поиск элемента в массиве

и о возврате индекса массива путем сопоставления значений.

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

Каким будет самый быстрый способ сделать это?

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

[~,idx] = min(abs(A - target))

Это код Matlab, но я новичок в Python, поэтому я думаю, есть ли быстрый способ сделать это в Python?

Большое вам спасибо за вашу помощь!

4b9b3361

Ответ 1

Это похоже на использование bisect_left, но это позволит вам передать массив целей

def find_closest(A, target):
    #A must be sorted
    idx = A.searchsorted(target)
    idx = np.clip(idx, 1, len(A)-1)
    left = A[idx-1]
    right = A[idx]
    idx -= target - left < right - target
    return idx

Некоторое объяснение:

Сначала общий случай: idx = A.searchsorted(target) возвращает индекс для каждого target, так что target находится между A[index - 1] и A[index]. Я называю эти left и right, поэтому мы знаем, что left < target <= right. target - left < right - target True (или 1), когда цель ближе к left и False (или 0), когда цель ближе к right.

Теперь особый случай: когда target меньше всех элементов A, idx = 0. idx = np.clip(idx, 1, len(A)-1) заменяет все значения idx < 1 с 1, поэтому idx=1. В этом случае left = A[0], right = A[1] и мы знаем, что target <= left <= right. Поэтому мы знаем, что target - left <= 0 и right - target >= 0, поэтому target - left < right - target есть True, если target == left == right и idx - True = 0.

Существует еще один частный случай, если target больше всех элементов A, в этом случае idx = A.searchsorted(target) и np.clip(idx, 1, len(A)-1) заменяет len(A) на len(A) - 1, поэтому idx=len(A) -1 и target - left < right - target заканчивается up False, поэтому idx возвращает len(A) -1. Я позволю вам работать, хотя логика сама по себе.

Например:

In [163]: A = np.arange(0, 20.)

In [164]: target = np.array([-2, 100., 2., 2.4, 2.5, 2.6])

In [165]: find_closest(A, target)
Out[165]: array([ 0, 19,  2,  2,  3,  3])

Ответ 2

Соответствующий код Numpy почти тот же, за исключением того, что вы используете numpy.argmin, чтобы найти минимальный индекс.

idx = numpy.argmin(numpy.abs(A - target))

Ответ 3

Протестировано и приурочено к двум решениям:

idx = np.searchsorted(sw, sCut)

и

idx = np.argmin(np.abs(sw - sCut))

для вычисления в дорогостоящем способе. время было 113 для вычисления со вторым решением и 132 для вычисления с первым.

Ответ 5

Возможное решение:

>>> a = [1.0, 3.2, -2.5, -3.1]
>>> i = -1.5
>>> diff = [(abs(i - x),idx) for (idx,x) in enumerate(a)]
>>> diff
[(2.5, 0), (4.7, 1), (1.0, 2), (1.6, 3)]
>>> diff.sort()
>>> diff
[(1.0, 2), (1.6, 3), (2.5, 0), (4.7, 1)]

У вас будет индекс ближайшего значения в diff [0] [1]

Ответ 6

def finder(myList, target)
    diff = ''
    index = None
    for i,num in enumerate(myList):
        if abs(target - num) < diff:
            diff = abs(target - num)
            index = i
    return index

Надеюсь, что это поможет

ИЗМЕНИТЬ

Если вам нужен один лайнер, вам может понравиться это лучше:

min(L, key=lambda x: abs(target-x))