O NumPy (Numerical Python) é a biblioteca fundamental para computação científica em Python. Desenvolvida originalmente por Travis Oliphant em 2005, tornou-se a espinha dorsal de praticamente todo o ecossistema de ciência de dados do Python moderno.

Se você trabalha com análise de dados, machine learning, engenharia ou qualquer área que exija cálculos numéricos eficientes, o NumPy é indispensável. Nesta guia completo, você vai dominar desde os conceitos básicos até técnicas avançadas de manipulação de arrays.

📦 O que é NumPy e Por Que Usá-lo?

O NumPy é uma biblioteca que fornece suporte para arrays multidimensionais de alto desempenho, além de funções matemáticas de alto nível para trabalhar com esses arrays. A principal vantagem do NumPy sobre listas Python tradicionais é a velocidade: operações com arrays NumPy são dezenas a centenas de vezes mais rápidas que equivalentes com listas nativas.

Essa eficiência ocorre porque o NumPy utiliza memória contígua e implementa operações vetorizadas que aproveitam a estrutura de dados para realizar cálculos em paralelo. Além disso, o NumPy é a base para outras bibliotecas essenciais como Pandas, Matplotlib, Scikit-learn e TensorFlow.

🚀 Instalação e Configuração

Instalação via pip

# Instalação padrão
pip install numpy

# Verificar versão
import numpy as np
print(np.__version__)

Instalação via conda

# Para usuários Anaconda/Miniconda
conda install numpy

🔧 Arrays NumPy: O Coração da Biblioteca

Criando Arrays Básicos

import numpy as np

# Array a partir de uma lista
arr1 = np.array([1, 2, 3, 4, 5])
print(arr1)

# Array de zeros
zeros = np.zeros(5)
print(zeros)

# Array de uns
uns = np.ones((3, 3))  # matriz 3x3
print(uns)

# Array com valores aleatórios
aleatorios = np.random.rand(5)
print(aleatorios)

# Array com sequência
sequencia = np.arange(0, 10, 2)  # de 0 a 10, passo 2
print(sequencia)

# Array com espaço linear
espacado = np.linspace(0, 1, 5)  # 5 valores entre 0 e 1
print(espacado)

Propriedades dos Arrays

import numpy as np

arr = np.array([[1, 2, 3], [4, 5, 6]])

print(f"Dimensions: {arr.ndim}")       # 2
print(f"Shape: {arr.shape}")           # (2, 3)
print(f"Total elements: {arr.size}")   # 6
print(f"Data type: {arr.dtype}")       # int64
print(f"Memory (bytes): {arr.itemsize * arr.size}")

📊 Operações Matemáticas com NumPy

Operações Aritméticas

import numpy as np

arr = np.array([1, 2, 3, 4, 5])

# Operações básicas - aplicadas elemento a elemento
print(arr + 10)    # [11, 12, 13, 14, 15]
print(arr - 5)     # [-4, -3, -2, -1, 0]
print(arr * 2)     # [2, 4, 6, 8, 10]
print(arr / 2)     # [0.5, 1.0, 1.5, 2.0, 2.5]
print(arr ** 2)     # [1, 4, 9, 16, 25]

# Operações entre arrays
a = np.array([1, 2, 3])
b = np.array([4, 5, 6])
print(a + b)       # [5, 7, 9]
print(a * b)       # [4, 10, 18]

Funções Matemáticas

import numpy as np

arr = np.array([0, np.pi/2, np.pi, 3*np.pi/2])

# Funções trigonométricas
print(np.sin(arr))   # [0. 1. 0. -1.]
print(np.cos(arr))   # [1. 0. -1. 0.]
print(np.tan(arr))   # [0. inf 0. inf]

# Outras funções importantes
arr2 = np.array([1, 4, 9, 16])
print(np.sqrt(arr2))   # [1. 2. 3. 4.]
print(np.log(arr2))    # [0. 1. 2. 2.77...]
print(np.abs([-1, -2, 3]))  # [1, 2, 3]

