Indexação em NumPy
Para aproveitar todas as vantagens que o NumPy pode oferecer para a computação numérica, saber acessar e manipular elementos em um array é essencial. A indexação em NumPy refere-se ao processo de acessar e manipular elementos em um array NumPy. Ela é uma operação fundamental que permite extrair valores específicos, modificar o conteúdo de vetores, matrizes e tensores e criar subarrays.
Quando um array possui uma estrutura simples, a indexação é equivalente à indexação de listas em Python. O problema para pessoas iniciantes é entender o processo de indexação em arrays multidimensionais. Neste post, cobriremos indexação em arrays de diferentes dimensões e também abordaremos alguns métodos avançados de indexação em NumPy.
Princípios Elementares de Indexação em NumPy
Assim como listas e outros iteráveis como sets e tuplas em Python, a indexação em NumPy permite acessar os elementos de uma estrutura de dados, nesse caso um array, através de suas posições ou índices. Seguindo o padrão tradicional do Python, a indexação em NumPy se inicia em 0. Parar arrays unidimensionais, a indexação é simples, veja alguns exemplos:
import numpy as np
arr = np.array([1, 2, 3, 4, 5])
print(arr[0], arr[1], arr[2]) # imprime o primeiro, o segundo e o terceiro elemento do array
# resultados: 1 2 3
Assim como ocorre com listas e outros iteráveis em Python, o NumPy aceita indexação negativa:
print(arr[-1], arr[-2], arr[-3])
# resultados: 5 4 3
Fatiamento em Arrays Unidimensionais
O fatiamento (slicing) de um array possibilita extrair um subarray em um intervalo. Para arrays unidimensionais, o processo é equivalente ao fatiamento em listas em Python. Podemos fatiar um array fornecendo um elemento de início (incluído) e de término (não incluído) de um intervalo:
arr = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8])
print(arr[0:4]) # extrai os elementos de índices variando de 0 a 4 no array
# resultado: [0 1 2 3]
O símbolo “:” pode ser usado para selecionar todos os elementos de um array, todos os elementos até uma posição específica (não incluído), ou ainda todos os elementos a partir de uma localização específica até o final. Veja abaixo:
arr = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8])
print(arr[:]) # seleciona todos os elementos de um array - equivalente a imprimir o array: print(arr)
# resultado: [0 1 2 3 4 5 6 7 8]
arr = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8])
print(arr[:4]) # seleciona todos os elementos do início até a posição de índice 4 (não incluída)
# resultado: [0 1 2 3]
arr = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8])
print(arr[4:]) # seleciona todos os elementos a partir da posição de índice 4 (incluída) até o final
# resultado: [4 5 6 7 8]
Indexação em Arrays Multidimensionais
Elementos de arrays multidimensionais têm uma diferença óbvia em relação aos equivalentes unidimensionais: cada elemento tem uma posição definida por mais de um índice. No exemplo abaixo, um array bidimensional foi usado. Veja que, para selecionar elementos com uma localização específica, é preciso fornecer o índice do eixo 0 e o índice do eixo 1. Lembrando que, para arrays bidimensionais, o eixo 0 corresponde ao eixo de linhas e o eixo 1 ao eixo de colunas de uma matriz:
arr = np.array([[1, 2, 3], [4, 5, 6]]) # array 2 x 3
print(arr[0,0]) # para selecionar um elemento, precisa fornecer dois indices no caso de arrays bidimensionais
# resultado: 1
print(arr[0,1])
# resultado: 2
print(arr[0,2])
# resultado: 3
Se o array tiver dimensionalidade maior, será preciso acrescentar os índices dos eixos adicionais para acessar um elemento específico. No exemplo abaixo, precisamos de 3 índices para acessar elementos específicos de um array tridimensional:
arr = np.array([[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [10, 11, 12]]]) # array 2 x 2 x 3
print(arr[0,0,0])
# resultado: 1
print(arr[-1,-1,-1])
# resultado: 12
Importante: a omissão do índice de um eixo nesses casos não causa um erro, mas retorna todos os elementos do eixo onde o NumPy entende que a omissão ocorreu (o último) no intervalo especificado. Veja abaixo:
arr = np.array([[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [10, 11, 12]]])
print(arr[1,0]) # equivalente a arr[1,0,:]
# resultado: [7 8 9]
Fatiamento em Arrays Multidimensionais
O fatiamento de arrays multidimensionais também leva todos os eixos em consideração. Se quisermos selecionar intervalos precisos, precisamos entender como definir o intervalo em cada eixo. Veja alguns exemplos com um array bidimensional:
arr = np.array([[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]]) # array 2 x 5
print(arr[:,3:]) # seleciona todos os elementos do eixo 0 que se localizam do índice 3 até o final do eixo 1
# resultado:
# [[ 4 5]
# [ 9 10]]
print(arr[:,:3]) # seleciona todos os elementos do eixo 0 que se localizam do índice 0 até o índice 3 (não incluído) do eixo 1
# resultado:
# [[1 2 3]
# [6 7 8]]
O fatiamento em arrays tritidimensionais pode ser ilustrado com o uso de imagens. Imagens coloridas podem ser criadas com arrays tridimensionais. O primeiro eixo representa a altura da imagem, o segundo a sua largura e o terceiro os 3 canais de cores (R, G, B). Usaremos a biblioteca Matplotlib para plotar o array como uma imagem.
import numpy as np
import matplotlib.pyplot as plt
# cria uma imagem com um array tridimensional
img = np.zeros((500, 500, 3)) # imagem inteira em preto criada com array tridimensional
plt.subplot(2,2,1)
plt.imshow(img) # plota imagem 1
# seleciona um intervalo pegando todas as linhas (eixo 0) das colunas 200 a 301 (eixo 1) do canal 0 (vermelho)
img[:,200:301,0] = 1 # muda os valores dos elementos selecionados para 1
plt.subplot(2,2,2)
plt.imshow(img) # plota imagem 2
# seleciona um intervalo pegando todas as colunas (eixo 1) das linhas 200 a 301 (eixo 0) do canal 2 (azul)
img[200:301,:,2] = 1 # muda os valores dos elementos selecionados para 1
plt.subplot(2,2,3)
plt.imshow(img) # plota imagem 3
# seleciona intervalos contendo todas as linhas (eixo 0) das colunas com intervalos de 50 em 50 do canal 1 (verde)
img[:,::50,1] = 1 # muda os valores dos elementos selecionados para 1
plt.subplot(2,2,4)
plt.imshow(img) # plota imagem 4
plt.show() # exibe a figura com todos os subplots
As imagens dos arrays são mostradas abaixos. Como usamos um array de zeros como ponto de partida, a imagem inicial é um quadrado preto. Ela vai sendo pintada a medida em que mudamos os valores dos elementos específicos do array de 0 para 1.
Métodos Avançados de Indexação em NumPy
Além dos métodos mostrados acima, o NumPy conta com outros mais avançados para acessar elementos de arrays. Conheça alguns a seguir.
Indexação com inteiros
Uma das formas mais avançadas de identificação em NumPy consiste no uso de listas ou matrizes de inteiros como índices. Ou seja, no lugar de especificar um índice de cada vez ou usar um fatiamento com um intervalo uniforme, podemos usar uma lista ou um array de índices para selecionar os elementos de interesse. Dois exemplos ilustrativos são mostrados abaixo:
# exemplo 1 - array unidimensional
arr1 = np.array([1, 2, 3, 4, 5, 6, 7])
print(arr1[[3,4,6]]) # imprime elementos de um array selecionados com uma lista de índices
# resultados: [4 5 7]
# exemplo 2 - array bidimensional
arr2 = np.array([[1, 2, 3], [4, 5, 6]])
print(arr2[[0,1],[0,2]])
# resultados: [1 6]
Indexação Booleana
A indexação booleana consiste no uso de uma condição para retornar todos os elementos que forem True para a condição testada. No exemplo abaixo, a condição especificada foi ser maior do que 5.
arr = np.array([1, 2, 3, 4, 5, 6])
print(arr[arr>5])
# resultado: [6]
O retorno da condição testada pode ser usado para modificar os elementos do array:
arr = np.array([1, 2, 3, 4, 5, 6])
arr[arr>3] = -1 # usa uma condição booleana para acessar todos os itens maiores do que 3 e modifica seus valores para -1
print(arr)
# resultado: [ 1 2 3 -1 -1 -1]
A indexação booleana também aceita múltiplas condições simultaneamente, como ilustrado abaixo:
arr = np.array([1, 2, 3, 4, 5, 6])
arr[(arr>2) & (arr<5)] = -100 # usa uma condição booleana composta para modificar elementos do array - note o uso do operador & (and)
print(arr)
# resultado: [ 1 2 -100 -100 5 6]
Veja também:
Encontrou algum erro ou quer fazer uma sugestão? Por favor, entre em contato usando nosso formulário de contatos.