Indexação e Slicing NumPy

Alguns tantos exemplos para facilitar sua compreensão

No artigo anterior, de Computação Numérica com NumPy, vimos como construir objetos unidimensionais e bidimensionais com métodos NumPy.

Relembrando, construir um objeto unidimensional, nada mais é do que um vetor, uma lista de valores. Enquanto um objeto bidimensional, é uma matriz, uma tabela em um banco de dados ou uma planilha excel.

Uma vez que tenhamos essas estruturas de dados, seja um vetor ou uma matriz, podemos buscar apenas algumas partes desses dados.

Suponha que tenhamos uma planilha em Excel toda preenchida, e desejamos buscar apenas algumas células específicas de uma planilha. Para fazer isso, utilizamos o conceito de slicing, ou seja, buscamos apenas uma parte dos dados dentro da nossa estrutura de dados, seja um vetor, seja uma matriz. Para trabalhar com slicing, precisamos primeiro conhecer o conceito de indexação em linguagem Python.

Notebook de estudo

Acesse o Jupyter Notebook para consultar os conceitos que serão abordados sobre Slicing e Fatiamento

Indexação e Slicing com NumPy

Uma vez que haja um vetor ou uma matriz, podemos buscar apenas algumas partes desses dados.

Importando módulo NumPy

# Importando o módulo Numpy
import numpy as np

Arange

Vamos criar um array unidimensional, apenas passando uma dimensão e imprimir na tela. Um array, nada mais é, que uma lista de valores.

array1 = np.arange(5); array1
array([0, 1, 2, 3, 4])

O que é um índice?

Para consultar elementos dentro de uma lista de valores, primeiramente, precisamos entender o conceito de indexação. Índice é uma espécie de endereço onde está gravado o elemento (dado), dentro da estrutura.

Em Python, o que temos é um conjunto de endereços que são chamados de índices e que apontam para os dados. Inclusive, é possível manipular esses índices da forma que for mais conveniente para o nosso trabalho.

Há particularidade na linguagem Python é que a indexação começa por 0, já em R, a indexação começa por 1.

1° elemento do Array

#Retornar 1° elemento do array 
array1[0] # endereço do elemento
0

2° elemento do Array

# Segundo elemento do array
array1[1] # endereço do elemento
1

Último elemento do Array

Podemos ainda, chamar a indexação negativa, que começa a mostrar o poder da indexação em Python e NumPy.

Quando utilizamos o -1 como índice, vamos buscar o último elemento da nossa lista com extrema simplicidade.

#Último elemento do array 
array1[-1] # final do endereço
4

Criando Array

#Criando um array
array2 = np.arange(5); array2
array([0, 1, 2, 3, 4])

Invertendo Array

Quando utilizamos dois pontos duplo com -1, invertemos a lista.

Quando for necessário realizar uma inversão, um comando simples como esse, faz o trabalho por nós.

#Invertendo a estrutura do array
array2[::-1]
array([4, 3, 2, 1, 0])

Trabalhando com Array multi-dimensional

*Dica: Chamamos a função Image do pacote Ipython.display para carregarmos imagens no Jupyter Notebook, através do nosso diretório.

from IPython.display import Image
Image('Numpy.png')
exemplo de expressões e notações de fatiamento

Exemplos

Vejamos agora exemplos, de como utilizar o NumPy para o Slicing de objetos multidimensionais.

Criando Array

Começar criando uma matriz com a função array do NumPy, passando uma lista de listas em Python. A lista aninhada tem o objeto de criar uma Matriz.

array3 = np.array(
[[190, 290, 490], [129, 458, 567], [761, 902, 346]]); array3
array([[190, 290, 490],
[129, 458, 567],
[761, 902, 346]]
)

Slicing de Matriz

Retornar dessa matriz, o elemento que está na linha de índice 2 e na coluna de índice 1.

#Retornar elemento da terceira linha, segunda coluna
array3[2, 1]
902
array([[190, 290, 490],
[129, 458, 567],
[761, 902, 346]])

Atribuindo valor a um elemento

Imagine que tenhamos uma matriz com vários elementos, queremos mudar um elemento específico dessa matriz que temos. Podemos usar a indexação:

#Atribuir valor a um elemento da segunda linha, segunda coluna
array3[1, 1] = 10; array3
array([[190, 290, 490],
[129, 10, 567],
[761, 902, 346]])

Retornar terceira linha da Matriz

Podemos ainda retornar apenas um elemento dessa matriz, para isso estamos usando apenas uma notação com apenas um valor.

Com apenas o índice 2, tivemos todos os elementos daquela linha da matriz.

#Retornar terceira linha da Matriz
array3[2]
array([761, 902, 346])

