Поиск ближайшего значения и возврат индекса массива в Python
Я нашел этот пост: Python: поиск элемента в массиве
и о возврате индекса массива путем сопоставления значений.
С другой стороны, то, что я собираюсь сделать, похоже, но отличается. Я хотел бы найти ближайшее значение для целевого значения. Например, я ищу 4.2, но знаю, что в массиве нет 4.2, но я хочу вернуть индекс значения 4.1 вместо 4.4.
Каким будет самый быстрый способ сделать это?
Я собираюсь сделать это по-старому, как то, как я это делал с Matlab, который использует массив A, где я хочу получить индекс от минус целевое значение и принять его абсолютное значение, затем выберите их в. Что-то вроде этого: -
[~,idx] = min(abs(A - target))
Это код Matlab, но я новичок в Python, поэтому я думаю, есть ли быстрый способ сделать это в Python?
Большое вам спасибо за вашу помощь!
Ответы
Ответ 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 для вычисления с первым.
Ответ 4
Хорошо, прошло более 2 лет, и я нашел очень простую реализацию из этого URL-адреса: Найти ближайшее значение в массиве numpy
Реализация:
def getnearpos(array,value):
idx = (np.abs(array-value)).argmin()
return idx
Ура!!
Ответ 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))