NumPy: Operações de Shape
Última atualização: 2026-08-26
Operações de Shape
1. O que Você Aprenderá
- ❶ reshape não copia dados — apenas altera metadados
- ❷
-1infere automaticamente o tamanho da dimensão - ❸ flatten vs ravel: cópia vs view
- ❹ transposição transpose / .T
- ❺ newaxis para adicionar dimensões, squeeze para removê-las
2. Uma História Real de um Desenvolvedor
(1) O Problema
Bob redimensiona 12 pontos de dados de 3×4 para 4×3, achando que está "reorganizando a memória" — mas cada reshape estava copiando dados, destruindo sua memória e velocidade.
(2) A Solução
Alice mostra a ele um diagrama Mermaid: "reshape apenas muda metadados — nem um único byte de dados se move. Esse é o segredo da velocidade do NumPy." Desde que uma operação retorne uma view, nenhum dado é copiado.
(3) O Resultado
Uma vez que Bob entendeu "view vs copy", seu código de operações de shape usou uma ordem de magnitude a menos de memória e rodou várias vezes mais rápido. Apenas flatten realmente copia; todo o resto — reshape, ravel, transpose, swapaxes — é uma view.
3. Operações de Shape em Detalhes
(1) Como reshape Funciona
reshape muda o shape do array mas não copia dados. Ele apenas modifica os metadados do array (shape e strides); os dados brutos na memória permanecem no lugar.
import numpy as np
a = np.arange(12)
b = a.reshape(3, 4)
print(a.shape) # (12,)
print(b.shape) # (3, 4)
print(b.base is a) # True — b é uma view de a
> **Saída:** Execute NumPy 2.x no seu ambiente Python local para ver a saída do ndarray. O servidor Piston não tem NumPy pré-instalado — instale localmente (`pip install numpy`) e compare. Os valores reais podem variar conforme a versão do NumPy e a semente aleatória.
# reshape NÃO copia dados
b[0, 0] = 999
print(a[0]) # 999 — modificar b muda a!
> **Saída:** Execute NumPy 2.x no seu ambiente Python local para ver a saída do ndarray. O servidor Piston não tem NumPy pré-instalado — instale localmente (`pip install numpy`) e compare. Os valores reais podem variar conforme a versão do NumPy e a semente aleatória.
Diagrama de Memória do reshape
graph LR
A["Array Original<br/>shape=(12,)"] -->|"reshape(3,4)"| B["View<br/>shape=(3,4)"]
A -->|"reshape(4,3)"| C["View<br/>shape=(4,3)"]
A -->|"reshape(2,6)"| D["View<br/>shape=(2,6)"]
style A fill:#4CAF50,color:#fff
style B fill:#2196F3,color:#fff
style C fill:#FF9800,color:#fff
style D fill:#9C27B0,color:#fff
> **Saída:** Execute NumPy 2.x no seu ambiente Python local para ver a saída do ndarray. O servidor Piston não tem NumPy pré-instalado — instale localmente (`pip install numpy`) e compare. Os valores reais podem variar conforme a versão do NumPy e a semente aleatória.
Ponto-chave: A, B, C e D todos compartilham a mesma memória — eles apenas a "interpretam" de forma diferente.
(2) Auto-Inferência com -1
Use -1 em reshape para deixar o NumPy computar automaticamente o tamanho daquela dimensão.
a = np.arange(12)
# NumPy infere: 12 / 3 = 4
b = a.reshape(3, -1) # shape = (3, 4)
c = a.reshape(2, -1) # shape = (2, 6)
d = a.reshape(-1, 6) # shape = (2, 6)
> **Saída:** Execute NumPy 2.x no seu ambiente Python local para ver a saída do ndarray. O servidor Piston não tem NumPy pré-instalado — instale localmente (`pip install numpy`) e compare. Os valores reais podem variar conforme a versão do NumPy e a semente aleatória.
(3) flatten vs ravel
| Método | Retorna | Copia? | Memória |
|---|---|---|---|
ndarray.flatten() |
Array 1D | Sempre copia | Nova memória |
ndarray.ravel() |
Array 1D | View quando possível | Geralmente compartilhada |
import numpy as np
a = np.arange(12).reshape(3, 4)
f = a.flatten() # sempre uma cópia
r = a.ravel() # geralmente uma view
f[0] = 999
print(a[0, 0]) # 0 — f é uma cópia, a inalterado
r[0] = 999
print(a[0, 0]) # 999 — r é uma view, a alterado
> **Saída:** Execute NumPy 2.x no seu ambiente Python local para ver a saída do ndarray. O servidor Piston não tem NumPy pré-instalado — instale localmente (`pip install numpy`) e compare. Os valores reais podem variar conforme a versão do NumPy e a semente aleatória.
(4) transpose e .T
import numpy as np
a = np.arange(12).reshape(3, 4)
print(a.shape) # (3, 4)
b = a.T # transposição — view, sem cópia
print(b.shape) # (4, 3)
# Para arrays multidimensionais, transpose aceita uma ordem de eixos
c = a.transpose(1, 0)
print(c.shape) # (4, 3)
> **Saída:** Execute NumPy 2.x no seu ambiente Python local para ver a saída do ndarray. O servidor Piston não tem NumPy pré-instalado — instale localmente (`pip install numpy`) e compare. Os valores reais podem variar conforme a versão do NumPy e a semente aleatória.
(5) newaxis e squeeze
import numpy as np
a = np.array([1, 2, 3]) # shape (3,)
# newaxis adiciona uma dimensão
b = a[np.newaxis, :] # shape (1, 3)
c = a[:, np.newaxis] # shape (3, 1)
d = a[np.newaxis, :, np.newaxis] # shape (1, 3, 1)
# squeeze remove dimensões de tamanho 1
e = np.squeeze(d) # shape (3,) — de volta ao original
> **Saída:** Execute NumPy 2.x no seu ambiente Python local para ver a saída do ndarray. O servidor Piston não tem NumPy pré-instalado — instale localmente (`pip install numpy`) e compare. Os valores reais podem variar conforme a versão do NumPy e a semente aleatória.
▶ Exemplo
> **Saída:** Execute NumPy 2.x no seu ambiente Python local para ver a saída do ndarray. O servidor Piston não tem NumPy pré-instalado — instale localmente (`pip install numpy`) e compare. Os valores reais podem variar conforme a versão do NumPy e a semente aleatória.
: reshape com auto-inferência -1 (Dificuldade ⭐)
import numpy as np
a = np.arange(24)
# Usar -1 para auto-inferência
b = a.reshape(2, -1) # 2 x 12
c = a.reshape(3, -1) # 3 x 8
d = a.reshape(4, -1) # 4 x 6
e = a.reshape(6, -1) # 6 x 4
print(f"a.shape={a.shape}")
print(f"b.shape={b.shape}") # (2, 12)
print(f"c.shape={c.shape}") # (3, 8)
print(f"d.shape={d.shape}") # (4, 6)
print(f"e.shape={e.shape}") # (6, 4)
> **Saída:** Execute NumPy 2.x no seu ambiente Python local para ver a saída do ndarray. O servidor Piston não tem NumPy pré-instalado — instale localmente (`pip install numpy`) e compare. Os valores reais podem variar conforme a versão do NumPy e a semente aleatória.
▶ Exemplo
> **Saída:** Execute NumPy 2.x no seu ambiente Python local para ver a saída do ndarray. O servidor Piston não tem NumPy pré-instalado — instale localmente (`pip install numpy`) e compare. Os valores reais podem variar conforme a versão do NumPy e a semente aleatória.
: flatten vs ravel — cópia vs view (Dificuldade ⭐⭐)
import numpy as np
a = np.arange(12).reshape(3, 4)
# flatten sempre copia
flat = a.flatten()
flat[0] = 999
print("After flat[0]=999, a[0,0]=", a[0,0]) # 0 (inalterado)
# ravel geralmente retorna uma view
rav = a.ravel()
rav[0] = 999
print("After rav[0]=999, a[0,0]=", a[0,0]) # 999 (alterado!)
> **Saída:** Execute NumPy 2.x no seu ambiente Python local para ver a saída do ndarray. O servidor Piston não tem NumPy pré-instalado — instale localmente (`pip install numpy`) e compare. Os valores reais podem variar conforme a versão do NumPy e a semente aleatória.
▶ Exemplo
> **Saída:** Execute NumPy 2.x no seu ambiente Python local para ver a saída do ndarray. O servidor Piston não tem NumPy pré-instalado — instale localmente (`pip install numpy`) e compare. Os valores reais podem variar conforme a versão do NumPy e a semente aleatória.
: transpose e newaxis (Dificuldade ⭐⭐)
import numpy as np
a = np.arange(12).reshape(3, 4)
# Transposição
print("Original shape:", a.shape) # (3, 4)
print("Transposed shape:", a.T.shape) # (4, 3)
# newaxis: adicionar dimensões
row = np.array([1, 2, 3])
print("row shape:", row.shape) # (3,)
print("row[np.newaxis,:] shape:", row[np.newaxis, :].shape) # (1, 3)
print("row[:,np.newaxis] shape:", row[:, np.newaxis].shape) # (3, 1)
> **Saída:** Execute NumPy 2.x no seu ambiente Python local para ver a saída do ndarray. O servidor Piston não tem NumPy pré-instalado — instale localmente (`pip install numpy`) e compare. Os valores reais podem variar conforme a versão do NumPy e a semente aleatória.
4. Tabelas Comparativas
(1) Resumo de Operações de Shape
| Operação | Retorna | Copia Dados? | Caso de Uso |
|---|---|---|---|
reshape |
View | Não | Mudar shape |
flatten |
Cópia | Sim | Conversão 1D segura |
ravel |
View (geralmente) | Raramente | 1D rápida |
T / transpose |
View | Não | Reordenar eixos |
newaxis |
View | Não | Adicionar dimensão |
squeeze |
View | Não | Remover dims de tamanho 1 |
swapaxes |
View | Não | Trocar dois eixos |
(2) View vs Cópia
| Característica | View | Cópia |
|---|---|---|
| Memória | Compartilhada | Nova alocação |
| Modificação | Afeta o original | Independente |
| Velocidade | O(1) | O(n) |
Atributo base |
Aponta para o original | None |
| Quando usar | Somente leitura ou compartilhamento intencional | Modificação segura |
5. Diagrama de Princípios
graph TB
A["Original (12,)"] -->|reshape/flatten/ravel| B["Novo shape"]
A --> C["buffer de dados: [0 1 2 ... 11]"]
B --> C
B -->|flatten| D["cópia do buffer de dados"]
B -->|ravel| C
B -->|transpose| C
B -->|newaxis| C
style A fill:#4CAF50,color:#fff
style C fill:#FF9800,color:#fff
style D fill:#E91E63,color:#fff
❓ Perguntas Frequentes
P: reshape sempre retorna uma view? R: Quase sempre — desde que o array seja contíguo na memória. Se o array não for contíguo (ex.: após uma transposição), reshape pode precisar copiar. Use
np.ascontiguousarray()antes se necessário.
P: Qual a diferença entre .T e .transpose()? R:
.Té um atalho para reverter todos os eixos (equivalente a.transpose()com ordem reversa). Para arrays 2D são idênticos. Para 3D+,.Treverte todos os eixos, enquanto.transpose(1,0,2)permite especificar a ordem.
P: Quando devo usar flatten vs ravel? R: Se vai modificar o resultado 1D e não quer afetar o original, use flatten (cópia segura). Se está apenas lendo ou quer que as mudanças se propaguem, use ravel (mais rápido, geralmente uma view).
P: O que significa -1 em reshape? R: Diz ao NumPy para "descobrir esta dimensão automaticamente". Apenas um -1 é permitido. NumPy calcula como
total_size / produto_das_outras_dims.
📖 Resumo
- reshape apenas muda metadados de shape/strides — sem cópia de dados, operação O(1)
-1infere automaticamente o tamanho da dimensão a partir da contagem total de elementos- flatten sempre copia; ravel geralmente retorna uma view (verifique
.base) - transpose/T/swapaxes retornam views com strides modificados, sem movimento de dados
- newaxis adiciona uma dimensão de tamanho 1; squeeze remove dimensões de tamanho 1
- Entender view vs copy é chave para escrever código NumPy eficiente em memória
📝 Exercícios
-
Básico (Dificuldade ⭐): Crie um array de 20 elementos, redimensione para (4,5), (5,4), (2,10) e (10,2) usando
-1. Verifique se todos os shapes estão corretos. -
Intermediário (Dificuldade ⭐⭐): Crie um array 3x4, transponha-o, depois tente fazer reshape do resultado transposto. O reshape ainda evita copiar? Verifique com
.base. -
Desafio (Dificuldade ⭐⭐⭐): Crie um array 3D com shape (2,3,4). Use
transpose(2,0,1)para reordenar os eixos. Explique o que cada dimensão representa no resultado. Depois useswapaxespara obter o mesmo resultado.