Enviar um café pro programador

Mostrando postagens com marcador Intervalos. Mostrar todas as postagens
Mostrando postagens com marcador Intervalos. Mostrar todas as postagens

Slicing e Indexing- Como fatiar, dividir e selecionar elementos e Intervalos de Arrays e Matrizes em Python

 No tutorial passado, aprendemos como acessar elementos, através da linha e da coluna, de um vetor unidimensional ou multidimensional. Agora, vamos aprender como selecionar intervalos dos arrays.

Essas técnicas de seleção, são de vital importância para filtrar dados. Imagine que você tenha um banco de dados com milhões de dados de pessoas, com linhas e colunas informando nome, idade, data de nascimento, local onde reside etc, e você vai querer filtrar apenas algumas coisas, como idade e profissão, então vai precisar fatiar essa matriz de informações. Isso já é Data Science.


Slicing Arrays - Fatiando e Selecionando Intervalos :

Vimos que através dos índices (index) selecionamos elementos específicos de um array, que podem simplesmente ser um número inteiro contado a partir o 0 para arrays unidimensional ou através de [linha][coluna] para acessar qualquer elemento de uma matriz de duas dimensões.

Porém, é muito comum querermos não apenas um elemento, mas uma faixa de elementos do array. Ou seja, temos que fatiar (slice) os vetores para obtermos apenas alguns dados específicos, e para isso vamos usar o operador de símbolo dois pontos :

Basicamente, vamos escrever inicio : fim, para selecionar os elementos de índice inicio até fim-1
Mais uma vez, lembre-se: a contagem de arrays começa no índice 0.


Slice de arrays unidimensionais

Suponha que temos um array de 10 elementos, do 0 até o 9.
Se quisermos selecionar os quatro primeiros, fazemos: 0:4 -

import numpy as np arr = np.array( [0,1,2,3,4,5,6,7,8,9]) print(arr[0:4])

Veja que ele pegou os elementos arr[0], arr[1], arr[2] e arr[3].

Agora, queremos fatiar do índice 5 até o 8:

print(arr[5:8])

Note que 8-5=3, logo, ele vai imprimir 3 elementos a partir do elemento de índice 5, que são os elementos: arr[5], arr[6] e arr[7].

Podemos, inclusive, selecionar o 'pulo' de elementos (step), dentro de cada intervalo dessas fatias. Quando fazemos m:n estamos fazendo, na verdade, m:n:1, pois estamos imprimindo de 1 em 1.

O código abaixo, usando m:n:2 percorre todos os elementos do array, mas pulando de 2 em 2:

import numpy as np arr = np.array( [0,1,2,3,4,5,6,7,8,9]) print(arr[0:10:2])

Se quiser exibir todos os elementos de um array, deixe em branco os índices do slicing, basta fazer: arr[:]
Pois ele entende que é do primeiro até o último índice. Isso valo se você preencher apenas o início ou fim. Por exemplo, para imprimir do primeiro índice até 5, faça: arr[:6]
Já para fatiar o array do índice 5 até o final, faça: arr[5:]

Rode cada um dos códigos e exemplos acima, para ver o resultado.

Slice e Index ao contrário, do final do array

Veja que esses fatiamentos foram sempre do começo para o fim do array. Mas também é possível fazer isso do final para o começo, bastante usar como index os números inteiros negativos. Por exemplo:

arr[-1] - último elemento do array
arr[inicio:-1] - fatia do índice inicio até o último
arr[1:-1] - quebra a partir do segundo elemento (índice 1) até o último (que é o de índice -1)
arr[ : : -1] - exibe todos os elementos mas do final pro começo, de 1 em 1

Questão: Como exibir todos os elementos de um array, do final para o início, de dois em dois?


Slicing e Indexing em arrays multidimensionais

Podemos, também, fatiar matrizes, ou seja, arrays de mais de uma dimensões. Agora, precisamos trabalhar com as linhas e colunas. Geralmente vamos precisar extrair determinadas linhas ou colunas de uma matriz, através do slicing e indexing.

Seja a matriz arr 3x3:
[1,2,3],
[4,5,6],
[7,8,9]

Para lidar com duas dimensões, vamos precisar usar o símbolo de slice : duas vezes, uma para as linhas e outro para as colunas, e vamos separar os fatiamentos por vírgula. Por exemplo, para exibir todos os elementos da matriz, fazemos:

arr[: , :]

Se quisermos, por exemplo, exibir a primeira coluna:

arr[: , 0]

Você pode interpretar a primeira parte, antes da vírgula como "todos os elementos da linha", e o segundo elemento, depois da linha, como o índice da coluna. Ou seja, todos os elementos das linhas (:), mas que estejam na primeira coluna (0).

Agora, para fatiar e extrair apenas a segunda linha da matriz:

arr[1 ,  :]

Agora vamos extrair uma submatriz, composta pelos dois primeiros elementos, da linha 1 e linha 2, das colunas 1 e 2:

arr[:2 , :2]

Cujo resultado é:
[1,2]
[4,5]

