Introdução à programação e aos algoritmos
5.14 Numpy
Por serem imutáveis, as tuplas também são mais rápidas e mais
econômicas em espaço de memória que as listas. Como uma lista tem métodos que podem fazê-la crescer, Python reserva mais memória que o necessário para armazenar os elementos de uma lista. A tupla tem sempre o mesmo tamanho.
EXERCÍCIO 5.31
Escreva um programa que crie uma tupla com todos os números entre 100 e 1000
que são divisíveis por 7 mas não são múltiplos de 3.
EXERCÍCIO 5.32
Modi que o Programa 4.16 de modo que a função que gera coordenadas
aleatórias receba como parâmetro o número de coordenadas que precisam ser
geradas e devolva uma lista de tuplas com essas coordenadas. Deste modo, a
função que calcula o valor de pi também precisa ser modi cada para tratar essas
coordenadas em forma de lista de tuplas.
EXERCÍCIO 5.33
Os dicionários de Python não são ordenados, pois sua função principal é a busca
rápida de uma informação baseada em uma chave. Modi que o programa sobre
aeroportos desta seção para trabalhar apenas com tuplas, eliminando o dicionário
e usando o nome da cidade como primeiro elemento da tupla.
5.14 NUMPY
As listas de Python não são verdadeiros vetores. Apesar de serem bem flexíveis, não são eficientes para trabalhar com cálculo científico. Queremos poder trabalhar com matrizes no sentido matemático.
Para isso foi criado o módulo numpy, o Python numérico que fornece a base para cálculos científicos com matrizes de maneira muito mais eficiente que as listas.
Primeiro, você precisa instalar o módulo numpy. Este módulo não vem por padrão nas instalações de Python. Por isso, em um terminal, digite:
pip3 install numpy
Depois disso você já pode importar o módulo numpy para os seus programas.
Vejamos um exemplo simples para evidenciar a diferença básica entre listas e numpy. Execute o Programa 5.38.
import numpy as np
a = [1, 2, 3]
b = [4, 5, 6]
c = a + b
print (c)
a_num = np.array(a)
b_num = np.array(b)
c_num = a_num + b_num
print (c_num)
■ Programa 5.38: Diferenças entre listas e numpy.
Executando o programa, obtemos:
[1, 2, 3, 4, 5, 6]
[5 7 9]
No primeiro caso, com as listas de Python, houve uma concatenação e as duas listas criaram uma lista que é a justaposição das duas. No segundo caso, com o array de numpy, houve o que esperamos da adição de duas matrizes: cada elemento foi somado com seu correspondente da outra matriz, resultando em um array de mesmo tamanho.
A manipulação de vetores e matrizes é muito facilitada em
relação às listas de Python. Digamos que você tenha uma lista com as notas de um aluno e uma outra com os pesos de cada nota. O processamento desses dados com os comandos usuais de Python não é complicado, mas com numpy se torna brincadeira de criança. Veja o Programa 5.39.
import numpy as np
notas = np.array([5, 9, 5.5, 10, 8])
pesos = np.array([1, 2, 4, 1, 2])
notas_ponderadas = notas * pesos
media = np.sum(notas_ponderadas)/np.sum(pesos)
print(‘Média =’, media)
■ Programa 5.39: Cálculo de média com numpy.
O programa imprime o resultado correto da média ponderada
das notas, 7,1. Na realidade, numpy pode calcular a média ponderada diretamente, sem que você tenha de calcular antes as notas ponderadas (Programa 5.40).
import numpy as np
notas = np.array([5, 9, 5.5, 10, 8])
pesos = np.array([1, 2, 4, 1, 2])
media = np.average(notas,weights=pesos)
print(‘Média =’, media)
■ Programa 5.40: Cálculo de média ponderada.
Na chamada da função average() usei a passagem de
parâmetros com a nomeação explícita do argumento dos pesos, pois a sintaxe completa de average() é:
average(a, axis=None, weights=None, returned=Fals
e)
que pode selecionar o eixo no qual será feita a operação.
As operações de fatiamento também funcionam com arrays de numpy. Por exemplo, podemos definir as notas e os pesos em um só array de numpy e usar o fatiamento para escolher a linha de pesos (Programa 5.41).
import numpy as np
notas_e_pesos = np.array([[5, 9, 5.5, 10, 8], [1, 2, 4, 1, 2]])
media = np.average(notas_e_pesos[0], weights=notas_ e_pesos[1,:])
print(‘Média =’, media)
■ Programa 5.41: Cálculo de média ponderada com
fatiamento.
Como você pode perceber, numpy permite a sintaxe notas_e_pesos[1,:] para referenciar a segunda linha do array. Nada impede, no entanto, que você utilize a sintaxe usual das listas: notas_e_pesos[1][:].
Outra característica bem útil de array sobre as listas é a indexação por valores booleanos, ou seja, True e False. Os elementos True são escolhidos e os elementos False são ignorados. Pode-se criar facilmente um array de valores booleanos a partir de algum critério seletivo no array e depois aplicá-lo aos elementos do array. O Programa 5.42 apresenta um exemplo:
import numpy as np
notas = np.array([5, 9, 5.5, 10, 8.4])
print(notas > 6)
print(‘Notas > 6:’,notas[notas > 6])
print(‘Notas <= 6:’,notas[notas <= 6])
■ Programa 5.42: Índices booleanos.
O resultado da sua execução é:
[False True False True True]
Notas > 6: [ 9. 10. 8.4]
Notas <= 6: [ 5. 5.5]
Podemos usar diretamente operações de comparação com o
array de numpy. No caso, foi feita a comparação para escolher as notas maiores que 6. Essa comparação gerou o array [False True False True True] . Poderíamos usar o array booleano criado como índice, mas é preferível fazer a operação diretamente, como em notas[notas > 6], que gera o array e o utiliza imediatamente.
Dica 5.5 – Cuidados quando usar numpy.
Os arrays de numpy são bem semelhantes às listas, porém guardam algumas
diferenças que podem causar erros no seu programa. Por exemplo, enquanto as listas
aceitam qualquer tipo de elemento, os arrays de numpy exigem que seus elementos
sejam todos do mesmo tipo. Assim, se você de ne um array como:
a = np.array([‘Python’, 1, 2, 3])
este não será um array misto. Todos os números serão convertidos em string, e
você obtém o seguinte array:
[‘Python’ ‘1’ ‘2’ ‘3’]
O Programa 5.43 mostra, além desse, outro aspecto relevante:
import numpy as np
a = np.array([‘Python’, 1, 2, 3])
print(a)
a = [1, 2, 3, 4, 5]
b = a[1:]