Skip to content
Temas
NumPy
NumPy Reshape: How to Change Array Shapes in Python

NumPy Reshape: Cómo cambiar la forma de arrays en Python

Updated on

Tienes una lista plana de 10.000 valores de píxeles y una red neuronal que espera una matriz de imagen de 100x100. O quizás scikit-learn está lanzando un error porque tu array de características es unidimensional cuando necesita ser un vector columna. Estos no son casos excepcionales -- son obstáculos diarios para cualquiera que trabaje con datos numéricos en Python. La función que los resuelve es numpy.reshape(), y entenderla correctamente ahorra horas de depuración.

📚

¿Qué hace numpy reshape?

numpy.reshape() cambia la forma de un array sin cambiar sus datos. Toma los mismos elementos y los reorganiza en un nuevo conjunto de dimensiones. Un array 1D con 12 elementos puede convertirse en una matriz 3x4, una matriz 2x6, una matriz 4x3, o incluso un array tridimensional 2x2x3. La única regla es que el número total de elementos debe permanecer igual.

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)

El array original a sigue existiendo con su forma original. El array reformado b es una nueva vista de los mismos datos (más sobre vistas vs copias después).

Sintaxis básica y parámetros

Hay dos formas de reformar un array en NumPy:

# Método 1: Como función
np.reshape(array, newshape, order='C')
 
# Método 2: Como método del array
array.reshape(newshape, order='C')
ParámetroTipoDescripción
arrayndarrayEl array a reformar (solo para la forma de función np.reshape())
newshapeint o tupla de intsLa forma objetivo. Una dimensión puede ser -1, que se calcula automáticamente.
order'C', 'F' o 'A'Orden de lectura/escritura de elementos. 'C' = por filas (predeterminado), 'F' = por columnas, 'A' = orden Fortran si el array es contiguo en Fortran, orden C en caso contrario.

Ambas formas producen resultados idénticos. La forma de método (array.reshape()) es más común porque se lee de forma más natural en el código.

Reformar arrays de 1D a 2D

Esta es la operación de reshape más frecuente. Empiezas con un array plano y necesitas una matriz.

import numpy as np
 
# Array 1D con 8 elementos
data = np.array([10, 20, 30, 40, 50, 60, 70, 80])
 
# Reformar a 2 filas, 4 columnas
matrix_2x4 = data.reshape(2, 4)
print(matrix_2x4)
# [[10 20 30 40]
#  [50 60 70 80]]
 
# Reformar a 4 filas, 2 columnas
matrix_4x2 = data.reshape(4, 2)
print(matrix_4x2)
# [[10 20]
#  [30 40]
#  [50 60]
#  [70 80]]
 
# Reformar a un vector columna (8 filas, 1 columna)
column_vector = data.reshape(8, 1)
print(column_vector)
# [[10]
#  [20]
#  [30]
#  [40]
#  [50]
#  [60]
#  [70]
#  [80]]
 
print(column_vector.shape)
# (8, 1)

La reformación a vector columna (n, 1) es particularmente importante. Muchas funciones de scikit-learn requieren entrada 2D incluso para una sola característica. Si pasas un array 1D, obtienes el error Expected 2D array, got 1D array instead. La solución es .reshape(-1, 1).

Reformar de 2D a 3D (Para Machine Learning y Deep Learning)

Los frameworks de deep learning como TensorFlow y PyTorch a menudo requieren tensores de entrada 3D o 4D. Por ejemplo, un lote de imágenes en escala de grises necesita la forma (batch_size, height, width), y un lote de imágenes a color necesita (batch_size, height, width, channels).

import numpy as np
 
# Simular 4 imágenes en escala de grises de 3x3 almacenadas como filas en un array 2D
images_2d = np.arange(36).reshape(4, 9)
print(images_2d.shape)
# (4, 9)
 
# Reformar a (lote, alto, ancho)
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 imágenes a color con 3 canales (RGB):

import numpy as np
 
# 2 imágenes a color, cada una de 4x4 con 3 canales, almacenadas planas
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)

El truco del -1: Calcular una dimensión automáticamente

