Eu tenho uma matriz NumPy 2D e gostaria de substituir todos os valores nela maiores ou iguais a um limite T com 255.0. Que eu saiba, a maneira mais fundamental seria:
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
Qual é a maneira mais concisa e pitônica de fazer isso?
Existe uma maneira mais rápida (possivelmente menos concisa e / ou menos pitônica) de fazer isso?
Isso fará parte de uma sub-rotina de ajuste de janela / nível para exames de ressonância magnética da cabeça humana. A matriz numpy 2D é o dado de pixel da imagem.
Respostas:
Acho que a maneira mais rápida e concisa de fazer isso é usar a indexação Fancy incorporada do NumPy. Se você tiver um
ndarray
nomearr
, poderá substituir todos os elementos>255
por um valor dax
seguinte maneira:Eu executei isso na minha máquina com uma matriz aleatória 500 x 500, substituindo todos os valores> 0,5 por 5, e levou uma média de 7,59ms.
fonte
arr
, em vez de criar umaresult
matriz como no OP.A
mas criando uma nova matriz?np.array([1,2,3]
)Como você realmente deseja uma matriz diferente, que é
arr
ondearr < 255
e255
, caso contrário, isso pode ser feito simplesmente:De maneira mais geral, para um limite inferior e / ou superior:
Se você deseja apenas acessar valores acima de 255, ou algo mais complicado, a resposta do @ mtitan8 é mais geral, mas
np.clip
enp.minimum
(ounp.maximum
) é mais agradável e muito mais rápida para o seu caso:Se você quiser fazer isso no local (por exemplo, modificar em
arr
vez de criarresult
), poderá usar oout
parâmetro denp.minimum
:ou
(o
out=
nome é opcional, pois os argumentos estão na mesma ordem que a definição da função.)Para a modificação no local, a indexação booleana acelera bastante (sem precisar fazer e modificar a cópia separadamente), mas ainda não é tão rápida quanto
minimum
:Para comparação, se você quiser restringir seus valores com um mínimo e um máximo, sem
clip
isso, você precisará fazer isso duas vezes, com algo comoou,
fonte
a[start:stop:step]
fornece os elementos da matriz destart
parastop
, mas, em vez de todos os elementos, são necessários apenas todosstep
(se negligenciados, é1
por padrão). ) Então, para definir todos os nivela a zero, você poderia fazera[::2] = 0
Eu acho que você pode conseguir isso o mais rápido usando o
where
função:Por exemplo, procurando itens maiores que 0,2 em uma matriz numpy e substituindo aqueles por 0:
fonte
Você pode considerar o uso de numpy.putmask :
Aqui está uma comparação de desempenho com a indexação interna do Numpy:
fonte
Outra maneira é usar o
np.place
que substitui no local e trabalha com matrizes multidimensionais:fonte
np.place
também foi mais lento em comparação com o método interno, embora o contrário seja reivindicado neste comentário.Você também pode usar
&
,|
(e / ou) para mais flexibilidade:valores entre 5 e 10:
A[(A>5)&(A<10)]
valores maiores que 10 ou menores que 5:
A[(A<5)|(A>10)]
fonte