Enviar um café pro programador

Mostrando postagens com marcador range. Mostrar todas as postagens
Mostrando postagens com marcador range. 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.

Exercícios de Arrays e Matrizes em Python

 Agora que já estudamos arrays, vamos praticar nossos conhecimentos na biblioteca numpy e praticar com exercícios. Estude antes:

E mais uma vez vamos reforçar: tente. Tente resolver as questões, sozinho, pense, quebre a cabeça...normal errar, não conseguir, faz parte. Mas tem que tentar, só assim você vai evoluir, tanto como programador Python tanto como cientista.

Questões de Array e Matriz

00. Qual a relação matemática entre len(arr), len(arr[0]) e  o atributo size?

01. Crie uma função sum() que recebe um array unidimensional e retorna a soma de seus elementos, usando apenas o atributo size do NumPy.

02. Crie uma função square_matrix(), que verifica se a matriz recebida é quadrada ou não. Matriz quadrada é aquela que o número de linhas é o mesmo do de colunas.

03. Crie uma função chamada trace() que recebe uma matriz quadrada e retorna o seu traço, ou seja, a soma dos elementos da diagonal principal. Lembrando que somente matrizes quadradas possuem traço.

04. Crie uma função sum_matrix() que recebe duas matrizes e retorne uma matriz com a soma destas duas matrizes anteriores. Lembre-se que só podemos somar matrizes que tenham mesmo número de linhas e colunas, seu script deve checar isso antes de somar.


Soluções e código comentado dos exercícios

  • Questão 00

O comando len(arr) vai mostrar quantos elementos tem o array. Se ele for um array unidimensional, ele vai mostrar quantos elementos tem naquele array. Se for uma matriz, ele vai mostrar o número de linhas na matriz, pois cada linha é um novo elemento (um novo array).

Por exemplo, o elemento arr[0] é a primeira linha da matriz arr, logo, o comando len(arr[0]) vai mostrar quantos elementos tem o array unidimensional arr[0], ou seja, quantas colunas esse array unidimensional tem. Mas, todas as linhas de uma matriz possuem o mesmo número de colunas. Logo, o comando len(arr[0]) exibe o número de colunas de uma matriz.

O atributo size dos arrays mostra o número TOTAL de elementos de uma matriz. Por exemplo, se tiver um array 5x6 de nome arr e usar o comando arr.size, vai ver que ele é um inteiro de valor 5*6=30

Ou seja, o size mostra o valor da multiplicação do número de linhas pelo número de colunas, então, para uma matriz: arr.size = len(arr) * len(arr[0])

  • Questão 01

O atributo size nos fornece a quantidade de elementos que existe em um array qualquer. Se esse valor é n e jogarmos esse valor dentro da função range(), ela vai iterar do elemento 0 até o elemento n-1 do array. Ou seja, vai percorrer todo o array:

import numpy as np def sum(arr): soma=0 for i in range(arr.size): soma += arr[i] return soma arr = np.array([1, 2, 3, 4, 5]) print("Soma dos elementos: ", sum(arr))

Ou seja, pegamos uma variável soma, inicializamos ela com o valor 0 e em seguida vamos adicionando elemento por elemento do array.

  • Questão 02

Vimos na questão 00 que o número de linhas do vetor arr é dado por len(arr) e o número de colunas é dado por len(arr[0]), então para saber se uma matriz é quadrada, basta verificar se esses dois valores são iguais:

import numpy as np def square_matrix(arr): if len(arr) == len(arr[0]): return True else: return False arr1 = np.array([ [1,2,3], [4,5,6], [7,8,9] ]) arr2 = np.array([ [1,2,3,4],[1,2,3,4] ]) print(square_matrix(arr1)) print(square_matrix(arr2))


  • Questão 03