Cuando estableces una dimensión en -1, NumPy la calcula automáticamente basándose en el número total de elementos y las otras dimensiones que especificaste. Esta es una de las características más útiles de reshape.

import numpy as np
 
arr = np.arange(12)
 
# "Dame 3 filas, calcula las columnas"
print(arr.reshape(3, -1))
# [[ 0  1  2  3]
#  [ 4  5  6  7]
#  [ 8  9 10 11]]
# Forma: (3, 4) -- NumPy calculó 4 columnas
 
# "Dame 2 columnas, calcula las filas"
print(arr.reshape(-1, 2))
# [[ 0  1]
#  [ 2  3]
#  [ 4  5]
#  [ 6  7]
#  [ 8  9]
#  [10 11]]
# Forma: (6, 2) -- NumPy calculó 6 filas
 
# Aplanar a 1D
print(arr.reshape(-1))
# [ 0  1  2  3  4  5  6  7  8  9 10 11]
# Forma: (12,)
 
# Vector columna
print(arr.reshape(-1, 1).shape)
# (12, 1)

Solo puedes usar -1 para una única dimensión. Usarlo para dos o más dimensiones genera un error porque el cálculo se vuelve ambiguo.

import numpy as np
 
arr = np.arange(12)
 
# Esto FALLA:
# arr.reshape(-1, -1)
# ValueError: can only specify one unknown dimension

reshape() vs resize(): Diferencias clave

Ambas funciones cambian la forma de los arrays, pero se comportan de manera muy diferente.

Característicareshape()resize()
RetornaNuevo array (vista o copia)Modifica el array in-place (método) o retorna nuevo array (función)
El tamaño debe coincidirSí -- el total de elementos debe ser idénticoNo -- rellena con ceros o trunca
Array originalSin cambiosModificado (al usar ndarray.resize())
SeguridadLanza error si los tamaños no coincidenRellena o trunca silenciosamente
Uso comúnReorganizar dimensionesCambiar el tamaño del array
import numpy as np
 
arr = np.array([1, 2, 3, 4, 5, 6])
 
# reshape: debe mantener el mismo total de elementos
reshaped = arr.reshape(2, 3)
print(reshaped)
# [[1 2 3]
#  [4 5 6]]
 
# np.resize (forma de función): rellena repitiendo si el nuevo tamaño es mayor
resized = np.resize(arr, (3, 3))
print(resized)
# [[1 2 3]
#  [4 5 6]
#  [1 2 3]]   <-- repite desde el principio
 
# np.resize: trunca si el nuevo tamaño es menor
resized_small = np.resize(arr, (2, 2))
print(resized_small)
# [[1 2]
#  [3 4]]

Usa reshape() cuando quieras reorganizar dimensiones sin cambiar los datos. Usa resize() solo cuando genuinamente necesites cambiar el número de elementos.

El parámetro order: C vs F vs A

El parámetro order controla cómo se leen los elementos del array original y se colocan en la nueva forma. Esto importa cuando trabajas con datos de diferentes lenguajes de programación o formatos de almacenamiento.

import numpy as np
 
arr = np.array([1, 2, 3, 4, 5, 6])
 
# Orden C (por filas): llena fila por fila -- esto es el predeterminado
c_order = arr.reshape(2, 3, order='C')
print("Orden C:")
print(c_order)
# [[1 2 3]
#  [4 5 6]]
 
# Orden F (por columnas): llena columna por columna
f_order = arr.reshape(2, 3, order='F')
print("Orden F:")
print(f_order)
# [[1 3 5]
#  [2 4 6]]
OrderNombreRellenaCaso de uso
'C'Estilo C / Por filasFila por fila (el último índice cambia más rápido)Diseño de memoria predeterminado de Python/C/C++
'F'Estilo Fortran / Por columnasColumna por columna (el primer índice cambia más rápido)Datos de MATLAB, Fortran, R
'A'AutomáticoUsa F si el array es contiguo en Fortran, de lo contrario CPreservar el diseño de memoria existente

