Найти ближайшее значение в массиве NumPy - PullRequest
277 голосов
/ 02 апреля 2010

Есть ли "тупой" способ, например, функция, чтобы найти ближайшее значение в массиве?

Пример:

np.find_nearest( array, value )

Ответы [ 16 ]

3 голосов
/ 12 сентября 2017

Вот быстрая векторизованная версия решения @ Dimitri, если у вас есть много values для поиска (values может быть многомерным массивом):

#`values` should be sorted
def get_closest(array, values):
    #make sure array is a numpy array
    array = np.array(array)

    # get insert positions
    idxs = np.searchsorted(array, values, side="left")

    # find indexes where previous index is closer
    prev_idx_is_less = ((idxs == len(array))|(np.fabs(values - array[np.maximum(idxs-1, 0)]) < np.fabs(values - array[np.minimum(idxs, len(array)-1)])))
    idxs[prev_idx_is_less] -= 1

    return array[idxs]

Тесты

> в 100 раз быстрее, чем использование цикла for с решением @ Demitri`

>>> %timeit ar=get_closest(np.linspace(1, 1000, 100), np.random.randint(0, 1050, (1000, 1000)))
139 ms ± 4.04 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

>>> %timeit ar=[find_nearest(np.linspace(1, 1000, 100), value) for value in np.random.randint(0, 1050, 1000*1000)]
took 21.4 seconds
1 голос
/ 18 мая 2018

Все ответы полезны для сбора информации для написания эффективного кода. Тем не менее, я написал небольшой скрипт на Python для оптимизации под различные случаи. Это будет лучший случай, если предоставленный массив отсортирован. При поиске по индексу ближайшей точки заданного значения модуль bisect наиболее эффективен по времени. Когда при одном поиске индексы соответствуют массиву, numpy searchsorted наиболее эффективен.

import numpy as np
import bisect
xarr = np.random.rand(int(1e7))

srt_ind = xarr.argsort()
xar = xarr.copy()[srt_ind]
xlist = xar.tolist()
bisect.bisect_left(xlist, 0.3)

В [63]:% time bisect.bisect_left (xlist, 0,3) Время процессора: пользователь 0 нс, sys: 0 нс, всего: 0 нс Время стены: 22,2 мкс

np.searchsorted(xar, 0.3, side="left")

В [64]:% time np.searchsorted (xar, 0.3, side = "left") Время процессора: пользователь 0 нс, sys: 0 нс, всего: 0 нс Время выдержки: 98,9 мкс

randpts = np.random.rand(1000)
np.searchsorted(xar, randpts, side="left")

% time np.searchsorted (xar, randpts, side = "left") Время процессора: пользовательский 4 мс, sys: 0 нс, всего: 4 мс Время стены: 1,2 мс

Если мы следуем правилу мультипликации, тогда numpy должен занять ~ 100 мс, что означает ~ 83X быстрее.

1 голос
/ 31 января 2017

Я думаю, что самый питонический способ будет:

 num = 65 # Input number
 array = n.random.random((10))*100 # Given array 
 nearest_idx = n.where(abs(array-num)==abs(array-num).min())[0] # If you want the index of the element of array (array) nearest to the the given number (num)
 nearest_val = array[abs(array-num)==abs(array-num).min()] # If you directly want the element of array (array) nearest to the given number (num)

Это основной код. Вы можете использовать его как функцию, если хотите

0 голосов
/ 25 июня 2019

Для массива 2d, чтобы определить позицию i, j ближайшего элемента:

import numpy as np
def find_nearest(a, a0):
    idx = (np.abs(a - a0)).argmin()
    w = a.shape[1]
    i = idx // w
    j = idx - i * w
    return a[i,j], i, j
0 голосов
/ 16 декабря 2018

Может быть полезно для ndarrays:

def find_nearest(X, value):
    return X[np.unravel_index(np.argmin(np.abs(X - value)), X.shape)]
0 голосов
/ 08 сентября 2018
import numpy as np
def find_nearest(array, value):
    array = np.array(array)
    z=np.abs(array-value)
    y= np.where(z == z.min())
    m=np.array(y)
    x=m[0,0]
    y=m[1,0]
    near_value=array[x,y]

    return near_value

array =np.array([[60,200,30],[3,30,50],[20,1,-50],[20,-500,11]])
print(array)
value = 0
print(find_nearest(array, value))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...