web-dev-qa-db-fra.com

Recherche de la valeur la plus proche et retourne l'index du tableau en Python

J'ai trouvé ce post: Python: trouver un élément dans un tableau

et il s'agit de renvoyer l'index d'un tableau en faisant correspondre les valeurs.

D'autre part, ce que je pense faire est similaire mais différent. Je voudrais trouver la valeur la plus proche pour la valeur cible. Par exemple, je cherche 4.2 mais je sais que dans le tableau il n’existe pas de 4.2 mais je veux renvoyer l’indice de la valeur 4.1 au lieu de 4.4.

Quel serait le moyen le plus rapide de le faire?

Je pense le faire à l'ancienne, comme je le faisais auparavant avec Matlab, qui utilise le tableau A où je veux obtenir l'index de moins la valeur cible et en prendre l'absolu, puis sélectionner le minimum. Quelque chose comme ça:-

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

C'est du code Matlab mais je suis débutant en Python, donc je me demande s'il existe un moyen rapide de le faire en Python?

Je vous remercie beaucoup pour votre aide!

33
Harry MacDowel

Ceci est similaire à l'utilisation de bisect_left, mais cela vous permettra de passer dans un tableau de cibles 

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

Quelques explications:

D'abord le cas général: idx = A.searchsorted(target) renvoie un index pour chaque target tel que target soit compris entre A[index - 1] et A[index]. J'appelle ces left et right afin que nous sachions que left < target <= right. target - left < right - target est True (ou 1) lorsque la cible est plus proche de left et False (ou 0) lorsque la cible est plus proche de right.

Maintenant, le cas spécial: quand target est inférieur à tous les éléments de A, idx = 0. idx = np.clip(idx, 1, len(A)-1) remplace toutes les valeurs de idx <1 par 1, donc idx=1. Dans ce cas, left = A[0], right = A[1] et nous savons que target <= left <= right. Nous savons donc que target - left <= 0 et right - target >= 0 donc target - left < right - target est True à moins que target == left == right et idx - True = 0.

Il existe un autre cas particulier si target est supérieur à tous les éléments de A. Dans ce cas, idx = A.searchsorted(target) et np.clip(idx, 1, len(A)-1) remplacent len(A) par len(A) - 1 afin que idx=len(A) -1 et target - left < right - target aboutissent à False alors idx renvoie len(A) -1. Je vous laisserai travailler à votre guise.

Par exemple:

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])
31
Bi Rico

Le code Numpy correspondant est presque identique, sauf que vous utilisez numpy.argmin pour trouver l'index minimum.

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

Eh bien, plus de 2 ans se sont écoulés et j'ai trouvé une implémentation très simple à partir de cette URL: Trouver la valeur la plus proche dans un tableau numpy

La mise en œuvre est:

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

À votre santé!! 

6
Harry MacDowel

Testé et chronométré deux solutions:

idx = np.searchsorted(sw, sCut)

et

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

pour le calcul dans une méthode coûteuse en temps. le timing était de 113s pour le calcul avec la deuxième solution , et 132s pour le calcul avec la première

4
octoback

Solution possible:

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

Vous aurez l'indice de la valeur la plus proche en diff [0] [1]

2
Maciek
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

J'espère que cela t'aides

MODIFIER:

Si vous souhaitez un one-liner, alors vous préférerez peut-être ceci:

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