NumPy: Broadcasting
Última atualização: 2026-08-26
Broadcasting
1. O que Você Aprenderá
- ❶ As 3 regras de broadcasting
- ❷ Broadcasting Escalar → 1D → 2D
- ❸ Verificações de compatibilidade
- ❹ Armadilhas comuns
- ❺ Broadcasting vs desempenho de loop
2. Uma História Real de um Desenvolvedor
(1) O Problema
Bob quer adicionar um vetor linha 1×3 a cada linha de uma matriz 4×3. Ele escreve um loop for de 4 linhas — código feio, lento e fácil de errar os índices.
(2) A Solução
Alice o esclarece: "Sem loop — o NumPy faz broadcast automaticamente. O vetor linha é 'transmitido' para 4×3 antes de adicionar." Bob assiste ao diagrama Mermaid e entende instantaneamente como as dimensões são "virtualmente expandidas."
(3) O Resultado
Após remover o loop, o código encolhe de 6 linhas para 1, rodando mais de 50x mais rápido — broadcasting é a base das operações vetorizadas do NumPy.
3. Regras de Broadcasting em Detalhes
(1) As 3 Regras
Broadcasting permite que arrays de formas diferentes trabalhem juntos em operações aritméticas alinhando automaticamente as dimensões — sem cópia manual de dados.
| Regra | Descrição | Exemplo |
|---|---|---|
| Regra 1: Alinhar | Comece da dimensão mais à direita, alinhe à esquerda, preencha dimensões ausentes à esquerda com 1 | (3,) + (2,3) → preencher para (1,3) + (2,3) |
| Regra 2: Tamanho-1 expande | Se uma dimensão tem tamanho 1, copie ao longo dessa dimensão para corresponder ao outro array | (1,3) + (2,3) → (2,3) + (2,3) |
| Regra 3: Outros devem corresponder | Dimensões que não são tamanho-1 devem corresponder exatamente, ou gera erro | (2,3) + (4,3) → ❌ 2≠4 |
Referência Rápida
| Cenário | Shape A | Shape B | Shape Resultado | Compatível? |
|---|---|---|---|---|
| Escalar + array | () |
(3,4) |
(3,4) |
✅ |
| 1D + 2D | (3,) |
(4,3) |
(4,3) |
✅ |
| Coluna + linha | (4,1) |
(1,3) |
(4,3) |
✅ |
| Dois 2D | (3,1) |
(1,5) |
(3,5) |
✅ |
| Incompatível | (2,3) |
(4,3) |
— | ❌ |
| Sem tamanho-1 para expandir | (3,) |
(4,) |
— | ❌ |
(2) Passos do Broadcasting Visualizados
Adicionando uma matriz (4,3) + vetor linha (3,):
graph TB
A["Matriz A<br/>shape=(4,3)"] --> D{"Regra 1:<br/>Alinhar dimensões"}
B["Vetor B<br/>shape=(3,)"] --> D
D --> E["Preencher dim esquerda<br/>B: (3,) → (1,3)"]
E --> F{"Regra 2:<br/>Expandir dim=1"}
F --> G["Expandir B ao longo do eixo 0<br/>(1,3) → (4,3)"]
G --> H["A + B_expandido<br/>shape=(4,3)"]
style A fill:#4CAF50,color:#fff
style B fill:#2196F3,color:#fff
style D fill:#FF9800,color:#fff
style F fill:#FF9800,color:#fff
style G fill:#9C27B0,color:#fff
style H fill:#E91E63,color:#fff
(3) Broadcasting em Ação
import numpy as np
# Escalar + array
a = np.array([1, 2, 3])
print(a + 10) # [11 12 13]
# 1D + 2D
matrix = np.arange(12).reshape(4, 3)
row = np.array([10, 20, 30])
print(matrix + row)
# [[10 22 34]
# [13 25 37]
# [16 28 40]
# [19 31 43]]
# Coluna + linha (operação externa)
col = np.array([[1], [2], [3], [4]]) # shape (4, 1)
print(col + row)
# [[11 21 31]
# [12 22 32]
# [13 23 33]
# [14 24 34]]
> **Output:** Execute o NumPy 2.x em seu ambiente Python local para ver a saída do ndarray. O servidor Piston não tem o NumPy pré-instalado — instale-o localmente (`pip install numpy`) e compare. Os valores reais podem variar conforme a versão do NumPy e a semente aleatória.
4. Armadilhas Comuns
(1) Incompatibilidade de Shape
a = np.ones((3, 2))
b = np.ones((2, 3))
# a + b # ValueError: shapes (3,2) and (2,3) not aligned
(2) Broadcasting Inesperado
a = np.ones((3, 1))
b = np.ones((3,))
# a + b faz broadcast para (3, 3) — pode não ser o que você espera!
(3) Resultado Pretendido
# Para evitar broadcasting, use shapes explícitos
a = np.ones((3, 1))
b = np.ones((3, 1)) # ou b[:, np.newaxis]
print((a + b).shape) # (3, 1) — sem broadcasting
> **Output:** Execute o NumPy 2.x em seu ambiente Python local para ver a saída do ndarray. O servidor Piston não tem o NumPy pré-instalado — instale-o localmente (`pip install numpy`) e compare. Os valores reais podem variar conforme a versão do NumPy e a semente aleatória.
▶ Exemplo
> **Output:** Execute o NumPy 2.x em seu ambiente Python local para ver a saída do ndarray. O servidor Piston não tem o NumPy pré-instalado — instale-o localmente (`pip install numpy`) e compare. Os valores reais podem variar conforme a versão do NumPy e a semente aleatória.
: Broadcasting de escalar para 2D (Dificuldade ⭐)
import numpy as np
# Broadcasting escalar
arr = np.array([[1, 2, 3],
[4, 5, 6]])
print("arr + 10:\n", arr + 10)
print("arr * 2:\n", arr * 2)
print("arr ** 2:\n", arr ** 2)
> **Output:** Execute o NumPy 2.x em seu ambiente Python local para ver a saída do ndarray. O servidor Piston não tem o NumPy pré-instalado — instale-o localmente (`pip install numpy`) e compare. Os valores reais podem variar conforme a versão do NumPy e a semente aleatória.
▶ Exemplo
> **Output:** Execute o NumPy 2.x em seu ambiente Python local para ver a saída do ndarray. O servidor Piston não tem o NumPy pré-instalado — instale-o localmente (`pip install numpy`) e compare. Os valores reais podem variar conforme a versão do NumPy e a semente aleatória.
: Coluna + linha = operação externa (Dificuldade ⭐⭐)
import numpy as np
# Padronizar dados: subtrair média, dividir pelo desvio padrão
data = np.random.randn(5, 3) # 5 amostras, 3 características
mean = data.mean(axis=0) # shape (3,)
std = data.std(axis=0) # shape (3,)
standardized = (data - mean) / std # broadcasting!
print("Standardized shape:", standardized.shape) # (5, 3)
print("Mean of standardized:", standardized.mean(axis=0).round(6))
# [ 0. 0. 0.] (dentro do ponto flutuante)
> **Output:** Execute o NumPy 2.x em seu ambiente Python local para ver a saída do ndarray. O servidor Piston não tem o NumPy pré-instalado — instale-o localmente (`pip install numpy`) e compare. Os valores reais podem variar conforme a versão do NumPy e a semente aleatória.
5. Tabelas Comparativas
(1) Broadcasting vs Loop
| Dimensão | Loop for Python | Broadcasting NumPy |
|---|---|---|
| Camada de execução | Interpretador Python | ufunc em nível C |
| Velocidade | Lento (10-100x) | Rápido |
| Código | for i in range(n): ... |
a + b |
| Memória | Sem alocação extra | Virtual (sem dados copiados) |
| Legibilidade | Baixa | Alta |
(2) Compatibilidade de Broadcasting
| Shape A | Shape B | Compatível? | Resultado |
|---|---|---|---|
| (3,) | (3,) | ✅ | (3,) |
| (3,) | (1,) | ✅ | (3,) |
| (4,3) | (3,) | ✅ | (4,3) |
| (4,3) | (4,1) | ✅ | (4,3) |
| (4,1) | (1,3) | ✅ | (4,3) |
| (2,3) | (4,3) | ❌ | Erro |
| (3,) | (4,) | ❌ | Erro |
6. Diagrama de Princípios
graph TB
A[Arrays de entrada] --> B[Alinhar dimensões da direita]
B --> C{Tamanhos correspondem?}
C -->|Sim| D[Operação direta]
C -->|Um é 1| E[Expandir dimensão tamanho-1]
E --> D
C -->|Nenhum é 1| F[ValueError: incompatível]
D --> G[Array resultado]
style A fill:#e1f5fe
style C fill:#fff9c4
style D fill:#c8e6c9
style F fill:#ffccbc
style G fill:#c8e6c9
▶ Exemplo: Broadcasting 3D com newaxis (Dificuldade ⭐⭐)
import numpy as np
# Array 3D + vetor 1D
arr_3d = np.arange(24).reshape(2, 3, 4)
vec = np.array([10, 20, 30, 40])
result = arr_3d + vec
print("Shape:", result.shape)
print("First layer:\n", result[0])
# Broadcasting com newaxis
col = np.array([0, 10, 20])[:, np.newaxis]
row = np.array([1, 2, 3, 4])
print("col + row:\n", col + row)
Output:
TEXT 📖 Somente leituraShape: (2, 3, 4) First layer: [[10 21 32 43] [14 25 36 47] [18 29 40 51]] col + row: [[ 1 2 3 4] [11 12 13 14] [21 22 23 24]]
❓ Perguntas Frequentes
P: O broadcasting realmente copia dados? R: Não — broadcasting é uma operação "virtual." O NumPy usa truques de stride para apresentar os dados como se estivessem expandidos, sem alocar nova memória. A expansão acontece em nível C durante a computação.
P: Como verificar se dois shapes são compatíveis para broadcast? R: Alinhe da direita. Para cada par de dimensões, são compatíveis se são iguais ou se um deles é 1. Se algum par falha e nenhum é 1, são incompatíveis.
P: O broadcasting pode causar problemas de desempenho? R: Não — é sempre mais rápido que um loop Python. Mas se você está fazendo broadcast de um array muito grande para preencher um temporário enorme, pode usar mais memória. Use
np.einsumounp.matmulpara controle explícito.
P: Qual é a diferença entre broadcasting e tile/repeat? R:
np.tileenp.repeatexpandem fisicamente os dados na memória. Broadcasting faz isso virtualmente. Broadcasting é mais rápido e usa menos memória. Use tile/repeat apenas quando precisa do array expandido para outras operações.
📖 Resumo
- Broadcasting alinha dimensões da direita, preenche as ausentes com 1, expande dimensões tamanho-1
- Operações escalares, operações com vetores linha/coluna e padronização de dados usam broadcasting
- Broadcasting é virtual — nenhum dado é realmente copiado, apenas os metadados de stride mudam
- Armadilhas comuns: broadcasting não intencional com shapes incompatíveis, esquecer de usar
[:, np.newaxis] - Broadcasting é sempre mais rápido que loops Python e usa menos memória que expansão explícita
📝 Exercícios
-
Básico (Dificuldade ⭐): Crie uma matriz 4x3 e um vetor linha 1x3. Some-os. Depois crie um vetor coluna 4x1 e some-o à matriz. Observe os shapes.
-
Intermediário (Dificuldade ⭐⭐): Crie um array 3D com shape (5, 4, 3) e um array 1D com shape (3,). Some-os. Explique quais dimensões são transmitidas (broadcast). Depois tente adicionar um array (4, 3) ao array 3D — funciona?
-
Desafio (Dificuldade ⭐⭐⭐): Gere 1000 pontos de dados com 5 características cada. Padronize os dados (subtraia a média, divida pelo desvio padrão) usando broadcasting. Depois implemente a mesma operação com um loop for Python. Compare o tempo de execução.