La mayoría de las veces usarás el orden 'C' predeterminado. Necesitas el orden 'F' cuando cargas datos exportados desde MATLAB o Fortran, donde las matrices se almacenan columna por columna.

Vistas vs copias: Cuándo reshape devuelve una vista

Un detalle crítico: reshape() devuelve una vista del array original siempre que sea posible. Una vista comparte la misma memoria subyacente. Modificar la vista modifica el array original, y viceversa.

import numpy as np
 
original = np.arange(6)
reshaped = original.reshape(2, 3)
 
# Modificar la vista reformada
reshaped[0, 0] = 999
 
print(original)
# [999   1   2   3   4   5]   <-- ¡el original también cambió!

Si NumPy no puede crear una vista (por ejemplo, cuando el diseño de memoria no es compatible con la nueva forma), devuelve una copia en su lugar. Puedes forzar una copia explícitamente:

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]   <-- el original NO se ve afectado

Para verificar si un reshape devolvió una vista o una copia, inspecciona el 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 -- es una vista
print(copy.base is arr)   # False -- es una copia

Errores comunes y cómo solucionarlos

Error: "cannot reshape array of size X into shape Y"

Este es el error de reshape más común. Ocurre cuando el número total de elementos no coincide con la forma objetivo.

import numpy as np
 
arr = np.arange(10)
 
# Esto FALLA porque 10 != 3 * 4 = 12
# arr.reshape(3, 4)
# ValueError: cannot reshape array of size 10 into shape (3,4)

Soluciones:

  1. Verifica tu cálculo. Asegúrate de que el producto de todas las dimensiones objetivo sea 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]]
  1. Rellena o recorta el array si realmente necesitas una forma que no divide uniformemente.
import numpy as np
 
arr = np.arange(10)
 
# Rellenar a 12 elementos, luego reformar a (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]]
  1. Usa -1 para que NumPy calcule una dimensión por ti, evitando errores 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]]

Error: "Expected 2D array, got 1D array instead"

Este error de scikit-learn aparece cuando pasas un array de características 1D. La solución es directa:

import numpy as np
 
features = np.array([1.5, 2.3, 3.1, 4.7, 5.0])
 
# Convertir a vector columna
features_2d = features.reshape(-1, 1)
print(features_2d.shape)
# (5, 1)

Ejemplos prácticos

Preparar datos para Scikit-Learn

scikit-learn espera matrices de características con forma (n_samples, n_features). Así es como se reforman los datos correctamente para una regresión lineal simple:

import numpy as np
 
# Característica única: tamaños de casas en pies cuadrados
sizes = np.array([850, 1200, 1500, 1800, 2100, 2400, 2800])
 
# Reformar a (n_samples, 1) para sklearn
X = sizes.reshape(-1, 1)
print(X.shape)
# (7, 1)
 
# La variable objetivo (precios) ya es 1D, lo cual sklearn acepta
y = np.array([150000, 220000, 275000, 320000, 380000, 430000, 510000])
 
# Ahora X e y están listos para sklearn
# from sklearn.linear_model import LinearRegression
# model = LinearRegression().fit(X, y)

Reformar datos de imágenes

Trabajar con conjuntos de datos de imágenes a menudo requiere reformar entre vectores planos y dimensiones espaciales:

import numpy as np
 
# Simular la carga de una imagen en escala de grises de 28x28 como array plano (como MNIST)
flat_image = np.random.randint(0, 256, size=784)
print(flat_image.shape)
# (784,)
 
# Reformar a imagen 2D
image_2d = flat_image.reshape(28, 28)
print(image_2d.shape)
# (28, 28)
 
# Reformar un lote de 100 imágenes para la entrada de una red neuronal
batch_flat = np.random.randint(0, 256, size=(100, 784))
batch_images = batch_flat.reshape(100, 28, 28, 1)  # agregar dimensión de canal
print(batch_images.shape)
# (100, 28, 28, 1)

Transponer con reshape (y por qué no deberías hacerlo)

Un error común es usar reshape para "transponer" una matriz. Reshape reordena elementos en orden de memoria, lo cual no es lo mismo que transponer.

import numpy as np
 
matrix = np.array([[1, 2, 3],
                   [4, 5, 6]])
 
