2012-01-18 51 views
31

me encontré con este post: Python: finding an element in an arrayEncontrar el valor más cercano y volver al índice de matriz en Python

Y se trata de devolver el índice de un array a través de coincidencia de los valores.

Por otro lado, lo que estoy pensando hacer es similar pero diferente. Me gustaría encontrar el valor más cercano para el valor objetivo. Por ejemplo, estoy buscando 4.2 pero sé que en la matriz no hay 4.2, pero quiero devolver el índice del valor 4.1 en lugar de 4.4.

¿Cuál sería la forma más rápida de hacerlo?

Estoy pensando en hacerlo a la vieja usanza, como solía hacerlo con Matlab, que está usando la matriz A donde quiero obtener el índice de menos el valor objetivo y tomar el absoluto, luego selecciona el min. Algo como esto: -

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

Ese es el código Matlab pero soy novato en Python, así que estoy pensando, ¿hay una forma rápida de hacerlo en Python?

¡Muchas gracias por su ayuda!

+0

http://stackoverflow.com/questions/2566412/find-nearest-value-in-numpy-array y http://stackoverflow.com/questions/6065697/python-numpy-quickly-find-the-index -en-un-conjunto-más cercano-a-algún-valor podría ser útil. – DSM

Respuesta

30

Esto es similar al uso de bisect_left, pero que va a permitir que usted pueda pasar en una serie de objetivos

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 

Algunos explicación:

primer lugar el caso general: idx = A.searchsorted(target) devuelve un índice para cada target tal que target es entre A[index - 1] y A[index]. Llamo a estos left y right por lo que sabemos que left < target <= right. target - left < right - target es True (o 1) cuando el objetivo está más cerca de left y False (o 0) cuando el objetivo está más cerca de right.

Ahora el caso especial: cuando target es menor que todos los elementos de A, idx = 0. idx = np.clip(idx, 1, len(A)-1) reemplaza todos los valores de idx < 1 con 1, entonces idx=1. En este caso left = A[0], right = A[1] y sabemos que target <= left <= right.Por lo tanto, sabemos que target - left <= 0 y right - target >= 0 así que target - left < right - target es True a menos que target == left == right y idx - True = 0.

No es otro caso especial si target es mayor que todos los elementos de A, en ese caso idx = A.searchsorted(target) y np.clip(idx, 1, len(A)-1) reemplaza len(A) con len(A) - 1 por lo idx=len(A) -1 y target - left < right - target termina False vuelve tan IDX len(A) -1. Te dejaré trabajar por tu propia lógica.

Por ejemplo:

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]) 
+0

Muchas gracias @Bago! Intento entender los códigos y tengo problemas con la parte 'idx - = target - left

+0

Totally got it! ¡Grandes códigos! Doble pulgares arriba. Gracias @Bago! –

30

El código Numpy correspondiente es casi el mismo, excepto que usa numpy.argmin para encontrar el índice mínimo.

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

'numpy.searchsorted' también es útil (y más eficiente) si la matriz de entrada está ordenada. –

+0

OP no lo especificó específicamente, pero pensé que lo señalaría si 'A = [4.1, 4.4, 5, 4.1]' y 'objetivo = 4.2'. Este código solo devolverá 'idx = 0' no' idx = [0, 3] '. ¿El único recurso es retroceder a través de 'A' comparando cada valor con el valor en' idx = 0', para determinar si hay otros? – sgallen

+0

@sgallen: El código OP de Matlab publicado da 'idx = 1' (el índice de Matlab está basado en 1), así que supongo que los demás no son necesarios. – kennytm

0
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 

Esperanza esto ayuda

EDITAR:

Si desea una sola línea, entonces te guste esto mejor:

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

Posible solución:

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

Vas a tener el índice de valor más cercano en dif [0] [1]

4

probado y cronometradas dos soluciones:

idx = np.searchsorted(sw, sCut) 

y

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

para el cálculo en un método caro momento. el tiempo fue 113s para el cálculo con la segunda solución, y 132s para el cálculo con el primero.

5

Bueno, más de 2 años han pasado y he encontrado una aplicación muy sencilla de esta URL, de hecho: Find nearest value in numpy array

La aplicación es:

def getnearpos(array,value): 
    idx = (np.abs(array-value)).argmin() 
    return idx 

Saludos !!

Cuestiones relacionadas