Primeiro, antes de calcular o traço da matriz, precisamos saber se ela é quadrada, portanto vamos deixar o código da função square_matrix() da questão anterior neste caso. Então, a primeira coisa da função trace() é checar se a função é quadrada. Se for, calcula o traço no teste condicional if, se não for, retorna None no else.

Os elementos da diagonal principal de uma matriz arr são arr[0][0], arr[1][1], arr[2][2]...ou seja, todos os elementos do tipo arr[i][i], de mesmo índice de linha e coluna.

Então, o traço é dado pela soma: arr[0][0] + arr[1][1] + arr[2][2] + ... + arr[n-1][n-1] , onde n é a ordem da matriz, ou seja, o número de linhas ou colunas (já que ela é quadrada).

Para fazer esse cálculo no código Python, definimos uma variável de valor inicial 0 e vamos somando os elementos da diagonal inicial de índice 0 até n-1, através da range():

import numpy as np def square_matrix(arr): if len(arr) == len(arr[0]): return True else: return False def trace(arr): sum=0 if square_matrix(arr): for i in range(len(arr)): sum += arr[i][i] return sum else: return None arr1 = np.array([ [0,2,3], [4,5,6], [7,8,9] ]) arr2 = np.array([ [1,2,3,4], [1,2,3,4] ]) print(trace(arr1)) print(trace(arr2))


  • Questão 04

.A primeira coisa que a função deve fazer é testar se o número de linhas são iguais e o número de colunas também são iguais entre si. Somente assim podemos somar as duas matrizes.

Se ambas matrizes tiverem o mesmo número de linhas lin=len(arr) e o mesmo número de colunas col=len(arr[0]), então criamos uma matriz vazia (empty), com tal tamanho.

Agora, basta preencher os elementos da matriz. Para isso, usamos um laço for de 0 até lin-1 e outro laço aninhado, de 0 até col-1, então para cada elemento matrix[lin][col] colocamos a soma arr1[lin][col]+arr2[lin][col]

import numpy as np

def sum_matrix(arr1, arr2):
if len(arr1)==len(arr2) and len(arr1[0])==len(arr2[0]):
matrix = np.empty( (len(arr1), len(arr1[0])) )
else:
return None
for lin in range(len(arr1)):
for col in range(len(arr1[0])):
matrix[lin][col] = arr1[lin][col] + arr2[lin][col]
return matrix


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

arr2 = np.array([ [1,1,1],
[2,2,2],
[3,3,3],
[0,0,0]])

print(sum_matrix(arr1, arr2))

Listas e o Laço For

Neste tutorial de nosso Curso de Python, vamos ver um uso bem especial do laço for: com as listas!

Veja também:
Curso Python Progressivo em PDF
Certificado do Curso para trabalhar como desenvolvedor Python

O Laço FOR com Listas em Python


Duas coisas que se casam e trabalham incrivelmente bem são: listas e laço for.
Usaremos o laço for para iterar a lista, ou seja, acessar item por item.

Mas, vamos ver com exemplos!

Exemplo 1 de laço FOR com Listas

Faça um script que cria uma lista de 10 elementos, preenchendo eles de 0 até 9, usando laço for.
Depois, printe essa lista.

Inicialmente, criamos nossa lista numeros.
No começo ela está vazia.

Vamos usar um iterador, uma variável count que vai de 0 até 9, através da função range.
Lembramos que count é um número, para concatenar ele, precisamos transformá-lo antes num lista: [count]

A cada looping do laço for, concatenamos nosso número na lista, veja:

numeros = []

for count in range(10):
    numeros += [count]

print(numeros)



Exemplo 2 de laço FOR e Listas 

No exemplo anterior, foi exibida uma lista no seguinte formato:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

Use o laço for para exibir ela sem colchetes e vírgulas um número por linha.

Agora, ao invés de percorremos os elementos da função range (que retorna algo a uma lista), vamos usar nossa própria lista numeros.

Ou seja, o count vai iterar, assumir o valor de cada item da lista, um por um, e imprimimos essa variável:
numeros = []

