python - multiplicar - numpy functions
Reemplazar todos los elementos de Python NumPy Array que sean mayores que algún valor (6)
Tengo una matriz 2D NumPy y me gustaría reemplazar todos los valores en ella mayores o iguales a un umbral T con 255.0. Que yo sepa, la forma más fundamental sería:
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
¿Cuál es la forma más concisa y pitónica de hacer esto?
¿Hay una manera más rápida (posiblemente menos conciso y / o menos pitónica) de hacer esto?
Esto será parte de una subrutina de ajuste de ventana / nivel para escaneos MRI de la cabeza humana. La matriz numpy 2D es la imagen de píxeles de imagen.
Como realmente quiere una matriz diferente que es arr
donde arr < 255
y 255
contrario, esto se puede hacer simplemente:
result = np.minimum(arr, 255)
De manera más general, para un límite inferior y / o superior:
result = np.clip(arr, 0, 255)
Si solo desea acceder a los valores superiores a 255, o algo más complicado, la respuesta de @mtitan8 es más general, pero np.clip
y np.minimum
(o np.maximum
) son más agradables y más rápidos para su caso:
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 desea hacerlo en el lugar (es decir, modificar arr
lugar de crear result
) puede usar el parámetro out
de np.minimum
:
np.minimum(arr, 255, out=arr)
o
np.clip(arr, 0, 255, arr)
(el out=
name es opcional ya que los argumentos están en el mismo orden que la definición de la función).
Para la modificación in situ, la indexación booleana se acelera mucho (sin tener que realizar y luego modificar la copia por separado), pero todavía no es tan rápida como 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
Para comparar, si quisiera restringir sus valores con un mínimo y un máximo, sin clip
, tendría que hacer esto dos veces, con algo como
np.minimum(a, 255, a)
np.maximum(a, 0, a)
o,
a[a>255] = 255
a[a<0] = 0
Creo que la forma más rápida y concisa de hacer esto es usar la indexación integrada de Numpy. Si tiene una ndarray
llamada arr
puede reemplazar todos los elementos >255
con un valor x
siguiente manera:
arr[arr > 255] = x
Ejecuté esto en mi máquina con una matriz aleatoria de 500 x 500, reemplazando todos los valores> 0.5 por 5, y tardé un promedio de 7.59ms.
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
Creo que puedes lograr esto de la manera más rápida usando la función where
:
Por ejemplo, busca elementos mayores a 0.2 en una matriz numpy y reemplaza aquellos con 0:
import numpy as np
nums = np.random.rand(4,3)
print np.where(nums > 0.2, 0, nums)
Otra forma es usar np.place
que reemplaza y funciona con arreglos multidimensionales:
import numpy as np
arr = np.arange(6).reshape(2, 3)
np.place(arr, arr == 0, -10)
Puedes considerar usar numpy.putmask :
np.putmask(arr, arr>=T, 255.0)
Aquí hay una comparación de rendimiento con la indexación integrada 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
También puedes usar &
, |
(y / o) para más flexibilidad:
valores entre 5 y 10: A[(A>5)&(A<10)]
valores mayores que 10 o menores que 5: A[(A<5)|(A>10)]