Retornar terceira linha com outra notação

Usando outra notação que retorna o mesmo resultado. Esse tipo de notação evita problemas de legibilidade do código.

#Retornar terceira linha da Matriz - notação com vírgula
array3[2,]
array([761, 902, 346])

Retornar todas as linhas de uma coluna específica

Podemos retornar todas as linhas da segunda coluna da nossa matriz.

#Retornar todas as linhas da segunda coluna da Matriz
array3[:,1]
array([290, 10, 902])

Índice fora dos limites

E se o índice não existir?

# índice 5 está fora dos limites do eixo 0 de tamanho 3
array4 = np.array([100, 200, 300])
array4[5]
IndexError Traceback (most recent call last)
<ipython-input-20-305837fed46b> in <module> ----> 1 array4[5]
IndexError: index 5 is out of bounds for axis 0 with size 3

Slicing de Arrays

O

array5 = np.arange(50) * 2; array5
array([0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 98])

Retornar elementos específicos

Queremos retornar os elementos que comecem com o índice 5 até o índice 10, saltando de 2 em 2. O índice 10 é exclusivo, o elemento que está na posição de índice 10 não é retornado.

#Retornar elementos do índice 5 ao índice 10, step 2
array5[5:10:2]
array([10, 14, 18])

O conceito de Indexação em slicing, proporciona uma grande quantidade de possibilidades, podemos retornar os dados da estrutura de dados da forma que desejarmos

Retornar elementos até um índice

O índice de saída, não entra no retorno dos dados.

#Retornar todos os valores até o Index 4 (5° elemento exclusive)
array5[:4]
array([0, 2, 4, 6])

Retornar elementos a partir de um índice

# A partir do elemento de index 4 (oposto ao anterior)
array5[4:]
array([8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 98])

Saltando elementos do array

array5[::3]
array([0, 6, 12, 18, 24, 30, 36, 42, 48, 54, 60, 66, 72, 78, 84, 90, 96])

Slicing não altera o objeto

O array fica intacto, estamos apenas retornando partes consultadas desse array. Que inclusive, poderíamos gravar as partes para facilitar o manuseio.

#Slicing não altera o objeto original
array5
array([0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 98])

Atribuir valores a um intervalo

Como o índice 3 é exclusivo, os valores foram substituídos até o índice de valor 2. Portanto, os 3 primeiros elementos do array foram alterados.

#Retornar até o índice 3 exclusivo e atribuir valor a estes índices
array5[:3] = 1; array5
array([1, 1, 1, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 98])

Atribuir um array a outra parte de Array

Pegar tods os elementos até o índice 4 (exclusivo) e substitua por um outro array de números 1.

# Atribuindo um array a uma parte de outro array. Substituir tais índices por um array de 1, np.ones.array5[:4] = np.ones(4); array5
array([1, 1, 1, 1, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 98])

Quando aplicamos slicing, o nosso objetivo é buscar um subset do conjunto principal de dado, ou seja, dentro de uma estrutura de dados original.

Criando um subset de um array

Aplicando slicing, o objetivo o é buscar um subset (subconjunto) do conjunto de dados.

#Criar array de 12 elementos
array7 = np.arange(12); array7
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])

Faremos um slicing dentro do array7, o resultado será gravado no array 8. Contudo, o array7 continuará intacto, o que estamos fazendo aqui, é olhar para o array7, fazer uma consulta de acordo com a regra estabelecida na notação de indexação e em seguida gravando em um outro array. Isto é um subset

array8 = array7[::2]; array8
array([0, 2, 4, 6, 8, 10])

A principal vantagem disso, é que podemos carregar os dados em um estado bruto e depois consultar as partes dos dados que são interessantes para o processo de análise e fatiá-las para análise posterior. Muito fácil.

Copiando um array com np.copy

Podemos ainda criar uma cópia do Array — boa prática — muito útil. Trabalhamos com a cópia para que não surjam surpresas com a estrutura de dados.

Criamos abaixo o array9 com 8 elementos e depois aplicamos o método copy para gerar o nosso último array a ser estudado aqui, o array10.

array9 = np.arange(8); array9
array([0, 1, 2, 3, 4, 5, 6, 7])
array10 = array9.copy(); array10
array([0, 1, 2, 3, 4, 5, 6, 7])

Como aprender sobre tantos métodos e atributos?

Sim, é muita coisa. O importante é consultar a documentação, pesquisar dentro do Jupyter Notebook e verificar se existe ou não um atributo ou método para aquilo que desejamos executar. Estudar, estudar e estudar.

Obrigado.

Composing a repository of books (i bought), authors (i follow) & blogs (direct ones) for my own understanding.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store