2014-10-03 60 views
3

我有在Python陣列像這樣:如何在滿足多個條件的numpy數組中找到索引?

實施例:

>>> scores = numpy.asarray([[8,5,6,2], [9,4,1,4], [2,5,3,8]]) 
>>> scores 
array([[8, 5, 6, 2], 
    [9, 4, 1, 4], 
    [2, 5, 3, 8]]) 

我想找到所有[row, col]指數在scores其中值是:

1)的最小在其

2)大於閾值

3)至多是下一個la的.8倍在行中的rgest值

我想盡可能有效地做到這一點,最好是沒有任何循環。我一直在努力爭取一段時間,所以你可以提供任何幫助將不勝感激!

+1

是不是進球數1)和3)相沖突? – JB333 2014-10-03 00:29:44

+0

@ JB333也許這是一個技巧性的問題,答案是總是返回一個空數組(沒有任何循環)。 ;-) – Carsten 2014-10-03 00:56:21

回答

2

它應該去的東西沿着

In [1]: scores = np.array([[8,5,6,2], [9,4,1,4], [2,5,3,8]]); threshold = 1.1; scores 
Out[1]: 
array([[8, 5, 6, 2], 
     [9, 4, 1, 4], 
     [2, 5, 3, 8]]) 

In [2]: part = np.partition(scores, 2, axis=1); part 
Out[2]: 
array([[2, 5, 6, 8], 
     [1, 4, 4, 9], 
     [2, 3, 5, 8]]) 

In [3]: row_mask = (part[:,0] > threshold) & (part[:,0] <= 0.8 * part[:,1]); row_mask 
Out[3]: array([ True, False, True], dtype=bool) 

In [4]: rows = row_mask.nonzero()[0]; rows 
Out[4]: array([0, 2]) 

In [5]: cols = np.argmin(scores[row_mask], axis=1); cols 
Out[5]: array([3, 0]) 

線那一刻,如果你正在尋找的實際座標對,你可以zip他們:

In [6]: coords = zip(rows, cols); coords 
Out[6]: [(0, 3), (2, 0)] 

或者,如果你打算看看這些元素,你可以直接使用它們:

In [7]: scores[rows, cols] 
Out[7]: array([2, 2]) 
+0

非常感謝!那是我正在尋找的那種東西。 – jmanring220 2014-10-03 14:12:41

1

我認爲你將很難做到這一點沒有任何for循環(或至少是執行這樣一個循環,但可能是僞裝它作爲別的東西),看看操作只取決於行,並且您想爲每行執行此操作。這不是最有效的(什麼是可能取決於條件2和3的頻率爲真),但是這將工作:

import heapq 
threshold = 1.5 
ratio = .8 
scores = numpy.asarray([[8,5,6,2], [9,4,1,4], [2,5,3,8]]) 

found_points = [] 
for i,row in enumerate(scores): 
    lowest,second_lowest = heapq.nsmallest(2,row) 
    if lowest > threshold and lowest <= ratio*second_lowest: 
     found_points.append([i,numpy.where(row == lowest)[0][0]]) 

你得到(爲例子):

found_points = [[0, 3], [2, 0]] 
+0

謝謝@ JB333!那也行得通。 – jmanring220 2014-10-03 14:12:09