пример - python numpy find element




Найти ближайшее значение в массиве numpy (10)

Вот быстрая векторная версия решения @ 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

Существует ли numpy-thonic способ, например function, чтобы найти ближайшее значение в массиве?

Пример:

np.find_nearest( array, value )

Вот версия с scipy для @Ari Onasafari, ответьте « найти ближайший вектор в массиве векторов »

In [1]: from scipy import spatial

In [2]: import numpy as np

In [3]: A = np.random.random((10,2))*100

In [4]: A
Out[4]:
array([[ 68.83402637,  38.07632221],
       [ 76.84704074,  24.9395109 ],
       [ 16.26715795,  98.52763827],
       [ 70.99411985,  67.31740151],
       [ 71.72452181,  24.13516764],
       [ 17.22707611,  20.65425362],
       [ 43.85122458,  21.50624882],
       [ 76.71987125,  44.95031274],
       [ 63.77341073,  78.87417774],
       [  8.45828909,  30.18426696]])

In [5]: pt = [6, 30]  # <-- the point to find

In [6]: A[spatial.KDTree(A).query(pt)[1]] # <-- the nearest point 
Out[6]: array([  8.45828909,  30.18426696])

#how it works!
In [7]: distance,index = spatial.KDTree(A).query(pt)

In [8]: distance # <-- The distances to the nearest neighbors
Out[8]: 2.4651855048258393

In [9]: index # <-- The locations of the neighbors
Out[9]: 9

#then 
In [10]: A[index]
Out[10]: array([  8.45828909,  30.18426696])

Вот расширение, чтобы найти ближайший вектор в массиве векторов.

import numpy as np

def find_nearest_vector(array, value):
  idx = np.array([np.linalg.norm(x+y) for (x,y) in array-value]).argmin()
  return array[idx]

A = np.random.random((10,2))*100
""" A = array([[ 34.19762933,  43.14534123],
   [ 48.79558706,  47.79243283],
   [ 38.42774411,  84.87155478],
   [ 63.64371943,  50.7722317 ],
   [ 73.56362857,  27.87895698],
   [ 96.67790593,  77.76150486],
   [ 68.86202147,  21.38735169],
   [  5.21796467,  59.17051276],
   [ 82.92389467,  99.90387851],
   [  6.76626539,  30.50661753]])"""
pt = [6, 30]  
print find_nearest_vector(A,pt)
# array([  6.76626539,  30.50661753])

Все ответы полезны для сбора информации для написания эффективного кода. Тем не менее, я написал небольшой скрипт 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) CPU times: user 0 ns, sys: 0 ns, total: 0 ns Настенное время: 22,2 мкс

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

В [64]:% времени np.searchsorted (xar, 0.3, side = "left") CPU times: user 0 ns, sys: 0 ns, total: 0 ns Время на стене: 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 быстрее.


Если вы не хотите использовать numpy, это сделает это:

def find_nearest(array, value):
    n = [abs(i-value) for i in array]
    idx = n.index(min(n))
    return array[idx]

При небольшой модификации ответ выше работает с массивами произвольной размерности (1d, 2d, 3d, ...):

def find_nearest(a, a0):
    "Element in nd array `a` closest to the scalar value `a0`"
    idx = np.abs(a - a0).argmin()
    return a.flat[idx]

Или, написано как одна строка:

a.flat[np.abs(a - a0).argmin()]

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

 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)

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


Если ваш массив отсортирован и очень большой, это гораздо более быстрое решение:

def find_nearest(array,value):
    idx = np.searchsorted(array, value, side="left")
    if idx > 0 and (idx == len(array) or math.fabs(value - array[idx-1]) < math.fabs(value - array[idx])):
        return array[idx-1]
    else:
        return array[idx]

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


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

import numpy as np
def find_nearest(array, value):
    array = np.asarray(array)
    idx = (np.abs(array - value)).argmin()
    return array[idx]

array = np.random.random(10)
print(array)
# [ 0.21069679  0.61290182  0.63425412  0.84635244  0.91599191  0.00213826
#   0.17104965  0.56874386  0.57319379  0.28719469]

value = 0.5

print(find_nearest(array, value))
# 0.568743859261




numpy