for count in range(10):
    numeros += [count]

for count in numeros:
    print(count)




Exemplo 3 de laço FOR e Listas 

Faça com que o script anterior também calcule a soma de todos os elementos na lista numeros e exiba seu resultado.

Vamos armazenar o valor numa variável chamada soma, que inicializamos como 0.
A cada iteração, somamos o valor de count a ela, como o count vai receber o valor de cada item da lista, teremos a soma de todos os termos da lista:

numeros = []

for count in range(10):
    numeros += [count]

soma=0
for count in numeros:
    print(count)
    soma += count

print("Soma: ", soma)


Note que nem precisamos de um novo laço for, usamos o laço que imprime cada item, um por linha.

Exemplo 4 de laço FOR e Listas 

Faça um script que exibe uma lista de 10 elementos, contados de 1 até 10.
Depois, dobre cada valor dessa lista e exiba. Veja que agora são todos pares.

Preenchemos a lista com valores de 1 até 10, usando range(1,11).
Depois, temos que ir em termo por termo, do índice 0 até o índice 9, para dobrar os valores ali contidos.

Para acessar todos os elementos, vamos usar uma range que vai de 0 até ... o tamanho da lista, que é len(numeros).

numeros = []

for count in range(1,11):
    numeros += [count]

for count in range(len(numeros)):
    numeros[count] = numeros[count]*2
    
for count in numeros:
    print(count)

Poderíamos ter feito apenas: numeros[count] *= 2

Exemplo 5 de laço FOR e Listas 

Faça um script que exiba a uma lista que tem os números de 1 até 10, na seguinte maneira:
Numero  1:  1
Numero  2:  2
Numero  3:  3
Numero  4:  4
Numero  5:  5
Numero  6:  6
Numero  7:  7
Numero  8:  8
Numero  9:  9
Numero 10: 10

Aqui tem uma pegadinha.
Para imprimir, vamos usar a range( len(numeros) ), assim o laço percorre todos os índices da lista.
Porém, o primeiro índice é 0.

Se printarmos a variável count direto, ia aparecer:
Número 0: 1
Número 1: 2 etc

Ou seja, temos que adicionar 1 na hora de imprimir:

numeros = []

for count in range(1,11):
    numeros += [count]

for count in range(len(numeros)):
    print("Numero %2d: %2d" %(count+1, numeros[count]))


Exemplo 6 de laço FOR e Listas 

Faça um script que peça ao usuário o número de matérias da escola, ou seja, um inteiro positivo.
Em seguida, ele vai digitando o valor de cada nota, de cada matéria e isso será armazenado numa lista.
Ao final, seu script deverá fornecer a média geral do aluno.
Primeiro, perguntamos ao usuário quantas matérias ele fez provas, e armazenamos em n.
Depois, criamos uma lista vazia, para as notas, bem como inicializamos a variável soma com valor 0, ela vai somar todas as notas.
Dentro do for, temos que preencher n notas, fazemos isso com a função range.
Perguntamos cada nota (imprimimos count+1, para os índices aparecerem bonitinho para o usuário, lembre-se que para ele a contagem não começa em 0, como começa para nós programadores) e vamos adicionando cada nota como uma lista, concatenando na lista maior notas.
Somamos o valor de soma com cada nota digitada.
No final, dividimos o valor dessa soma pelo número de matérias que o aluno fez provas, e temos a média geral dela.
Nosso código Python fica:
n = int(input("Numero de materias: "))
notas = []
soma=0

for count in range(n):
    nota=float(input("Nota da materia %2d: " % (count+1)))
    notas += [nota]    
    soma += nota

print("Notas: ",notas)
print("Media: %.2f" % (soma/n))


Exercícios Propostos

1. Faça um script que pede ao usuário um número inteiro positivo.
Em seguida, deve criar uma lista onde o primeiro termo é 0, o segundo é 1 e os outros são a sequência de Fibonacci. O número de termos é o que o usuário forneceu como número.

