Escrito por Leonardo Bartoccini
Tópicos abordados
- O que é NumPy e para que serve
- Criação e manipulação de arrays
- Extração e manipulação de dados
- Realização de operações matemáticas
- Manipulação de bases de dados simples
Disclaimer
Essa aula assume que você possui conhecimentos básicos de programação em Python. Caso não seja o seu caso, recomendamos que você acesse a página de Recursos Externos, que oferece opções de cursos introdutórios de programação em Python, deep learning e outros temas. Você deve familiarizar-se com a sintaxe básica e com estruturas de dados, como matrizes, para compreender essa aula na totalidade.
Introdução
NumPy é a principal biblioteca de código aberto para computação científica em Python, essencial para a manipulação de dados em larga escala. Isso se deve, principalmente, à presença de uma estrutura de matriz extremamente eficiente e rápida para a realização de operações matemáticas. Dessa forma, o aprendizado de NumPy é essencial para o machine learning, uma vez que é a base de bibliotecas como Pandas, Matplotlib e Scikit-learn, que veremos nas próximas aulas.
Funcionalidades Básicas
Primeiramente, para instalar a biblioteca, basta executar !pip install numpy em uma célula de código do Jupyter Notebook (o ‘!’ indica que o código deverá ser executado no terminal).
!pip install numpy
Requirement already satisfied: numpy in /Library/Frameworks/Python.framework/Versions/3.13/lib/python3.13/site-packages (2.3.1)
Em seguida, importamos a biblioteca com import numpy as np.
import numpy as np
Agora, vamos criar nossa primeira matriz. Para fazer isso, basta executar np.array([], [], ...) e inserir dentro dos colchetes os valores desejados para cada linha, separados por vírgulas. O parâmetro dtype pode ser adicionado opcionalmente para especificar o tipo de dado inserido.
a = np.array([1,2,3], dtype='int16')
b = np.array([[9.0,8.3,7.2,4.3],[6.0,5.45,4.0,3.0]])
Podemos obter diversas informações sobre as matrizes que acabamos de criar. Abaixo, demonstramos alguns exemplos:
b.ndim # Mostra o número de dimensões da matriz
2
b.shape # Mostra o formato da matriz (linhas, colunas)
(2, 4)
a.dtype # Mostra o tipo de dados da matriz
dtype('int16')
a.itemsize # Mostra o tamanho em bytes de cada elemento da matriz
2
a.nbytes # Mostra o tamanho total em bytes da matriz
6
Extraindo e Modificando Dados
Agora que temos informações sobre a matriz, podemos começar a extrair dados específicos dela e até mesmo modificá-los.
b[0,1] # Seleciona um elemento (1ª linha, 2ª coluna)
np.float64(8.3)
b[1,:] # Seleciona uma linha (2ª linha, todas as colunas)
array([6. , 5.45, 4. , 3. ])
b[:,1] # Seleciona uma coluna (1ª coluna, todas as linhas)
array([8.3 , 5.45])
b[0,1:6:2] # Seleciona usando o formato [começo:fim:passo]
array([8.3, 4.3])
b[1,3] = 20 # Altera um elemento (2ª linha, 4ª coluna)
b[0,:] = 100 # Altera uma linha (1ª linha, todas as colunas)
b[[0,1],1] # Seleciona elementos usando uma lista de índices (1ª, 2ª e 4ª linhas) e coluna 2
array([8.3 , 5.45])
Da mesma forma, podemos também manipular arrays em três dimensões:
b = np.array([[[1,2],[3,4]],[[5,6],[7,8]]]) # Cria array 3D com 2 blocos, 2 linhas e 2 colunas
b[0,1,1] # Seleciona um elemento específico do array 3D (1º bloco, 2ª linha, 2ª coluna)
np.int64(4)
b[:,1,:] # Seleciona a uma linha de cada bloco do array 3D (2ª linha, todas as colunas, todos os blocos)
array([[3, 4],
[7, 8]])
b[:,1,:] = [[9,9],[8,8]] # Altera uma linha de cada bloco do array 3D
b[:,1,:]
array([[9, 9],
[8, 8]])
Inicializando Arrays
Agora, vamos abordar as diferentes formas de inicializar um array NumPy. Como alguns arrays são usados com muita frequência, existem formas de inicializá-los de maneira mais rápida. Abaixo, elencamos algumas delas:
np.zeros((2,3)) # Cria um array 2D de zeros
array([[0., 0., 0.],
[0., 0., 0.]])
np.ones((4,2,2), dtype='int16') # Cria um array de uns
array([[[1, 1],
[1, 1]],
[[1, 1],
[1, 1]],
[[1, 1],
[1, 1]],
[[1, 1],
[1, 1]]], dtype=int16)
np.full((2,2), 99) # Cria um array preenchido com o valor 99
array([[99, 99],
[99, 99]])
b = np.array([[1,2,3],[4,5,6]])
np.full_like(b, 4) # Cria um array com a mesma forma de b, preenchido com o valor 4
array([[4, 4, 4],
[4, 4, 4]])
np.random.rand(4,2) # Cria um array 4x2 com valores aleatórios entre 0 e 1
array([[0.56971655, 0.56121705],
[0.94883996, 0.11001646],
[0.94242777, 0.98836246],
[0.89494765, 0.14380536]])
np.random.randint(-4,8,size=(3,3)) # Cria um array 3x3 com valores inteiros aleatórios entre -4 e 7
array([[ 6, -4, -2],
[ 2, 5, -1],
[ 0, 5, -2]])
np.eye(5) # Cria uma matriz identidade 5x5 (1s na diagonal principal, 0s fora dela)
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.]])
arr = np.array([[1,2,3]])
np.repeat(arr, 3, axis=0) # Repete o array 3 vezes ao longo do eixo 0 (linhas)
array([[1, 2, 3],
[1, 2, 3],
[1, 2, 3]])
Copiando e Reorganizando Arrays
Agora que sabemos criar e inicializar arrays, veremos algumas formas de copiar e reorganizar arrays. Iniciemos vendo como reorganizar arrays já existentes:
before = np.array([[1,2,3,4],[5,6,7,8]])
before.reshape((4,2)) # Altera a forma do array para 4 linhas e 2 colunas (note que o número total de elementos deve permanecer o mesmo)
array([[1, 2],
[3, 4],
[5, 6],
[7, 8]])
v1 = np.array([1,2,3,4])
v2 = np.array([5,6,7,8])
v3 = np.array([9,10,11,12])
np.vstack([v1,v2,v3]) # Empilha os vetores v1, v2 e v3 verticalmente para criar uma matriz 3x4
array([[ 1, 2, 3, 4],
[ 5, 6, 7, 8],
[ 9, 10, 11, 12]])
h1 = np.ones((2,4))
h2 = np.zeros((2,2))
np.hstack((h1,h2)) # Empilha os arrays h1 e h2 horizontalmente para criar uma matriz 2x6
array([[1., 1., 1., 1., 0., 0.],
[1., 1., 1., 1., 0., 0.]])
Vale destacar também a forma correta de realizar cópias de arrays, uma vez que ela pode não ser intuitiva. As variáveis de arrays em NumPy contém referências para a localização desses arrays na memória, e não de fato os seus valores. Logo, ao simplesmente atribuir um array ao outro, não se cria um array novo, mas apenas uma segunda variável para o mesmo array. Com isso em mente, mostramos a seguir uma maneira incorreta de copiar arrays realizada por muitos iniciantes, seguida da forma correta de realizar o procedimento.
# Copiando arrays de forma INCORRETA
a = np.array([1,2,3])
b = a # b aponta para o mesmo array que a
b[0] = 100
a # a também é alterado, pois a e b são o mesmo array
array([100, 2, 3])
# Copiando arrays de forma CORRETA
a = np.array([1,2,3])
b = a.copy() # b é uma cópia independente de a
b[0] = 100
a # a permanece inalterado, pois a e b são arrays diferentes
array([1, 2, 3])
Operações Matemáticas
Outra utilização muito comum do NumPy é para a realização de contas matemáticas. A seguir, demonstramos como realizar algumas operações matemáticas com a biblioteca. Iniciemos com operações aritméticas:
a = np.array([1,2,3,4])
b = np.array([5,6,7,8])
a - 2 # Subtrai 2 de cada elemento de a
array([-1, 0, 1, 2])
a * 2 # Multiplica cada elemento de a por 2
array([2, 4, 6, 8])
a + b # Soma os elementos correspondentes de a e b
array([ 6, 8, 10, 12])
a ** 2 # Eleva cada elemento de a ao quadrado
array([ 1, 4, 9, 16])
Agora, vejamos como utilizar as funções trigonométricas:
np.sin(a) # Aplica a função seno a cada elemento de a
array([ 0.84147098, 0.90929743, 0.14112001, -0.7568025 ])
np.cos(np.pi) # Calcula o cosseno de π (os ângulos são em radianos)
np.float64(-1.0)
A seguir, mostramos alguns exemplos de cálculos de álgebra linear com NumPy:
a = np.ones((2,3))
b = np.full((3,2), 2)
np.matmul(a,b) # Realiza a multiplicação matricial entre a (2x3) e b (3x2), resultando em um array 2x2
array([[6., 6.],
[6., 6.]])
a = np.array([[1,2],[3,4]])
print(np.linalg.det(a)) # Calcula o determinante da matriz a
-2.0000000000000004
Por fim, vejamos como realizar cálculos estatísticos em matrizes NumPy:
stats = np.array([[1,2,3],[4,5,6]])
np.min(stats) # Valor mínimo do array
np.int64(1)
np.max(stats) # Valor máximo do array
np.int64(6)
np.sum(stats) # Soma de todos os elementos do array
np.int64(21)
np.mean(stats) # Média dos valores do array
np.float64(3.5)
np.median(stats) # Mediana dos valores do array
np.float64(3.5)
np.std(stats) # Desvio padrão dos valores do array
np.float64(1.707825127659933)
np.corrcoef(stats) # Matriz de correlação dos valores do array
array([[1., 1.],
[1., 1.]])
Manipulação de Bases de Dados
Para concluir essa aula, vamos mostrar brevemente como o NumPy pode ser usado para manipular bases de dados. Não iremos nos extender muito nessa aplicação, pois veremos na próxima aula que é possível usar bibliotecas como Pandas que facilitam a manipulação dessas bases de dados. Para esse exemplo, usaremos uma database simples, com apenas alguns números inteiros para ilustrar o funcionamento do NumPy.
filedata = np.genfromtxt('data.txt', delimiter=',')
filedata = filedata.astype('int32')
filedata # Mostra os dados lidos do arquivo, convertidos para inteiros
array([[ 1, 13, 21, 11, 196, 75, 4, 3, 34, 6, 7, 8, 0,
1, 2, 3, 4, 5],
[ 3, 42, 12, 33, 766, 75, 4, 55, 6, 4, 3, 4, 5,
6, 7, 0, 11, 12],
[ 1, 22, 33, 11, 999, 11, 2, 1, 78, 0, 1, 2, 9,
8, 7, 1, 76, 88]], dtype=int32)
filedata > 50 # Retorna um array booleano indicando quais elementos de filedata são maiores que 50
array([[False, False, False, False, True, True, False, False, False,
False, False, False, False, False, False, False, False, False],
[False, False, False, False, True, True, False, True, False,
False, False, False, False, False, False, False, False, False],
[False, False, False, False, True, False, False, False, True,
False, False, False, False, False, False, False, True, True]])
np.any(filedata > 50, axis=0) # Verifica se há algum elemento maior que 50 em cada coluna
array([False, False, False, False, True, True, False, True, True,
False, False, False, False, False, False, False, True, True])
np.any((filedata > 50) & (filedata < 100), axis=1) # Verifica se há algum elemento entre 50 e 100 em cada linha
array([ True, True, True])
np.all(filedata > 50, axis=0) # Verifica se todos os elementos são maiores que 50 em cada coluna
array([False, False, False, False, True, False, False, False, False,
False, False, False, False, False, False, False, False, False])
