2012-01-18 59 views
31

tôi tìm thấy bài đăng này: Python: finding an element in an arrayTìm giá trị gần nhất và trả lại chỉ số của mảng bằng Python

và nó về trả lại chỉ số của mảng thông qua phù hợp với các giá trị.

Mặt khác, điều tôi đang nghĩ là làm tương tự nhưng khác nhau. Tôi muốn tìm giá trị gần nhất cho giá trị đích. Ví dụ tôi đang tìm kiếm 4,2 nhưng tôi biết trong mảng không có 4,2 nhưng tôi muốn trả về chỉ số của giá trị 4.1 thay vì 4.4.

Cách nhanh nhất để làm điều đó là gì?

Tôi đang nghĩ đến việc làm theo cách cũ như cách tôi sử dụng để làm điều đó với Matlab, đang sử dụng mảng A, nơi tôi muốn lấy chỉ mục từ để trừ giá trị đích và tận dụng nó, sau đó chọn min. Một cái gì đó như thế này: -

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

Đó là mã Matlab nhưng tôi là newbie trong Python vì vậy tôi nghĩ, có cách nào nhanh để thực hiện nó bằng Python không?

Cảm ơn bạn rất nhiều vì sự giúp đỡ của bạn!

+0

http://stackoverflow.com/questions/2566412/find-nearest-value-in-numpy-array và http://stackoverflow.com/questions/6065697/python-numpy-quickly-find-the-index -in-an-mảng-gần-với-một-giá trị có thể hữu ích. – DSM

Trả lời

30

này cũng tương tự như sử dụng bisect_left, nhưng nó sẽ cho phép bạn vượt qua trong một loạt các mục tiêu

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 

một số giải thích:

Đầu tiên là trường hợp chung: idx = A.searchsorted(target) trả về một chỉ số cho mỗi targettarget là giữa A[index - 1]A[index]. Tôi gọi những số này là leftright để chúng tôi biết rằng left < target <= right. target - left < right - targetTrue (hoặc 1) khi mục tiêu gần hơn với leftFalse (hoặc 0) khi mục tiêu gần hơn với right.

Hiện trường hợp đặc biệt: khi target nhỏ hơn tất cả các thành phần của A, idx = 0. idx = np.clip(idx, 1, len(A)-1) thay thế tất cả các giá trị của idx < 1 bằng 1, vì vậy idx=1. Trong trường hợp này là left = A[0], right = A[1] và chúng tôi biết rằng target <= left <= right.Do đó, chúng tôi biết rằng target - left <= 0right - target >= 0 vì vậy target - left < right - targetTrue trừ khi target == left == rightidx - True = 0.

Có một trường hợp đặc biệt nếu target lớn hơn tất cả các yếu tố của A, Trong trường hợp đó idx = A.searchsorted(target)np.clip(idx, 1, len(A)-1) thay thế len(A) với len(A) - 1 nên idx=len(A) -1target - left < right - target kết thúc lên False trở nên idx len(A) -1. Tôi sẽ cho phép bạn làm việc mặc dù logic của riêng bạn.

Ví dụ:

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

Cảm ơn bạn rất nhiều @Bago! Tôi đang cố gắng để hiểu các mã và tôi đang gặp vấn đề với phần 'idx - = target - left

+0

Hoàn toàn hiểu được! Mã tuyệt vời! Đôi ngón tay cái lên. Cảm ơn @Bago! –

30

Mã Numpy tương ứng gần như giống nhau, ngoại trừ bạn sử dụng numpy.argmin để tìm chỉ mục tối thiểu.

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

'numpy.searchsorted' cũng có ích (và hiệu quả hơn) nếu mảng đầu vào được sắp xếp theo thứ tự sắp xếp. –

+0

OP không xác định cụ thể nhưng tôi nghĩ tôi muốn chỉ ra rằng nếu 'A = [4.1, 4.4, 5, 4.1]' và 'target = 4.2'. Mã này sẽ chỉ trả về 'idx = 0' không phải' idx = [0, 3] '. Chỉ có sự truy đòi lặp lại thông qua 'A' so sánh từng giá trị với giá trị tại' idx = 0', để xác định xem có giá trị nào khác không? – sgallen

+0

@sgallen: Mã Matlab OP được đăng cho 'idx = 1' (chỉ mục Matlab là 1-based), vì vậy tôi đoán những người khác không cần thiết. – 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 

Hope this helps

EDIT:

Nếu bạn muốn một lớp lót, sau đó bạn có thể muốn này tốt hơn:

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

thể giải pháp:

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

Bạn sẽ có các chỉ số của giá trị gần nhất trong diff [0] [1]

4

Tested và đúng lúc hai giải pháp:

idx = np.searchsorted(sw, sCut) 

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

cho tính toán trong một thời gian phương pháp đắt tiền. thời gian là 113 để tính toán với giải pháp thứ hai132 để tính toán với số đầu tiên.

5

Vâng, hơn 2 năm đã trôi qua và tôi đã tìm thấy một thi rất đơn giản từ URL này trên thực tế: Find nearest value in numpy array

Việc thực hiện là:

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

Cheers !!

Các vấn đề liên quan