Agora vamos extrair somente a primeira e terceira linhas:

arr[ [0,2] , :]

Já a primeira e terceira coluna:

arr[ : , [0,2] ]

Rode o exemplo abaixo, agora com uma matriz maior, 5x5:

import numpy as np arr = np.array([ [11,12,13,14,15], [21,22,23,24,25], [31,32,33,34,35], [41,42,43,44,45], [51,52,53,54,55]]) print("Todos:\n" ,arr[: , :]) print("Primeira coluna:\n", arr[:, 0]) print("Segunda linha:\n", arr[1, :]) print("Sub-matriz 3x3:\n", arr[:3, :3]) print("Primeira e última linha:\n", arr[[0,4], :]) print("Primeira e última coluna:\n", arr[:, [0,4]])

Deixando bem claro que neste tutorial dissemos como exibir tais informações, porém podemos usar os mesmos códigos para atribuir valores esses arrays que determinamos ou também podemos pegar esses slices e salvar como outro array e trabalhar com eles, deixando o original intocado.

NumPy - Como criar e inicializar Arrays em Python

 Neste tutorial, vamos te ensinar como usar a biblioteca NumPy para declarar, inicializar e usar Arrays em Python.

Este tutorial faz parte de nosso curso Programação Científica - Computação Numérica e Data Science com Python.


Como importar o módulo NumPy

Para podermos usar a biblioteca NumPy, a primeira coisa que temos que fazer é...'colocar' ela em nosso código. Ou seja, deixar claro para o Python que iremos usar o módulo numpy, e fazemos isso com o comando import

  • import numpy

Agora, basta usarmos o nome numpy seguido de um ponto, e em seguida o recurso que você deseja acessar/usar, da biblioteca. Por exemplos, para imprimirmos o valor do número pi:

  1. import numpy
  2. print(numpy.pi)

Teste sempre nossos exemplos de código. Sempre.

Porém, é bem comum darmos algum 'apelido' para essas bibliotecas, geralmente algum nome mais curto e simples, para evitar ficarmos repetindo um comando maior. Por exemplo, vamos dar o apelido de 'np' para a NumPy:

  1. import numpy as np
  2. print(np.e)

No exemplo acima, pegamos o valor da constante de Euler, muito usada em logaritmos.


Como criar Arrays a partir de Listas e Tuplas

Vamos usar a função numpy.array() para criar e inicializar nossos arrays com valores específicos. No exemplo a seguir, vamos passar a lista [1, 2, 3]:

import numpy as np MeuArray = np.array( [1,2,3] ) print(MeuArray)

Saída: [1 2 3]

Agora, vamos primeiro criar uma variável de nome MinhaTupla, colocar uma Tupla contendo strings nela e passar essa variável direto para a função array():

import numpy as np MinhaTupla = ("Python", "Java", "C++") MeuArray = np.array( MinhaTupla ) print(MeuArray)

Saída: ['Python' 'Java' 'C++']

Para criarmos arrays multidimensionais, basta ir separando as sequências (listas ou tuplas) por vírgulas. Por exemplo, vamos criar uma matriz 3x3 de floats:

import numpy as np MeuArray = np.array([ [1.1, 2.4, 5.4], [5.5, 7.6, 8.9], [9.1, 0.0, 2.1] ]) print(MeuArray)

Saída:
[[1.1 2.4 5.4]
 [5.5 7.6 8.9]
 [9.1 0.  2.1]]

Veja que a as três listas estão dentro de um par de colchetes também.

Inicializando Arrays com Zeros e Um

Muitas vezes, em exatas, vamos precisar inicializar vetores e matrizes com alguns números constantes, como 0 e 1.

Por exemplo, se você vai contar algo, precisa que sua variável parta do 0, logo você tem que inicializar ela com zero. Outras vezes, como em Álgebra Linear, podemos querer inicializar uma matriz com todos seus elementos tendo valores 1.

Para isso, usaremos as funções numpy.zeros() e numpy.ones(), respectivamente.
Para isto, basta passarmos as dimensões do array que você quer inicializar.

Por exemplo, um array de valores nulos, com 5 elementos:

import numpy as np MeuArray = np.zeros(5) print(MeuArray)

Já para criar uma matriz de 4x3 preenchidas de valores unitários, fazemos:

import numpy as np MeuArray = np.ones( (4,3) ) print(MeuArray)

Note que colocamos as dimensões dentro de um par de parêntesis.

E se quisermos um array todo preenchido com o valor de Pi, por exemplo?
Muito simples, basta multiplicar o valor de Pi pela função ones():

import numpy as np MeuArray = np.pi * np.ones( 10 ) print(MeuArray)

Note que para inicializar um arrays com valores diferentes de 0 e 1, usamos dois passos: invocar a função zeros() ou ones() e depois multiplicar. É possível fazer isso chamando apenas uma função, a full(), onde primeiro informamos a dimensão de nosso array e em seguida o valor que queremos inicializar todos os elementos.

Por exemplo, uma matriz 2x2 toda inicializada com o valor 2112:

