NumPy Reshape: Como alterar a forma de arrays em Python
Updated on
Você tem uma lista plana de 10.000 valores de pixels e uma rede neural que espera uma matriz de imagem 100x100. Ou talvez o scikit-learn esteja lançando um erro porque seu array de features é unidimensional quando precisa ser um vetor coluna. Esses não são casos extremos -- são obstáculos diários para qualquer pessoa que trabalha com dados numéricos em Python. A função que os resolve é numpy.reshape(), e entendê-la corretamente economiza horas de depuração.
O que o numpy reshape faz?
numpy.reshape() altera a forma de um array sem alterar seus dados. Ele pega os mesmos elementos e os reorganiza em um novo conjunto de dimensões. Um array 1D com 12 elementos pode se tornar uma matriz 3x4, uma matriz 2x6, uma matriz 4x3, ou até mesmo um array tridimensional 2x2x3. A única regra é que o número total de elementos deve permanecer o mesmo.
import numpy as np
a = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12])
print(a.shape)
# (12,)
b = a.reshape(3, 4)
print(b)
# [[ 1 2 3 4]
# [ 5 6 7 8]
# [ 9 10 11 12]]
print(b.shape)
# (3, 4)O array original a continua existindo com sua forma original. O array reformatado b é uma nova visualização dos mesmos dados (mais sobre visualizações vs cópias adiante).
Sintaxe básica e parâmetros
Existem duas maneiras de reformatar um array no NumPy:
# Método 1: Como função
np.reshape(array, newshape, order='C')
# Método 2: Como método do array
array.reshape(newshape, order='C')| Parâmetro | Tipo | Descrição |
|---|---|---|
array | ndarray | O array a reformatar (apenas para a forma de função np.reshape()) |
newshape | int ou tupla de ints | A forma alvo. Uma dimensão pode ser -1, que é calculada automaticamente. |
order | 'C', 'F' ou 'A' | Ordem de leitura/escrita dos elementos. 'C' = por linhas (padrão), 'F' = por colunas, 'A' = ordem Fortran se o array for contíguo em Fortran, ordem C caso contrário. |
Ambas as formas produzem resultados idênticos. A forma de método (array.reshape()) é mais comum porque se lê mais naturalmente no código.
Reformatando arrays de 1D para 2D
Esta é a operação de reshape mais frequente. Você começa com um array plano e precisa de uma matriz.
import numpy as np
# Array 1D com 8 elementos
data = np.array([10, 20, 30, 40, 50, 60, 70, 80])
# Reformatar para 2 linhas, 4 colunas
matrix_2x4 = data.reshape(2, 4)
print(matrix_2x4)
# [[10 20 30 40]
# [50 60 70 80]]
# Reformatar para 4 linhas, 2 colunas
matrix_4x2 = data.reshape(4, 2)
print(matrix_4x2)
# [[10 20]
# [30 40]
# [50 60]
# [70 80]]
# Reformatar para um vetor coluna (8 linhas, 1 coluna)
column_vector = data.reshape(8, 1)
print(column_vector)
# [[10]
# [20]
# [30]
# [40]
# [50]
# [60]
# [70]
# [80]]
print(column_vector.shape)
# (8, 1)A reformatação para vetor coluna (n, 1) é particularmente importante. Muitas funções do scikit-learn exigem entrada 2D mesmo para uma única feature. Se você passar um array 1D, obtém o erro Expected 2D array, got 1D array instead. A solução é .reshape(-1, 1).
Reformatando de 2D para 3D (Para Machine Learning e Deep Learning)
Frameworks de deep learning como TensorFlow e PyTorch frequentemente exigem tensores de entrada 3D ou 4D. Por exemplo, um lote de imagens em escala de cinza precisa da forma (batch_size, height, width), e um lote de imagens coloridas precisa de (batch_size, height, width, channels).
import numpy as np
# Simular 4 imagens em escala de cinza 3x3 armazenadas como linhas em um array 2D
images_2d = np.arange(36).reshape(4, 9)
print(images_2d.shape)
# (4, 9)
# Reformatar para (lote, altura, largura)
images_3d = images_2d.reshape(4, 3, 3)
print(images_3d.shape)
# (4, 3, 3)
print(images_3d[0])
# [[0 1 2]
# [3 4 5]
# [6 7 8]]Para imagens coloridas com 3 canais (RGB):
import numpy as np
# 2 imagens coloridas, cada uma 4x4 com 3 canais, armazenadas de forma plana
flat_data = np.arange(96) # 2 * 4 * 4 * 3 = 96
images = flat_data.reshape(2, 4, 4, 3)
print(images.shape)
# (2, 4, 4, 3)O truque do -1: Calculando uma dimensão automaticamente
Quando você define uma dimensão como -1, o NumPy a calcula automaticamente com base no número total de elementos e nas outras dimensões que você especificou. Esta é uma das funcionalidades mais úteis do reshape.
import numpy as np
arr = np.arange(12)
# "Me dê 3 linhas, calcule as colunas"
print(arr.reshape(3, -1))
# [[ 0 1 2 3]
# [ 4 5 6 7]
# [ 8 9 10 11]]
# Forma: (3, 4) -- NumPy calculou 4 colunas
# "Me dê 2 colunas, calcule as linhas"
print(arr.reshape(-1, 2))
# [[ 0 1]
# [ 2 3]
# [ 4 5]
# [ 6 7]
# [ 8 9]
# [10 11]]
# Forma: (6, 2) -- NumPy calculou 6 linhas
# Achatar para 1D
print(arr.reshape(-1))
# [ 0 1 2 3 4 5 6 7 8 9 10 11]
# Forma: (12,)
# Vetor coluna
print(arr.reshape(-1, 1).shape)
# (12, 1)Você só pode usar -1 para uma única dimensão. Usá-lo para duas ou mais dimensões gera um erro porque o cálculo se torna ambíguo.
import numpy as np
arr = np.arange(12)
# Isto FALHA:
# arr.reshape(-1, -1)
# ValueError: can only specify one unknown dimensionreshape() vs resize(): Diferenças principais
Ambas as funções alteram a forma dos arrays, mas se comportam de maneira muito diferente.
| Característica | reshape() | resize() |
|---|---|---|
| Retorna | Novo array (visualização ou cópia) | Modifica o array in-place (método) ou retorna novo array (função) |
| Tamanho deve corresponder | Sim -- total de elementos deve ser idêntico | Não -- preenche com zeros ou trunca |
| Array original | Inalterado | Modificado (ao usar ndarray.resize()) |
| Segurança | Lança erro em caso de incompatibilidade de tamanho | Preenche ou trunca silenciosamente |
| Uso comum | Reorganizar dimensões | Alterar o tamanho do array |
import numpy as np
arr = np.array([1, 2, 3, 4, 5, 6])
# reshape: deve manter o mesmo total de elementos
reshaped = arr.reshape(2, 3)
print(reshaped)
# [[1 2 3]
# [4 5 6]]
# np.resize (forma de função): preenche por repetição se o novo tamanho for maior
resized = np.resize(arr, (3, 3))
print(resized)
# [[1 2 3]
# [4 5 6]
# [1 2 3]] <-- repete desde o início
# np.resize: trunca se o novo tamanho for menor
resized_small = np.resize(arr, (2, 2))
print(resized_small)
# [[1 2]
# [3 4]]Use reshape() quando quiser reorganizar dimensões sem alterar os dados. Use resize() apenas quando genuinamente precisar alterar o número de elementos.
O parâmetro order: C vs F vs A
O parâmetro order controla como os elementos são lidos do array original e colocados na nova forma. Isso importa quando você trabalha com dados de diferentes linguagens de programação ou formatos de armazenamento.
import numpy as np
arr = np.array([1, 2, 3, 4, 5, 6])
# Ordem C (por linhas): preenche linha por linha -- este é o padrão
c_order = arr.reshape(2, 3, order='C')
print("Ordem C:")
print(c_order)
# [[1 2 3]
# [4 5 6]]
# Ordem F (por colunas): preenche coluna por coluna
f_order = arr.reshape(2, 3, order='F')
print("Ordem F:")
print(f_order)
# [[1 3 5]
# [2 4 6]]| Order | Nome | Preenchimento | Caso de uso |
|---|---|---|---|
'C' | Estilo C / Por linhas | Linha por linha (último índice muda mais rápido) | Layout de memória padrão Python/C/C++ |
'F' | Estilo Fortran / Por colunas | Coluna por coluna (primeiro índice muda mais rápido) | Dados de MATLAB, Fortran, R |
'A' | Automático | Usa F se o array for contíguo em Fortran, caso contrário C | Preservar layout de memória existente |
Na maioria das vezes você usará a ordem 'C' padrão. Você precisa da ordem 'F' ao carregar dados exportados do MATLAB ou Fortran, onde as matrizes são armazenadas coluna por coluna.
Visualizações vs cópias: Quando o reshape retorna uma visualização
Um detalhe crítico: reshape() retorna uma visualização do array original sempre que possível. Uma visualização compartilha a mesma memória subjacente. Modificar a visualização modifica o array original, e vice-versa.
import numpy as np
original = np.arange(6)
reshaped = original.reshape(2, 3)
# Modificar a visualização reformatada
reshaped[0, 0] = 999
print(original)
# [999 1 2 3 4 5] <-- o original também mudou!Se o NumPy não puder criar uma visualização (por exemplo, quando o layout de memória não é compatível com a nova forma), ele retorna uma cópia. Você pode forçar uma cópia explicitamente:
import numpy as np
original = np.arange(6)
reshaped_copy = original.reshape(2, 3).copy()
reshaped_copy[0, 0] = 999
print(original)
# [0 1 2 3 4 5] <-- o original NÃO é afetadoPara verificar se um reshape retornou uma visualização ou uma cópia, inspecione o atributo base:
import numpy as np
arr = np.arange(6)
view = arr.reshape(2, 3)
copy = arr.reshape(2, 3).copy()
print(view.base is arr) # True -- é uma visualização
print(copy.base is arr) # False -- é uma cópiaErros comuns e como corrigi-los
Erro: "cannot reshape array of size X into shape Y"
Este é o erro de reshape mais comum. Ocorre quando o número total de elementos não corresponde à forma alvo.
import numpy as np
arr = np.arange(10)
# Isto FALHA porque 10 != 3 * 4 = 12
# arr.reshape(3, 4)
# ValueError: cannot reshape array of size 10 into shape (3,4)Correções:
- Verifique seus cálculos. Certifique-se de que o produto de todas as dimensões alvo é igual a
arr.size.
import numpy as np
arr = np.arange(10)
print(arr.size) # 10
# Formas válidas para 10 elementos: (2,5), (5,2), (1,10), (10,1), (10,)
print(arr.reshape(2, 5))
# [[0 1 2 3 4]
# [5 6 7 8 9]]- Preencha ou corte o array se você realmente precisar de uma forma que não divide uniformemente.
import numpy as np
arr = np.arange(10)
# Preencher para 12 elementos, depois reformatar para (3, 4)
padded = np.pad(arr, (0, 2), constant_values=0)
print(padded.reshape(3, 4))
# [[0 1 2 3]
# [4 5 6 7]
# [8 9 0 0]]- Use -1 para que o NumPy calcule uma dimensão para você, evitando erros de cálculo manual.
import numpy as np
arr = np.arange(10)
print(arr.reshape(-1, 2))
# [[0 1]
# [2 3]
# [4 5]
# [6 7]
# [8 9]]Erro: "Expected 2D array, got 1D array instead"
Este erro do scikit-learn aparece quando você passa um array de features 1D. A correção é direta:
import numpy as np
features = np.array([1.5, 2.3, 3.1, 4.7, 5.0])
# Converter para vetor coluna
features_2d = features.reshape(-1, 1)
print(features_2d.shape)
# (5, 1)Exemplos práticos
Preparando dados para o Scikit-Learn
O scikit-learn espera matrizes de features com forma (n_samples, n_features). Veja como reformatar os dados corretamente para uma regressão linear simples:
import numpy as np
# Feature única: tamanhos de casas em pés quadrados
sizes = np.array([850, 1200, 1500, 1800, 2100, 2400, 2800])
# Reformatar para (n_samples, 1) para o sklearn
X = sizes.reshape(-1, 1)
print(X.shape)
# (7, 1)
# A variável alvo (preços) já é 1D, o que o sklearn aceita
y = np.array([150000, 220000, 275000, 320000, 380000, 430000, 510000])
# Agora X e y estão prontos para o sklearn
# from sklearn.linear_model import LinearRegression
# model = LinearRegression().fit(X, y)Reformatando dados de imagens
Trabalhar com conjuntos de dados de imagens frequentemente requer reformatar entre vetores planos e dimensões espaciais:
import numpy as np
# Simular o carregamento de uma imagem em escala de cinza 28x28 como array plano (como MNIST)
flat_image = np.random.randint(0, 256, size=784)
print(flat_image.shape)
# (784,)
# Reformatar para imagem 2D
image_2d = flat_image.reshape(28, 28)
print(image_2d.shape)
# (28, 28)
# Reformatar um lote de 100 imagens para entrada de rede neural
batch_flat = np.random.randint(0, 256, size=(100, 784))
batch_images = batch_flat.reshape(100, 28, 28, 1) # adicionar dimensão de canal
print(batch_images.shape)
# (100, 28, 28, 1)Transpondo com reshape (e por que você não deveria)
Um erro comum é usar reshape para "transpor" uma matriz. Reshape reordena elementos na ordem da memória, o que não é o mesmo que transpor.
import numpy as np
matrix = np.array([[1, 2, 3],
[4, 5, 6]])
# ERRADO: reshape(3, 2) NÃO transpõe
wrong = matrix.reshape(3, 2)
print("reshape(3,2):")
print(wrong)
# [[1 2]
# [3 4]
# [5 6]]
# CORRETO: use .T ou np.transpose()
correct = matrix.T
print("Transpor:")
print(correct)
# [[1 4]
# [2 5]
# [3 6]]Trabalhando com NumPy Reshape no RunCell
Se você reformata arrays frequentemente e quer um fluxo de trabalho mais rápido, RunCell (opens in a new tab) é um agente de IA que roda dentro de notebooks Jupyter. Foi construído para cientistas de dados que passam o dia escrevendo código NumPy, pandas e scikit-learn.
O RunCell pode ajudar com operações de reshape de várias formas:
- Depuração instantânea de formas. Quando você encontra um erro de incompatibilidade de forma, o RunCell lê o traceback e sugere a chamada reshape correta, incluindo as dimensões certas e o parâmetro order.
- Geração automática de código repetitivo. Descreva o que você precisa em linguagem natural -- "reformate este array plano em um lote de imagens 32x32 com 3 canais" -- e o RunCell escreve o código.
- Explorar alternativas. O RunCell pode mostrar se você deve usar
reshape,np.expand_dims,np.newaxisounp.squeezedependendo da sua situação específica.
Como o RunCell opera diretamente no seu ambiente Jupyter, você mantém controle total dos seus dados e código enquanto recebe sugestões assistidas por IA exatamente onde precisa.
FAQ
O que numpy reshape(-1) faz?
Chamar array.reshape(-1) achata o array em uma dimensão. O -1 diz ao NumPy para calcular o número total de elementos automaticamente. É equivalente a array.ravel() ou array.flatten(), embora reshape(-1) retorne uma visualização quando possível enquanto flatten() sempre retorna uma cópia.
O numpy reshape altera o array original?
Não. reshape() retorna um novo objeto array. No entanto, se o array retornado for uma visualização (o que geralmente é), modificar o array reformatado também modificará o original porque eles compartilham a mesma memória. Para evitar isso, chame .copy() no resultado.
Qual é a diferença entre reshape e flatten?
reshape() pode converter um array para qualquer forma compatível. flatten() sempre converte para um array 1D e sempre retorna uma cópia. ravel() também converte para 1D mas retorna uma visualização quando possível, similar a reshape(-1).
Posso reformatar um DataFrame do pandas com numpy reshape?
Não diretamente. Primeiro você precisa extrair o array NumPy subjacente usando df.values ou df.to_numpy(), e depois reformatá-lo. Para operações de reformatação específicas do DataFrame, use métodos do pandas como pivot(), melt(), stack() ou unstack().
Como reformato um array para adicionar um novo eixo?
Você pode usar reshape(), mas np.expand_dims() ou np.newaxis é mais limpo para adicionar uma única dimensão:
import numpy as np
arr = np.array([1, 2, 3])
# Usando reshape
print(arr.reshape(1, 3).shape) # (1, 3)
print(arr.reshape(3, 1).shape) # (3, 1)
# Usando np.newaxis (mais legível)
print(arr[np.newaxis, :].shape) # (1, 3)
print(arr[:, np.newaxis].shape) # (3, 1)Conclusão
numpy.reshape() é uma das funções mais frequentemente usadas na biblioteca NumPy. Ela permite converter entre arrays 1D, 2D, 3D e de dimensões superiores sem copiar dados (na maioria dos casos). Os pontos-chave a lembrar:
- O número total de elementos deve permanecer o mesmo antes e depois da reformatação.
- Use
-1para uma dimensão para que o NumPy a calcule automaticamente. reshape()geralmente retorna uma visualização, não uma cópia. Mudanças na visualização afetam o original.- O
order='C'padrão preenche elementos linha por linha. Useorder='F'para dados de coluna principal do MATLAB ou Fortran. - Quando o scikit-learn reclamar de arrays 1D,
.reshape(-1, 1)é sua solução.
Domine esses padrões e você lidará com incompatibilidades de forma com confiança, seja preparando dados tabulares para machine learning ou reformatando tensores de imagens para deep learning.