Pular para o conteúdo

NumPy

Introdução

NumPy (Numerical Python) é uma biblioteca do Python que permite operações com vetores multidimensionais. Note que o Python não define vetor como uma das suas estruturas de dados. Uma lista do Python não é um vetor (array). Por exemplo, considere a soma das listas A e B como mostrada abaixo.

A = [1, 2, 3]
B = [4, 5, 6]
print(A + B)

O resultado gerado pelo programa mostra a concatenação das duas listas.

[1, 2, 3, 4, 5, 6]

Com NumPy, a mesma operação é definida por

import numpy as np
A = np.array ([1, 2, 3])
B = np.array ([4, 5, 6])
print(A + B)

Agora a resposta do programa corresponde à soma dos elementos correspondentes de cada posição (soma de vetores).

[5 7 9]

Exemplos

  • Exemplo: Lista as características do vetor unidimensional A e do vetor bidimensional B. Note que um vetor unidimensional possui uma única linha e pode ter uma ou mais colunas, enquanto um vetor bidimensional (também chamado de matriz) possui várias linhas e uma ou mais colunas.
import numpy as np
A = np.array ([0, 1, 2])
B = np.array ([[0, 1, 2], [3, 4, 5]])
for vetor in [A, B]:
   print("\n***** Vetor ", vetor, "\n")
   print(vetor)          # Mostra os valores do vetor
   print(vetor.ndim)     # Mostra número de dimensões do vetor
   print(vetor.shape)    # Mostra a forma do vetor
   print(vetor.size)     # Mostra o tamanho do vetor
   print(vetor.dtype)    # Mostra o tipo de dados dos elementos do vetor
   print(vetor.itemsize) # Mostra o tamanho de um elemento do vetor em bytes
   print(vetor.data)     # Mostra onde o vetor está alocado na memória

A resposta obtida é mostrada a seguir.

***** Vetor  [0 1 2] 

[0 1 2]
1
(3,)
3
int64
8
<memory at 0x7fdb13b21d80>

***** Vetor  [[0 1 2]
 [3 4 5]] 

[[0 1 2]
 [3 4 5]]
2
(2, 3)
6
int64
8
<memory at 0x7fdb13b8a0c0>

Observe que: a resposta da dimensão do vetor é uma tupla, por isso quando o vetor é unidimensional, aparece uma vírgula após o único elemento; os elementos dos vetores são números inteiros de 8 bytes (64 bits); a posição de memória ocupada pelo vetor (A ou B) pode variar a cada execução.

  • Exemplo: os vetores A, B e C são criados com o método arange(). Esse método retorna valores uniformemente espaçados dentro de um determinado intervalo. Os parâmetros do arange() são: valor inicial (o valor padrão é zero), valor final e o valor de incremento (o valor padrão é 1). Assim, o vetor A assume valores entre 0 e 12 com incremento de 1; o vetor B assume valores entre 0 e 12 com incremento de 3; e o vetor C assume valores entre 0,1 e 4,0 com incremento de 0,5. Note que o valor final, definido no método arange(), não faz parte do intervalo gerado.
import numpy as np
A = np.arange(12)
B = np.arange(0,12,3)
C = np.arange(0.1, 4.0, 0.5)
print(A)
print(B)
print(C)

A resposta do programa é

[ 0  1  2  3  4  5  6  7  8  9 10 11]
[0 3 6 9]
[0.1 0.6 1.1 1.6 2.1 2.6 3.1 3.6]
  • Exemplo: o método linspace() gera um vetor com uma determinada quantidade de números espaçados em um intervalo. No exemplo, o vetor A é composto por cinco números onde o primeiro número é zero, o último número é 3 e o espacejamento entre os números é 0,75. O vetor B é composto por 5 números de zero a 2,4 com espacejamento entre eles igual a 0,6. Neste caso, o valor final do intervalo não é considerado por causa do parâmetro “endpoint=False”, embora o espacejamento entre 2,4 e 3 também seja igual a 0,6. É importante observar que, se a quantidade de números do vetor não for fornecida, o método linspace() assume que o vetor deve ter 50 números igualmente espaçados.
import numpy as np
A = np.linspace(0, 3, 5)
B = np.linspace(0, 3, 5, endpoint = False)
print("A =", A)
print("B =", B)

Abaixo a resposta fornecida pelo programa.

A = [0.   0.75 1.5  2.25 3.  ]
B = [0.  0.6 1.2 1.8 2.4]
  • Exemplo: Cria duas matrizes quadradas de dimensão 2. As operações de soma e multiplicação são executadas com as duas matrizes.
import numpy as np
A = np.array ([[1, 2], [3, 4]])
B = np.array ([[3, 2], [1, 4]])
print("A + B =", A + B)
print("A * B = ", A * B)

A resposta é apresentada abaixo.

A + B = [[4 4]
 [4 8]]
A * B =  [[ 3  4]
 [ 3 16]]

Note que as operações são feitas entre os elementos de uma mesma posição das duas matrizes. Isto significa que, ao multiplicar os elementos de A pelos elementos de B, o resultado não é a multiplicação das duas matrizes, mas a multiplicação dos elementos que estão em posições correspondentes. Por exemplo, C[1][0] = A[1][0] * B[1][0] = 3 * 1 = 3.

  • Exemplo: Multiplicação de duas matrizes (A e B).
import numpy as np
A = np.array ([[1, 2], [3, 4]])
B = np.array ([[3, 2], [1, 4]])
C = np.array ([[0, 0], [0, 0]])
for i in range(len(A)):
    for j in range(len(B)):
        for k in range(len(A)):
            C[i][j] += A[i][k] * B[k][j]
print("C =", C)

A resposta mostra a multiplicação das matrizes A e B.

