2017-06-13 157 views
1

這裏的目標是速度 - 我試圖擺脫通過有問題的數組循環。但是可以假設這兩個數組是排序的。在兩個numpy數組中找到最接近的值

a = np.arange(10) 
b = np.array([2.3, 3.5, 5.8, 13]) 
c = somefunc(a,b) 

現在somefunc應該找到的a的指數,其在b值最接近太,即

In []: c 
Out[]: array([2, 3or4, 6, 9]) #3 or 4 depending on python2 or 3 

再次,這可能是一個循環中完成,但我尋找的東西快得多。我採取的絕對差值類型的方法,喜歡的東西相當接近:

np.argmin(np.abs(a[:, np.newaxis] - b), axis=0) 

但是,即使這是一個有點慢的很多不必要的減法完成。

+0

我想你可能希望'c'是'array([2,3,6,9])',因爲你在比較'arange(10)',它從0開始。 – Praveen

+0

你是什麼意思是當你說你的'argmin'結果不會給每個'b'值一個索引?它對我來說...... – Praveen

+0

應該不是'[2,4,6,9]'而是? – Divakar

回答

-1

因此,使用從該@Eelco建議,使用searchsorted,我來這是更快與除np.argmin上的矢量更大的數據集以下方法:

def finder(a, b): 
    dup = np.searchsorted(a, b) 
    uni = np.unique(dup) 
    uni = uni[uni < a.shape[0]] 
    ret_b = np.zeros(uni.shape[0]) 
    for idx, val in enumerate(uni): 
     bw = np.argmin(np.abs(a[val]-b[dup == val])) 
     tt = dup == val 
     ret_b[idx] = np.where(tt == True)[0][bw] 
    return np.column_stack((uni, ret_b)) 
0

跟蹤兩個指針,一個用於a的當前索引,另一個用於b。當我們增加指針a時,我們會跟蹤被指向的元素之間的最小差異和索引,直到指向sharp_a> pointed_b。再次更新最小差異和索引(如果有變化)。我們有第一個元素的答案。通過增加b的指針來類似地繼續搜索,並從我們離開的地方拿起指針a。

複雜:O(LEN一個+ LEN b)中,因此線性

+0

如果'log a'是'ω(log(b)* log(log b)))'那麼這可以優化爲'len a'二進制搜索,這可以提高效率。 – enedil

0

scipy.spatial.cKDTree是解決此問題的最簡單方法;矢量化,並且可能對您的應用程序足夠好;但鑑於您的數據是排序的,在理論上並不理想。

或者,您可以使用numpy.searchsorted。使用它來查找左側或右側插入點,然後比較該點和下一個點以找到最近的點。

相關問題