2. Faça um script que pede um número inteiro positivo ao usuário.
Em seguida, cria uma lista com igual número de itens, onde o primeiro termo é 1!, o segundo é 2!, o terceiro é o valor de 3!, etc, até o termo que ele digitou. Ou seja, se digitou n, vai exibir até o termo de índice n-1, e lá na lista vai ter o valor de (n-1)!.

Resolução desses exercícios no e-book

Jogando Dados com Python - Estatística e Probabilidade

Neste tutorial de Python, vamos envolver programação e Matemática, especificamente estatística e probabilidade, e vamos comprovar na prática que elas existem e funcionam!

Leia também:

Jogando os Dados com o Python


Para gerar nossos números aleatórios de 1 até 6, vamos definir a função gera() que não tem nenhum parâmetro e vai, obviamente, retornar número inteiro de 1 até 6.

Para isso, vamos usar a função randint da biblioteca random.
Se não leu nosso tutorial, veja: Como gerar números aleatórios em Python

Essa função recebe os argumentos 1 e 6, parar gerar inteiros de 1 até 6. E para usar ela, temos que importar o módulo random.
Ela fica:

import random

def gera():
    return random.randint(1,6)

Agora, vamos criar a função repete(n), que vai repetir n lançamentos de dados, onde n o usuário vai escolher quantas vezes vai jogar os dados.

Vamos armazenar os resultados 1, na variável test1.
Vamos armazenar os resultados 2, na variável test2.
...
Vamos armazenar os resultados 6, na variável test6.

Então inicializamos essa variável com todas elas igual a 0.

Agora vamos fazer um laço for pra rodar n vezes o lançamento de dados.
Cada vez que lança o dado (simplesmente chamando a função gera() - uma maravilha função né?), armazenamos na variável test.

Em seguida, vamos fazer várias comparações com IF, ELIF e ELSE, para saber se o valor do dado é 1, 2, 3, 4, 5 ou 6. E quando achar o valor certo, incrementar em 1 o valor da variável test1, ou test2 ou ... test6.

Ou seja, ao final do laço for, as variáveis test1, test2, ..., test6 terão quando vezes foi sorteado o número 1, 2, 3, 4, 5 e 6 respectivamente.

Então simplesmente damos seis prints, para exibir quantas vezes cada número saiu, bem como mostramos a porcentagem de frequência de cada valor,





Veja o código:

import random

def gera():
    return random.randint(1,6)

def repete(n):
    test1=test2=test3=      \
    test4=test5=test6 = 0
    for val in range(n):
        test = gera()

        if(test==1):
            test1 += 1
        elif(test==2):
            test2 += 1
        elif(test==3):
            test3 += 1
        elif(test==4):
            test4 += 1
        elif(test==5):
            test5 += 1
        else:
            test6 += 1
            

    print("Numero 1 saiu ", test1," vezes = ",(test1/n)*100, " %")
    print("Numero 2 saiu ", test2," vezes = ",(test2/n)*100, " %")
    print("Numero 3 saiu ", test3," vezes = ",(test3/n)*100, " %")
    print("Numero 4 saiu ", test4," vezes = ",(test4/n)*100, " %")
    print("Numero 5 saiu ", test5," vezes = ",(test5/n)*100, " %")
    print("Numero 6 saiu ", test6," vezes = ",(test6/n)*100, " %")

        
def menu():
    n = int(input('Quantos lançamentos de dado? '))
    repete(n)
    
while True:
    menu()

PS 1: Quanto maior for o n, mais a porcentagem se aproxima de 16,67% pois vai tendendo à probabilidade, que é de 1/6 .

PS 2: Mais na frente, quantos estudarmos sequências, você aprenderá maneiras mais simples de se trabalhar com várias variáveis de uma vez só.