2012-10-21 8 views
31

muszę zliczyć wszystkie wartości w matrycy (2-d) matrycy, które są większe niż 200liczba wszystkich wartości w osnowie większa niż wartość

kod I zapisała w to:

za=0 
p31 = numpy.asarray(o31) 
for i in range(o31.size[0]): 
    for j in range(o32.size[1]): 
     if p31[i,j]<200: 
      za=za+1 
print za 

o31 to obraz i zamieniam go na matrycę, a następnie znajdowanie wartości.

Moje pytanie brzmi, czy istnieje prostszy sposób na zrobienie tego?

+1

Czy to nie wystarczy wydrukować liczbę wartości mniej niż 200, a nie rzeczywistych wartości? –

+0

Tak. Po prostu potrzebuję sumy wszystkich wartości zamiast samych wartości rzeczywistych. –

+0

Tutaj też nie ma całkowitej sumy. Ustaw 'za' na pustą listę' za = [] ', następnie' za.append (p31 [i, j]) ', w końcu z pętli for,' print sum (za) '; ale jestem pewien, że jest lepszy sposób, ponieważ używasz numpy. –

Odpowiedz

45

Funkcja numpy.where jest Twoim przyjacielem. Ponieważ została zaimplementowana, aby w pełni wykorzystać typ danych tablicy, w przypadku dużych obrazów należy zauważyć poprawę szybkości w stosunku do dostarczanego przez nas samego rozwiązania Pythona.

Korzystanie bezpośrednio numpy.where przyniesie maskę logiczną wskazującą, czy pewne wartości dopasować warunki:

>>> data 
array([[1, 8], 
     [3, 4]]) 
>>> numpy.where(data > 3) 
(array([0, 1]), array([1, 1])) 

I maski mogą być używane do indeksu tablicy bezpośrednio uzyskać rzeczywiste wartości:

>>> data[ numpy.where(data > 3) ] 
array([8, 4]) 

Dokładnie tam, gdzie je bierzesz, zależy od formy, w jakiej chcesz uzyskać wyniki.

+6

Dzięki ... Ale potrzebuję całkowitej liczby wartości, a nie same wartości ... czy powinienem zrobić sumę (numpy.where (dane <200))? –

+0

Jeśli chcesz mieć liczbę OF, a nie sumę, zrobiłbyś len (numpy.where (dane <200)) – jimh

+0

jeśli warunek został zmieniony na> 0, to powróci (tablica ([0, 0, 1, 1 ]), array ([0, 1, 0, 1])), co to znaczy? czy to błąd? – hihell

15

Istnieje wiele sposobów osiągnięcia tego celu, np. Latten filtrujący lub po prostu wymienić, ale myślę, że za pomocą Boolean/mask array jest najprostszym jeden (i IIRC znacznie szybciej jeden):

>>> y = np.array([[123,24123,32432], [234,24,23]]) 
array([[ 123, 24123, 32432], 
     [ 234, 24, 23]]) 
>>> b = y > 200 
>>> b 
array([[False, True, True], 
     [ True, False, False]], dtype=bool) 
>>> y[b] 
array([24123, 32432, 234]) 
>>> len(y[b]) 
3 
>>>> y[b].sum() 
56789 

Aktualizacja:

Jak nneonneo odpowiedział, jeśli wszystko Chcesz, aby liczba elementów przekroczyła próg, wystarczy:

>>>> (y>200).sum() 
3 

co jest prostszym rozwiązaniem.


porównanie prędkości z filter:

### use boolean/mask array ### 

b = y > 200 

%timeit y[b] 
100000 loops, best of 3: 3.31 us per loop 

%timeit y[y>200] 
100000 loops, best of 3: 7.57 us per loop 

### use filter ### 

x = y.ravel() 
%timeit filter(lambda x:x>200, x) 
100000 loops, best of 3: 9.33 us per loop 

%timeit np.array(filter(lambda x:x>200, x)) 
10000 loops, best of 3: 21.7 us per loop 

%timeit filter(lambda x:x>200, y.ravel()) 
100000 loops, best of 3: 11.2 us per loop 

%timeit np.array(filter(lambda x:x>200, y.ravel())) 
10000 loops, best of 3: 22.9 us per loop 

*** use numpy.where *** 

nb = np.where(y>200) 
%timeit y[nb] 
100000 loops, best of 3: 2.42 us per loop 

%timeit y[np.where(y>200)] 
100000 loops, best of 3: 10.3 us per loop 
+0

'timeit y [b]' pomija połowę kodu z obliczeń wykonanych w filtrze. '% timeit y [y> 200]' jest równoważne-ish. –

44

To jest bardzo proste z logicznych tablic:

p31 = numpy.asarray(o31) 
za = (p31 < 200).sum() # p31<200 is a boolean array, so `sum` counts the number of True elements 
6

Oto wariant, który używa ozdobnego indeksowanie i ma rzeczywiste wartości jako półprodukt:

p31 = numpy.asarray(o31) 
values = p31[p31<200] 
za = len(values) 
+0

To jest po prostu regularne indeksowanie boolowskie. –