C = [[ 5 10]
 [13 22]]

Em resumo:

A = \begin{pmatrix} 1 & 2 \\ 3 & 4 \end{pmatrix} \hspace{0.5cm} B = \begin{pmatrix} 3 & 2 \\ 1 & 4 \end{pmatrix} \hspace{0.5cm} A \times B = \begin{pmatrix} 5 & 10 \\ 13 & 22 \end{pmatrix}
  • Exemplo: Considere as quatro matrizes mostradas abaixo. A matriz A é uma matriz nula (só possui zeros). A matriz B é uma matriz que só tem elementos com valor 1. A matriz C é uma matriz identidade (os elementos da diagonal principal são iguais a 1 e os outros elementos são iguais a zero). E a matriz D é uma matriz que só tem valores diferentes de zero na diagonal principal. Todas as matrizes são quadradas (número de linhas igual ao número de colunas) com dimensão igual a 5.
A = \begin{pmatrix} 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 \end{pmatrix} \hspace{0.5cm} B = \begin{pmatrix} 1 & 1 & 1 & 1 & 1 \\ 1 & 1 & 1 & 1 & 1 \\ 1 & 1 & 1 & 1 & 1 \\ 1 & 1 & 1 & 1 & 1 \\ 1 & 1 & 1 & 1 & 1 \end{pmatrix} \hspace{0.5cm} C = \begin{pmatrix} 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 \end{pmatrix} \hspace{0.5cm} D = \begin{pmatrix} 2 & 0 & 0 & 0 & 0 \\ 0 & 3 & 0 & 0 & 0 \\ 0 & 0 & 4 & 0 & 0 \\ 0 & 0 & 0 & 5 & 0 \\ 0 & 0 & 0 & 0 & 6 \end{pmatrix}

As matrizes A, B, C e D podem ser criadas pelo seguinte código Python:

import numpy as np
A = np.zeros((5, 5), dtype=int)
B = np.ones((5, 5), dtype=int)
C = np.eye(5, dtype=int)
D = np.diag(np.array([2,3,4,5,6]))
print ("A = ", A)
print ("B = ", B)
print ("C = ", C)
print ("D = ", D)

A saída do programa é mostrada abaixo. Observe que NumPy define uma matriz como um conjunto de vetores dentro de um vetor.

A =  [[0 0 0 0 0]
 [0 0 0 0 0]
 [0 0 0 0 0]
 [0 0 0 0 0]
 [0 0 0 0 0]]
B =  [[1 1 1 1 1]
 [1 1 1 1 1]
 [1 1 1 1 1]
 [1 1 1 1 1]
 [1 1 1 1 1]]
C =  [[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]]
D =  [[2 0 0 0 0]
 [0 3 0 0 0]
 [0 0 4 0 0]
 [0 0 0 5 0]
 [0 0 0 0 6]]
  • Exemplo: O determinante de uma matriz quadrada pode ser calculado usando a função det() do módulo linalg do NumPy. Considere duas matrizes com as seguintes definições:
A = \begin{pmatrix} 1 & 2 \\ 3 & 4 \end{pmatrix} \hspace{0.5cm} e \hspace{0.5cm} B = \begin{pmatrix} 3 & 2 \\ 1 & 4 \end{pmatrix} \hspace{0.5cm}

O programa abaixo calcula o determinante de A e o determinante de B.

import numpy as np
A = np.array ([[1, 2], [3, 4]])
B = np.array ([[3, 2], [1, 4]])
det_A = np.linalg.det(A)
det_B = np.linalg.det(B)
print("Determinante de A = %.2f" %det_A)
print("Determinante de B = %.2f" %det_B)

Sabemos que Det (A) = 1 \times 4 - 2 \times 3 = -2 e Det (B) = 3 \times 4 - 2 \times 1 = 10 . Portanto, a resposta do programa é:

Determinante de A = -2.00
Determinante de B = 10.00
  • Exemplo: A Prefeitura da Cidade do Rio de Janeiro disponibiliza o índice pluviométrico de 33 estações. A imagem abaixo mostra parte dos dados da Estação de Copacabana em janeiro de 2022. Note que a coleta de dados é feita a cada 15 minutos, sendo fornecidos os índices pluviométricos acumulados dos últimos 15 minutos, da última hora, das últimas 4 horas, das últimas 24 horas e das últimas 96 horas.

É possível usar uma matriz tridimensional para armazenar os dados pluviométricos de um mês de coleta. A primeira dimensão representaria o dia do mês, a segunda dimensão representaria o horário do dia e a terceira dimensão seria o índice pluviométrico acumulado em cada um dos intervalos definidos.

from xxlimited import Str
import numpy as np

nome = "copacabana_202201_Plv.txt"
arq = open(nome, 'r')
linha = arq.readlines()

num_dias = 31
num_reg  = 24 * 4   # registros a cada 15 min dentro de 1 hora
num_int  = 5        # 5 intervalos de chuvas (15min, 01h, 04h, 24h, 96h)

ind_plv = np.empty((num_dias, num_reg, num_int), dtype=Str)

for dia in range(0, num_dias):
    for hora in range(0, num_reg):
        i = dia * num_reg + hora + 5
        lista = linha[i].split()
        lista.pop(0)    # deleta data
        lista.pop(0)    # deleta hora
        #print(lista)
        for i in range(0, num_int):
            ind_plv[dia][hora][i] = lista[i]

Neste caso, ind_plv[0] corresponde ao primeiro dia do mês de janeiro, ind_plv[0][8] corresponde à coleta feita às 2 horas da manhã e ind_plv[0][8] [4] corresponde ao índice pluviométrico das 96h antes das 2h do primeiro dia de janeiro.