# Estatísticas
notas = np.array([7.5, 8.0, 6.5, 9.0, 7.0])
print(f"Média: {np.mean(notas):.2f}")      # 7.6
print(f"Mediana: {np.median(notas):.2f}")  # 7.5
print(f"Desvio padrão: {np.std(notas):.2f}")  # 0.98
print(f"Variância: {np.var(notas):.2f}")   # 0.96
print(f"Máximo: {np.max(notas)}")         # 9.0
print(f"Mínimo: {np.min(notas)}")          # 6.5

🎯 Indexing e Slicing

Acesso a Elementos

import numpy as np

arr = np.array([[1, 2, 3, 4],
                [5, 6, 7, 8],
                [9, 10, 11, 12]])

# Acesso por índice
print(arr[0, 0])      # 1
print(arr[1, 2])      # 7
print(arr[-1, -1])    # 12

# Indexação negativa
print(arr[-1])        # [9, 10, 11, 12]
print(arr[-1, -2])   # 11

Slicing (Fatiamento)

import numpy as np

arr = np.arange(1, 21).reshape(4, 5)

# Linhas e colunas específicas
print(arr[0, :])      # primeira linha
print(arr[:, 2])      # terceira coluna

# Intervalos
print(arr[1:3, 1:4])  # linhas 1-2, colunas 1-3

# Com passo
print(arr[::2])       # todas as linhas, passo 2
print(arr[::2, ::2])  # linhas e colunas com passo 2

# Máscara booleana
arr2 = np.array([10, 20, 30, 40, 50])
mascara = arr2 > 25
print(arr2[mascara])  # [30, 40, 50]

# Indexação fancy
indices = [0, 2, 4]
print(arr2[indices])  # [10, 30, 50]

🔄 Manipulação de Arrays

reshape() e flatten()

import numpy as np

arr = np.arange(1, 13)
print(arr.shape)  # (12,)

# Redimensionar para matriz 3x4
matriz = arr.reshape(3, 4)
print(matriz)
# [[1  2  3  4]
#  [5  6  7  8]
#  [9 10 11 12]]

# flatten() - achatar para 1D
print(matriz.flatten())

# ravel() - similar ao flatten mas retorna vista
print(matriz.ravel())

transpose() e swapaxes()

import numpy as np

matriz = np.array([[1, 2, 3],
                   [4, 5, 6]])

print(matriz.T)
# [[1 4]
#  [2 5]
#  [3 6]]

# swapaxes() - trocar eixos
arr3d = np.arange(1, 13).reshape(2, 3, 2)
print(arr3d.swapaxes(1, 2).shape)  # (2, 2, 3)

Concatenação e Split

import numpy as np

a = np.array([1, 2, 3])
b = np.array([4, 5, 6])

# Concatenar
print(np.concatenate([a, b]))        # [1 2 3 4 5 6]
print(np.hstack([a, b]))             # horizontal stack
print(np.vstack([a, b]))             # vertical stack

# Split
arr = np.array([1, 2, 3, 4, 5, 6])
print(np.split(arr, 3))  # [array([1,2]), array([3,4]), array([5,6])]

💡 Broadcasting

O broadcasting é uma técnica poderosa do NumPy que permite realizar operações entre arrays de diferentes formatos. O NumPy automaticamente expande o array menor para compatibilidade.

import numpy as np

# Exemplo 1: arrays de diferentes formas
a = np.array([[1, 2, 3],
              [4, 5, 6]])
b = np.array([10, 20, 30])

# b é "broadcast" para ter a mesma forma de a
print(a + b)
# [[11 22 33]
#  [14 25 36]]

# Exemplo 2: escalar com array
arr = np.array([1, 2, 3, 4, 5])
print(arr * 10)  # [10 20 30 40 50]

