2014-10-03 5 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) не более 0,8 раза в следующем году argest значение в строке

Я хотел бы сделать это максимально эффективно, желательно без каких-либо петель. Я боролся с этим какое-то время, поэтому любая помощь, которую вы можете предоставить, будет очень признательна!

+1

ли не цели номер 1) и 3) противоречиями? – JB333

+0

@ JB333 Возможно, это трюк, и ответ заключается в том, чтобы всегда возвращать пустой массив (без каких-либо циклов). ;-) – Carsten

ответ

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

1

Я думаю, что вам будет трудно это сделать без каких-либо циклов (или, по крайней мере, что-то, что выполняет такой цикл, но может быть маскировка это как-то еще), видя, как операция зависит только от строки, и вы хотите сделать это для каждой строки. Это не самый эффективный (и что это может зависеть от того, как часто условия 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

Смежные вопросы