web-dev-qa-db-fra.com

Remplace tous les éléments de Python NumPy Array supérieurs à une valeur

J'ai un tableau 2D NumPy et voudrais remplacer toutes les valeurs supérieures ou égales à un seuil T avec 255.0. À ma connaissance, le moyen le plus fondamental serait:

shape = arr.shape
result = np.zeros(shape)
for x in range(0, shape[0]):
    for y in range(0, shape[1]):
        if arr[x, y] >= T:
            result[x, y] = 255
  1. Quel est le moyen le plus concis et pythonique de le faire?

  2. Y at-il un moyen plus rapide (peut-être moins concis et/ou moins Pythonic) de le faire?

Cela fera partie d'un sous-programme de réglage de fenêtre/niveau pour les examens IRM de la tête humaine. Le tableau numpy 2D correspond aux données de pixels de l’image.

153
NLi10Me

Je pense que le moyen le plus rapide et le plus concis de procéder consiste à utiliser l'indexation Fancy intégrée de NumPy. Si vous avez une ndarray nommée arr, vous pouvez remplacer tous les éléments >255 par une valeur x comme suit:

arr[arr > 255] = x

Je l'ai exécuté sur ma machine avec une matrice aléatoire de 500 x 500, en remplaçant toutes les valeurs> 0,5 par 5, et cela a pris en moyenne 7,59 ms.

In [1]: import numpy as np
In [2]: A = np.random.Rand(500, 500)
In [3]: timeit A[A > 0.5] = 5
100 loops, best of 3: 7.59 ms per loop
266
mdml

Puisque vous voulez réellement un tableau différent qui est arrarr < 255 et 255 sinon, vous pouvez le faire simplement:

result = np.minimum(arr, 255)

Plus généralement, pour une limite inférieure et/ou supérieure:

result = np.clip(arr, 0, 255)

Si vous voulez juste accéder aux valeurs supérieures à 255, ou quelque chose de plus compliqué, la réponse de @ mtitan8 est plus générale, mais np.clip et np.minimum (ou np.maximum) sont plus agréables et plus rapides pour votre ordinateur. Cas:

In [292]: timeit np.minimum(a, 255)
100000 loops, best of 3: 19.6 µs per loop

In [293]: %%timeit
   .....: c = np.copy(a)
   .....: c[a>255] = 255
   .....: 
10000 loops, best of 3: 86.6 µs per loop

Si vous voulez le faire sur place (c'est-à-dire, modifier arr au lieu de créer result), vous pouvez utiliser le paramètre out de np.minimum:

np.minimum(arr, 255, out=arr)

ou

np.clip(arr, 0, 255, arr)

(Le nom out= est facultatif, car les arguments sont dans le même ordre que la définition de la fonction.)

Pour la modification sur place, l'indexation booléenne accélère beaucoup (sans avoir à créer puis à modifier la copie séparément), mais n'est pas aussi rapide que minimum:

In [328]: %%timeit
   .....: a = np.random.randint(0, 300, (100,100))
   .....: np.minimum(a, 255, a)
   .....: 
100000 loops, best of 3: 303 µs per loop

In [329]: %%timeit
   .....: a = np.random.randint(0, 300, (100,100))
   .....: a[a>255] = 255
   .....: 
100000 loops, best of 3: 356 µs per loop

À titre de comparaison, si vous vouliez restreindre vos valeurs avec un minimum aussi bien qu'un maximum, sans clip, vous devrez le faire deux fois, avec quelque chose comme:

np.minimum(a, 255, a)
np.maximum(a, 0, a)

ou,

a[a>255] = 255
a[a<0] = 0
43
askewchan

Je pense que vous pouvez y arriver le plus rapidement en utilisant la fonction where:

Par exemple, recherchez des éléments supérieurs à 0,2 dans un tableau numpy et remplacez ceux-ci par 0:

import numpy as np

nums = np.random.Rand(4,3)

print np.where(nums > 0.2, 0, nums)
11
Amir F

Vous pouvez envisager d'utiliser numpy.putmask:

np.putmask(arr, arr>=T, 255.0)

Voici une comparaison des performances avec l'indexation intégrée de Numpy:

In [1]: import numpy as np
In [2]: A = np.random.Rand(500, 500)

In [3]: timeit np.putmask(A, A>0.5, 5)
1000 loops, best of 3: 1.34 ms per loop

In [4]: timeit A[A > 0.5] = 5
1000 loops, best of 3: 1.82 ms per loop
8
lev

Une autre méthode consiste à utiliser np.place qui effectue le remplacement sur place et fonctionne avec des tableaux multidimensionnels:

import numpy as np

arr = np.arange(6).reshape(2, 3)
np.place(arr, arr == 0, -10)
8
Shital Shah

Vous pouvez également utiliser &, | (et/ou) pour plus de flexibilité:

valeurs comprises entre 5 et 10: A[(A>5)&(A<10)]

valeurs supérieures à 10 ou inférieures à 5: A[(A<5)|(A>10)]

2
Mahdi Shahbaba