import numpy as np MeuArray = np.full((2,2),2112) print(MeuArray)

arange(): inicializando um array com uma sequência numérica

Temos no módulo NumPy uma função semelhante a função range() do Python, mas para lidarmos de maneira bem eficiente com arrays, é a arange().

Por exemplo, se quisermos um array com os 100 primeiros números inteiros, fazemos simplesmente:

import numpy as np MeuArray = np.arange(100) print(MeuArray)

Saída:
[ 0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99]

Importante notar que, na arange(), ao fornecermos um valor n, o NumPy vai inicializar com os valores de 0 até n-1, ou seja, nunca inclui o número n.

A arange() vai mais além (assim como a range() ). Podemos definir o ponto inicial, o final e o step ou pulo, que os valores vão dar. Por exemplo, para inicializar os elementos de um array com todos os números pares, de 0 até 100 (incluindo este), fazemos: 

import numpy as np MeuArray = np.arange(0,101,2) print(MeuArray)

Saída: [  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 100]

linspace(): definindo o número de intervalos da sequência

Se usarmos valores do tipo float (decimais), a arange() irá fazer alguns arredondamentos, o que pode acarretar um problema: não sabermos quantos valores o array terá.

Para contornar isso, temos uma função bem parecida, a linspace(), onde vamos deixar bem claro quantos intervalos teremos:

  • numpy.linspace(inicio, fim, numero_termos)

Ou seja, não vamos definir o valor do step e sim o número de intervalos que queremos.
Por exemplo, para termos um array com valores de 0 até 10, divididos em 11 espaçamentos, fazemos:

import numpy as np MeuArray = np.linspace(0, 10, 11)

Saída: array([ 0.,  1.,  2.,  3.,  4.,  5.,  6.,  7.,  8.,  9., 10.])

Note que, na saída anterior, o valor 10 apareceu. Na linspace(), o elemento final aparece, diferente da arange(). Note também que o resultado da linspace() está em formato float (com casas decimais).
Recomendamos usar a arange() com valores inteiros e a linspace() com valores decimais.

Veja bem, o step na arange() é para você incrementar a sequência de step em step.
O step na linspace() é para você definir quantos intervalos você quer quebrar a sequência (inicio,fim)

Em nossa apostila Programação Científica em Python, vamos te mostrar e explicar o código para produzir o gráfico abaixo, usando a linspace(), de uma função seno, variando de 0 até 2pi:

Como plotar figuras em Python com NumPy e matplotlib

Como criar array de matrizes

O NumPy também oferece uma vasta de opções para trabalharmos diretamente com matrizes.
Por exemplo, para criar uma matriz identidade de dimensão 5 (ou seja, uma matriz com os elementos da diagonal principal com valor 1 e valor 0 para os demais), usamos a função identity():

import numpy as np matriz = np.identity(5)

Saída:

array([[1., 0., 0., 0., 0.],
       [0., 1., 0., 0., 0.],
       [0., 0., 1., 0., 0.],
       [0., 0., 0., 1., 0.],
       [0., 0., 0., 0., 1.]])

Podemos também 'deslocar' essa diagonal de valor, usando a função eye(), que recebe dois argumentos:

  1. O primeiro é o da dimensão da matriz
  2. O segundo é o argumento k, que é o offset, ou seja, o deslocamento. Se for positivo, subimos essa diagonal de 1's e se for negativo, descemos a diagona de números 1

Por exemplo, uma matriz de dimensão 6 com a diagonal deslocada para a diagonal imediatamente acima:

import numpy as np matriz = np.eye(5,k=1)

Saída:

array([[0., 1., 0., 0., 0.],
       [0., 0., 1., 0., 0.],
       [0., 0., 0., 1., 0.],
       [0., 0., 0., 0., 1.],
       [0., 0., 0., 0., 0.]])

Agora uma matriz de dimensão 7, com um offset de dois:

import numpy as np matriz = np.eye(7,k=-2)

Saída:

array([[0., 0., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0., 0.],
       [1., 0., 0., 0., 0., 0., 0.],
       [0., 1., 0., 0., 0., 0., 0.],
       [0., 0., 1., 0., 0., 0., 0.],
       [0., 0., 0., 1., 0., 0., 0.],
       [0., 0., 0., 0., 1., 0., 0.]])

Também é possível criar uma matriz cuja a diagonal principal recebe uma lista qualquer de valores, para isso bastando usar a função diag(). A dimensão de nossa matriz será a mesma dessa sequência de valores. Por exemplo, uma matriz de dimensão 10 com os números 0, 1, 2, 3, 4, 5, 6, 7, 8 e 9:

import numpy as np matriz = np.diag( np.arange(0,10,1) )

Saída:

array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 1, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 2, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 3, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 4, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 5, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 6, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 7, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 8, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0, 9]])

Essa função também aceita um argumento k de offset.

Exercício: que valor devemos passar para a função eye() para que ela seja igual a identity()? Ou seja, para preencher a diagonal principal.