# INCORRECTO: reshape(3, 2) NO transpone
wrong = matrix.reshape(3, 2)
print("reshape(3,2):")
print(wrong)
# [[1 2]
#  [3 4]
#  [5 6]]
 
# CORRECTO: usa .T o np.transpose()
correct = matrix.T
print("Transponer:")
print(correct)
# [[1 4]
#  [2 5]
#  [3 6]]

Trabajar con NumPy Reshape en RunCell

Si reformas arrays frecuentemente y quieres un flujo de trabajo más rápido, RunCell (opens in a new tab) es un agente de IA que se ejecuta dentro de notebooks Jupyter. Está diseñado para científicos de datos que pasan su día escribiendo código NumPy, pandas y scikit-learn.

RunCell puede ayudar con operaciones de reshape de varias formas:

  • Depuración instantánea de formas. Cuando encuentras un error de incompatibilidad de formas, RunCell lee el traceback y sugiere la llamada reshape correcta, incluyendo las dimensiones correctas y el parámetro order.
  • Generación automática de código repetitivo. Describe lo que necesitas en lenguaje natural -- "reforma este array plano en un lote de imágenes de 32x32 con 3 canales" -- y RunCell escribe el código.
  • Explorar alternativas. RunCell puede mostrarte si debes usar reshape, np.expand_dims, np.newaxis o np.squeeze dependiendo de tu situación específica.

Como RunCell opera directamente en tu entorno Jupyter, mantienes el control total de tus datos y código mientras recibes sugerencias asistidas por IA exactamente donde las necesitas.

FAQ

¿Qué hace numpy reshape(-1)?

Llamar a array.reshape(-1) aplana el array en una dimensión. El -1 le dice a NumPy que calcule el número total de elementos automáticamente. Es equivalente a array.ravel() o array.flatten(), aunque reshape(-1) devuelve una vista cuando es posible mientras que flatten() siempre devuelve una copia.

¿Numpy reshape cambia el array original?

No. reshape() devuelve un nuevo objeto array. Sin embargo, si el array devuelto es una vista (lo cual suele ser el caso), modificar el array reformado también modificará el original porque comparten la misma memoria. Para evitar esto, llama a .copy() sobre el resultado.

¿Cuál es la diferencia entre reshape y flatten?

reshape() puede convertir un array a cualquier forma compatible. flatten() siempre convierte a un array 1D y siempre devuelve una copia. ravel() también convierte a 1D pero devuelve una vista cuando es posible, similar a reshape(-1).

¿Puedo reformar un DataFrame de pandas con numpy reshape?

No directamente. Primero necesitas extraer el array NumPy subyacente usando df.values o df.to_numpy(), y luego reformarlo. Para operaciones de reformación específicas de DataFrame, usa métodos de pandas como pivot(), melt(), stack() o unstack().

¿Cómo reformo un array para agregar un nuevo eje?

Puedes usar reshape(), pero np.expand_dims() o np.newaxis es más limpio para agregar una sola dimensión:

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 (más legible)
print(arr[np.newaxis, :].shape)  # (1, 3)
print(arr[:, np.newaxis].shape)  # (3, 1)

Conclusión

numpy.reshape() es una de las funciones más utilizadas en la biblioteca NumPy. Te permite convertir entre arrays 1D, 2D, 3D y de dimensiones superiores sin copiar datos (en la mayoría de los casos). Los puntos clave a recordar:

  • El número total de elementos debe permanecer igual antes y después de reformar.
  • Usa -1 para una dimensión para que NumPy la calcule automáticamente.
  • reshape() generalmente devuelve una vista, no una copia. Los cambios en la vista afectan al original.
  • El order='C' predeterminado llena elementos fila por fila. Usa order='F' para datos de columna mayor de MATLAB o Fortran.
  • Cuando scikit-learn se queja de arrays 1D, .reshape(-1, 1) es tu solución.

Domina estos patrones y manejarás las incompatibilidades de forma con confianza, ya sea que estés preparando datos tabulares para machine learning o reformando tensores de imágenes para deep learning.

📚