6.12. Seleção e reordenação¶
As reduções colapsaram um array até um escalar ou um resultado de classificação inferior. A seleção cobre as operações que escolhem quais os elementos que sobrevivem e onde ficam: escolha condicional, recorte, ordenação, consulta de índices, reordenação ao longo de um eixo.
6.12.1. Escolha condicional¶
where() devolve um array que toma elementos de x onde a condição é verdadeira e de y caso contrário. Os três operandos são difundidos em conjunto:
a = np.array([1, 2, 3, 4, 5], dtype=np.float)
np.where(a < 3, a, 0.0)
# array([1.0, 2.0, 0.0, 0.0, 0.0])
Esta é a ferramenta certa para um «if/else por elemento» sem escrever um ciclo Python.
clip() é uma abreviatura para maximum(lo, minimum(a, hi)) – saturar os valores num intervalo:
np.clip(a, 2.0, 4.0)
# array([2.0, 2.0, 3.0, 4.0, 4.0])
maximum() e minimum() recebem dois operandos e devolvem o maior/menor elemento a elemento:
np.maximum(a, 3.0)
np.minimum(a, np.array([5, 4, 3, 2, 1]))
6.12.2. Localização de índices¶
nonzero() devolve as coordenadas de cada elemento não nulo, divididas num array de índices por dimensão. Para uma entrada bidimensional, o resultado é um tuplo de dois arrays: o primeiro contém os índices de linha, o segundo os índices de coluna. Emparelhá-los coluna a coluna fornece o (row, col) de cada posição não nula:
m = np.array([[0, 2, 0],
[3, 0, 0]], dtype=np.float)
np.nonzero(m)
# (array([0, 1], dtype=uint16), array([1, 0], dtype=uint16))
As entradas não nulas em m são m[0, 1] = 2 e m[1, 0] = 3. O primeiro array devolvido [0, 1] fornece os seus índices de linha; o segundo [1, 0] fornece os seus índices de coluna. Ler os dois arrays lado a lado recupera as posições (0, 1) e (1, 0).
Duas reduções também produzem índices:
argmin()/argmax()– índice do elemento mais pequeno / maior.argsort()– um array de inteiros que ordenaria a entrada ao longo do eixo indicado (por predefinição, o último):a = np.array([40, 10, 30, 20], dtype=np.uint8) idx = np.argsort(a) # array([1, 3, 2, 0], dtype=uint16) a[idx] # array([10, 20, 30, 40])
argsortdevolve sempreuint16; o array a ordenar não pode, portanto, ter mais de 65.535 elementos no eixo ordenado.
bincount() conta as ocorrências de cada inteiro não negativo numa entrada uint8 / uint16 unidimensional:
histogram = np.bincount(np.array([0, 1, 1, 2, 2, 2], dtype=np.uint8))
# array([1, 2, 3], dtype=uint16)
Útil para construir histogramas de valores de pixel de inteiros pequenos sem escrever um ciclo Python.
6.12.3. Ordenação e reordenação¶
sort() devolve uma cópia ordenada do array ao longo do eixo indicado (o último por predefinição). Use sort() diretamente no array para uma versão in-place:
np.sort(np.array([3, 1, 2], dtype=np.float))
# array([1.0, 2.0, 3.0])
flip() inverte a ordem ao longo do eixo indicado (todos os eixos quando não é passado nenhum axis):
np.flip(np.array([1, 2, 3, 4]))
# array([4, 3, 2, 1])
roll() desloca ciclicamente os elementos pelo número indicado. Útil para implementar um registo de deslocamento no estilo de ring-buffer:
np.roll(np.array([1, 2, 3, 4]), 1)
# array([4, 1, 2, 3])
take() é a forma explícita de indexação fancy – selecionar elementos em índices arbitrários:
a = np.array([10, 20, 30, 40, 50], dtype=np.uint8)
np.take(a, [0, 2, 4])
# array([10, 30, 50], dtype=uint8)
6.12.4. Filtragem e edições estruturais¶
compress() é a forma explícita de indexação booleana – devolver as fatias de a selecionadas pela condição booleana:
a = np.array([10, 20, 30, 40], dtype=np.uint8)
np.compress(a > 15, a)
# array([20, 30, 40], dtype=uint8)
delete() devolve uma cópia com as entradas nos índices indicados removidas:
a = np.array([10, 20, 30, 40, 50], dtype=np.uint8)
np.delete(a, [1, 3])
# array([10, 30, 50], dtype=uint8)
diff() devolve a n-ésima diferença discreta para a frente do array ao longo de um eixo. Usado para calcular variações de primeira ordem entre amostras adjacentes:
samples = np.array([1, 3, 6, 10, 15], dtype=np.float)
np.diff(samples)
# array([2.0, 3.0, 4.0, 5.0])
6.12.5. O custo de cada operação¶
Quase todas as funções desta página devolvem um array recentemente alocado. Duas exceções:
sort()ordena in-place; a função livresort()devolve uma cópia ordenada.take()aceita uma palavra-chaveout=para escrever num buffer já existente.
Num ciclo que corre muitas vezes por segundo, prefira o sort() in-place e reutilize buffers pré-alocados em todos os outros casos. As máscaras booleanas são alocadas de cada vez que a comparação corre – construa uma máscara uma vez e reutilize-a entre operações em vez de a reconstruir dentro de cada iteração.