Je dois compter toutes les valeurs d'une matrice (tableau à 2 dimensions) supérieures à 200.
Le code que j'ai écrit pour cela est:
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
est une image et je la convertis en matrice puis recherche les valeurs.
Ma question est la suivante: existe-t-il un moyen plus simple de procéder?
Le numpy.where
_ fonction est votre ami. Comme il est implémenté pour tirer pleinement parti du type de données de la matrice, vous devriez constater une amélioration de la vitesse pour les grandes images par rapport à la solution pure python que vous fournissez.
Utiliser numpy.where directement donnera un masque booléen indiquant si certaines valeurs correspondent à vos conditions:
>>> data
array([[1, 8],
[3, 4]])
>>> numpy.where( data > 3 )
(array([0, 1]), array([1, 1]))
Et le masque peut être utilisé pour indexer directement le tableau pour obtenir les valeurs réelles:
>>> data[ numpy.where( data > 3 ) ]
array([8, 4])
L’endroit exact où vous le prenez dépend de la forme sous laquelle vous souhaitez obtenir les résultats.
C'est très simple avec les tableaux booléens:
p31 = numpy.asarray(o31)
za = (p31 < 200).sum() # p31<200 is a boolean array, so `sum` counts the number of True elements
Il y a plusieurs façons d'y parvenir, comme aplatir et filtrer ou simplement énumérer, mais je pense que l'utilisation de tableau booléen/masque est la plus simple (et une beaucoup plus rapide):
>>> 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
Mise à jour :
Comme nneonneo a répondu, si tout ce que vous voulez, c'est le nombre d'éléments dépassant le seuil, vous pouvez simplement faire:
>>>> (y>200).sum()
3
ce qui est une solution plus simple.
Comparaison de la vitesse avec 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
Voici une variante qui utilise l'indexation de fantaisie et dont les valeurs réelles sont intermédiaires:
p31 = numpy.asarray(o31)
values = p31[p31<200]
za = len(values)
Pour compter le nombre de valeurs supérieures à x dans n’importe quel tableau numpy, vous pouvez utiliser:
n = len(matrix[matrix > x])
L'indexation booléenne renvoie un tableau contenant uniquement les éléments où la condition (matrice> x) est remplie. Alors len () compte ces valeurs.