# Exemplo 3: matriz 2D com vetor
matriz = np.ones((3, 3))
vetor = np.array([1, 2, 3)
print(matriz + vetor)
# [[2 3 4]
#  [2 3 4]
#  [2 3 4]]

🧮 Álgebra Linear com NumPy

import numpy as np

# Produto escalar
a = np.array([1, 2, 3])
b = np.array([4, 5, 6])
print(np.dot(a, b))      # 32

# Multiplicação de matrizes
A = np.array([[1, 2], [3, 4]])
B = np.array([[5, 6], [7, 8]])
print(np.matmul(A, B))
# [[19 22]
#  [43 50]]

# Determinante
print(np.linalg.det(A))  # -2.0

# Inversa
print(np.linalg.inv(A))
# [[-2.   1. ]
#  [ 1.5 -0.5]]

# Autovalores
w, v = np.linalg.eig(A)
print(f"Autovalores: {w}")
print(f"Autovetores: {v}")

🎓 Projeto Prático: Análise de Vendas

import numpy as np

# Simular dados de vendas de uma loja
np.random.seed(42)

dias = 30
produtos = ["Eletrônicos", "Roupas", "Alimentos", "Casa"]

# Gerar vendas aleatórias para cada produto
vendas = np.random.randint(1000, 5000, size=(dias, len(produtos)))
vendas = vendas.astype(float)

# Adicionar variação de preço por produto
precos = np.array([500.00, 80.00, 25.00, 150.00])

# Calcular receita diária
receita_diaria = vendas * precos

print("=" * 50)
print("📊 RELATÓRIO DE VENDAS - LOJA MIX")
print("=" * 50)

# Receita total por produto
receita_por_produto = receita_diaria.sum(axis=0)
print("\n💰 Receita por Produto:")
for i, prod in enumerate(produtos):
    print(f"  {prod}: R$ {receita_por_produto[i]:,.2f}")

# Produto mais vendido
produto_mais_vendido = produtos[np.argmax(receita_por_produto)]
print(f"\n🏆 Produto mais vendido: {produto_mais_vendido}")

# Média diária de vendas
vendas_media_dia = vendas.mean(axis=1)
print(f"\n📈 Média de vendas por dia: {vendas_media_dia.mean():,.0f}")

# Dia com maior receita
dia_maior_receita = np.argmax(receita_diaria.sum(axis=1)) + 1
receita_dia_max = receita_diaria.sum(axis=1).max()
print(f"\n📅 Melhor dia: Dia {dia_maior_receita} (R$ {receita_dia_max:,.2f})")

# Desvio padrão das vendas (volatilidade)
volatilidade = vendas.std(axis=0)
print(f"\n📉 Volatilidade por produto:")
for i, prod in enumerate(produtos):
    print(f"  {prod}: {volatilidade[i]:,.0f}")

🔗 Integração com Outras Bibliotecas

O NumPy é a base do ecossistema de ciência de dados Python. Veja como ele integra com as principais bibliotecas:

NumPy + Pandas

import numpy as np
import pandas as pd

# Criar DataFrame a partir de arrays NumPy
dados = np.random.randn(100, 3)
df = pd.DataFrame(dados, columns=['A', 'B', 'C'])
print(df.describe())

NumPy + Matplotlib

import numpy as np
import matplotlib.pyplot as plt

x = np.linspace(0, 2 * np.pi, 100)
y = np.sin(x)

plt.plot(x, y)
plt.title('Seno com NumPy')
plt.show()

NumPy + SciPy

from scipy import stats
import numpy as np

dados = np.array([23, 25, 28, 30, 32, 35, 38, 40])
media = np.mean(dados)
desvio = np.std(dados)
resultado = stats.normaltest(dados)
print(f"Média: {media:.2f}")
print(f"Teste normalidade: {resultado}")

⚡ Dicas de Performance

  • ✅ Use arrays NumPy ao invés de listas Python para operações numéricas
  • ✅ Prefira operações vetorizadas em vez de loops for
  • ✅ Utilize np.where() para condicionais em arrays
  • ✅ Use @njit (Numba) para funções que não podem ser vetorizadas
  • ✅ Evite usar append() em loops - pré-aloque a memória
  • ✅ Use view ao invés de copy quando possível
  • ✅ Configure o dtype correto para economizar memória
  • ❌ Evite converter arrays NumPy para listas Python

🚀 Próximos Passos

Agora que você dominou o NumPy, o próximo passo é explorar bibliotecas que o utilizam como base:

O NumPy é apenas o começo da sua jornada em ciência de dados com Python. Continue praticando e explorando as infinitas possibilidades que essa poderosa biblioteca oferece!