NumPy Reshape: How to Change Array Shapes in Python
Updated on
You have a flat list of 10,000 pixel values and a neural network that expects a 100x100 image matrix. Or maybe scikit-learn is throwing an error because your feature array is one-dimensional when it needs to be a column vector. These are not edge cases -- they are daily roadblocks for anyone working with numerical data in Python. The function that solves them is numpy.reshape(), and understanding it properly saves hours of debugging.
What Does numpy reshape Do?
numpy.reshape() changes the shape of an array without changing its data. It takes the same elements and rearranges them into a new set of dimensions. A 1D array with 12 elements can become a 3x4 matrix, a 2x6 matrix, a 4x3 matrix, or even a 2x2x3 three-dimensional array. The only rule is that the total number of elements must stay the same.
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)The original array a still exists with its original shape. The reshaped array b is a new view of the same data (more on views vs copies later).
Basic Syntax and Parameters
There are two ways to reshape an array in NumPy:
# Method 1: As a function
np.reshape(array, newshape, order='C')
# Method 2: As an array method
array.reshape(newshape, order='C')| Parameter | Type | Description |
|---|---|---|
array | ndarray | The array to reshape (only for np.reshape() function form) |
newshape | int or tuple of ints | The target shape. One dimension can be -1, which is inferred automatically. |
order | 'C', 'F', or 'A' | Read/write order of elements. 'C' = row-major (default), 'F' = column-major, 'A' = Fortran-order if array is Fortran-contiguous, C-order otherwise. |
Both forms produce identical results. The method form (array.reshape()) is more common because it reads naturally in code.
Reshaping 1D to 2D Arrays
This is the most frequent reshape operation. You start with a flat array and need a matrix.
import numpy as np
# 1D array with 8 elements
data = np.array([10, 20, 30, 40, 50, 60, 70, 80])
# Reshape to 2 rows, 4 columns
matrix_2x4 = data.reshape(2, 4)
print(matrix_2x4)
# [[10 20 30 40]
# [50 60 70 80]]
# Reshape to 4 rows, 2 columns
matrix_4x2 = data.reshape(4, 2)
print(matrix_4x2)
# [[10 20]
# [30 40]
# [50 60]
# [70 80]]
# Reshape to a single-column vector (8 rows, 1 column)
column_vector = data.reshape(8, 1)
print(column_vector)
# [[10]
# [20]
# [30]
# [40]
# [50]
# [60]
# [70]
# [80]]
print(column_vector.shape)
# (8, 1)The column vector reshape (n, 1) is particularly important. Many scikit-learn functions require 2D input even for a single feature. If you pass a 1D array, you get the error Expected 2D array, got 1D array instead. The fix is .reshape(-1, 1).
Reshaping 2D to 3D (For Machine Learning and Deep Learning)
Deep learning frameworks like TensorFlow and PyTorch often require 3D or 4D input tensors. For example, a batch of grayscale images needs shape (batch_size, height, width), and a batch of color images needs (batch_size, height, width, channels).
import numpy as np
# Simulate 4 grayscale 3x3 images stored as rows in a 2D array
images_2d = np.arange(36).reshape(4, 9)
print(images_2d.shape)
# (4, 9)
# Reshape to (batch, height, width)
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]]For color images with 3 channels (RGB):
import numpy as np
# 2 color images, each 4x4 with 3 channels, stored flat
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)The -1 Trick: Auto-Calculating One Dimension
When you set one dimension to -1, NumPy calculates it automatically based on the total number of elements and the other dimensions you specified. This is one of the most useful features of reshape.
import numpy as np
arr = np.arange(12)
# "Give me 3 rows, figure out the columns"
print(arr.reshape(3, -1))
# [[ 0 1 2 3]
# [ 4 5 6 7]
# [ 8 9 10 11]]
# Shape: (3, 4) -- NumPy calculated 4 columns
# "Give me 2 columns, figure out the rows"
print(arr.reshape(-1, 2))
# [[ 0 1]
# [ 2 3]
# [ 4 5]
# [ 6 7]
# [ 8 9]
# [10 11]]
# Shape: (6, 2) -- NumPy calculated 6 rows
# Flatten to 1D
print(arr.reshape(-1))
# [ 0 1 2 3 4 5 6 7 8 9 10 11]
# Shape: (12,)
# Column vector
print(arr.reshape(-1, 1).shape)
# (12, 1)You can only use -1 for a single dimension. Using it for two or more dimensions raises an error because the calculation becomes ambiguous.
import numpy as np
arr = np.arange(12)
# This FAILS:
# arr.reshape(-1, -1)
# ValueError: can only specify one unknown dimensionreshape() vs resize(): Key Differences
Both functions change array shapes, but they behave very differently.
| Feature | reshape() | resize() |
|---|---|---|
| Returns | New array (view or copy) | Modifies array in-place (method) or returns new array (function) |
| Size must match | Yes -- total elements must be identical | No -- pads with zeros or truncates |
| Original array | Unchanged | Modified (when using ndarray.resize()) |
| Safety | Raises error on size mismatch | Silently pads or truncates |
| Common usage | Rearranging dimensions | Changing array size |
import numpy as np
arr = np.array([1, 2, 3, 4, 5, 6])
# reshape: must keep same total elements
reshaped = arr.reshape(2, 3)
print(reshaped)
# [[1 2 3]
# [4 5 6]]
# np.resize (function form): pads by repeating if new size is larger
resized = np.resize(arr, (3, 3))
print(resized)
# [[1 2 3]
# [4 5 6]
# [1 2 3]] <-- repeats from the beginning
# np.resize: truncates if new size is smaller
resized_small = np.resize(arr, (2, 2))
print(resized_small)
# [[1 2]
# [3 4]]Use reshape() when you want to rearrange dimensions without changing data. Use resize() only when you genuinely need to change the number of elements.
The Order Parameter: C vs F vs A
The order parameter controls how elements are read from the original array and placed into the new shape. This matters when you are working with data from different programming languages or storage formats.
import numpy as np
arr = np.array([1, 2, 3, 4, 5, 6])
# C order (row-major): fills row by row -- this is the default
c_order = arr.reshape(2, 3, order='C')
print("C order:")
print(c_order)
# [[1 2 3]
# [4 5 6]]
# F order (column-major): fills column by column
f_order = arr.reshape(2, 3, order='F')
print("F order:")
print(f_order)
# [[1 3 5]
# [2 4 6]]| Order | Name | Fills | Use Case |
|---|---|---|---|
'C' | C-style / Row-major | Row by row (last index changes fastest) | Default Python/C/C++ memory layout |
'F' | Fortran-style / Column-major | Column by column (first index changes fastest) | MATLAB, Fortran, R data |
'A' | Auto | Uses F if array is Fortran-contiguous, else C | Preserving existing memory layout |
Most of the time you will use the default 'C' order. You need 'F' order when loading data exported from MATLAB or Fortran, where matrices are stored column-by-column.
Views vs Copies: When Reshape Returns a View
A critical detail: reshape() returns a view of the original array whenever possible. A view shares the same underlying memory. Modifying the view modifies the original array, and vice versa.
import numpy as np
original = np.arange(6)
reshaped = original.reshape(2, 3)
# Modify the reshaped view
reshaped[0, 0] = 999
print(original)
# [999 1 2 3 4 5] <-- original changed too!If NumPy cannot create a view (for example, when the memory layout is not compatible with the new shape), it returns a copy instead. You can force a copy explicitly:
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] <-- original is NOT affectedTo check whether a reshape returned a view or a copy, inspect the base attribute:
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 -- it's a view
print(copy.base is arr) # False -- it's a copyCommon Errors and How to Fix Them
Error: "cannot reshape array of size X into shape Y"
This is the most common reshape error. It occurs when the total number of elements does not match the target shape.
import numpy as np
arr = np.arange(10)
# This FAILS because 10 != 3 * 4 = 12
# arr.reshape(3, 4)
# ValueError: cannot reshape array of size 10 into shape (3,4)Fixes:
- Check your math. Make sure the product of all target dimensions equals
arr.size.
import numpy as np
arr = np.arange(10)
print(arr.size) # 10
# Valid shapes for 10 elements: (2,5), (5,2), (1,10), (10,1), (10,)
print(arr.reshape(2, 5))
# [[0 1 2 3 4]
# [5 6 7 8 9]]- Pad or trim the array if you truly need a shape that does not divide evenly.
import numpy as np
arr = np.arange(10)
# Pad to 12 elements, then reshape to (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 to let NumPy calculate one dimension for you, avoiding manual arithmetic errors.
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"
This scikit-learn error appears when you pass a 1D feature array. The fix is straightforward:
import numpy as np
features = np.array([1.5, 2.3, 3.1, 4.7, 5.0])
# Convert to column vector
features_2d = features.reshape(-1, 1)
print(features_2d.shape)
# (5, 1)Practical Examples
Preparing Data for Scikit-Learn
scikit-learn expects feature matrices with shape (n_samples, n_features). Here is how to reshape data correctly for a simple linear regression:
import numpy as np
# Single feature: house sizes in square feet
sizes = np.array([850, 1200, 1500, 1800, 2100, 2400, 2800])
# Reshape to (n_samples, 1) for sklearn
X = sizes.reshape(-1, 1)
print(X.shape)
# (7, 1)
# Target variable (prices) is already 1D, which sklearn accepts
y = np.array([150000, 220000, 275000, 320000, 380000, 430000, 510000])
# Now X and y are ready for sklearn
# from sklearn.linear_model import LinearRegression
# model = LinearRegression().fit(X, y)Reshaping Image Data
Working with image datasets often requires reshaping between flat vectors and spatial dimensions:
import numpy as np
# Simulate loading a 28x28 grayscale image as a flat array (like MNIST)
flat_image = np.random.randint(0, 256, size=784)
print(flat_image.shape)
# (784,)
# Reshape to 2D image
image_2d = flat_image.reshape(28, 28)
print(image_2d.shape)
# (28, 28)
# Reshape a batch of 100 images for a neural network input
batch_flat = np.random.randint(0, 256, size=(100, 784))
batch_images = batch_flat.reshape(100, 28, 28, 1) # add channel dimension
print(batch_images.shape)
# (100, 28, 28, 1)Transposing with Reshape (and Why You Should Not)
A common mistake is using reshape to "transpose" a matrix. Reshape reorders elements in memory order, which is not the same as transposing.
import numpy as np
matrix = np.array([[1, 2, 3],
[4, 5, 6]])
# WRONG: reshape(3, 2) does NOT transpose
wrong = matrix.reshape(3, 2)
print("reshape(3,2):")
print(wrong)
# [[1 2]
# [3 4]
# [5 6]]
# CORRECT: use .T or np.transpose()
correct = matrix.T
print("Transpose:")
print(correct)
# [[1 4]
# [2 5]
# [3 6]]Working with NumPy Reshape in RunCell
If you frequently reshape arrays and want a faster workflow, RunCell (opens in a new tab) is an AI agent that runs inside Jupyter notebooks. It is built for data scientists who spend their day writing NumPy, pandas, and scikit-learn code.
RunCell can help with reshape operations in several ways:
- Instant shape debugging. When you hit a shape mismatch error, RunCell reads the traceback and suggests the correct reshape call, including the right dimensions and order parameter.
- Auto-generating boilerplate. Describe what you need in plain language -- "reshape this flat array into a batch of 32x32 images with 3 channels" -- and RunCell writes the code.
- Exploring alternatives. RunCell can show you whether to use
reshape,np.expand_dims,np.newaxis, ornp.squeezedepending on your specific situation.
Since RunCell operates directly in your Jupyter environment, you keep full control of your data and code while getting AI-assisted suggestions exactly where you need them.
FAQ
What does numpy reshape(-1) do?
Calling array.reshape(-1) flattens the array into one dimension. The -1 tells NumPy to calculate the total number of elements automatically. It is equivalent to array.ravel() or array.flatten(), though reshape(-1) returns a view when possible while flatten() always returns a copy.
Does numpy reshape change the original array?
No. reshape() returns a new array object. However, if the returned array is a view (which it usually is), modifying the reshaped array will also modify the original because they share the same memory. To avoid this, call .copy() on the result.
What is the difference between reshape and flatten?
reshape() can convert an array to any compatible shape. flatten() always converts to a 1D array and always returns a copy. ravel() also converts to 1D but returns a view when possible, similar to reshape(-1).
Can I reshape a pandas DataFrame with numpy reshape?
Not directly. You first need to extract the underlying NumPy array using df.values or df.to_numpy(), then reshape it. For DataFrame-specific reshaping operations, use pandas methods like pivot(), melt(), stack(), or unstack().
How do I reshape an array to add a new axis?
You can use reshape(), but np.expand_dims() or np.newaxis is cleaner for adding a single dimension:
import numpy as np
arr = np.array([1, 2, 3])
# Using reshape
print(arr.reshape(1, 3).shape) # (1, 3)
print(arr.reshape(3, 1).shape) # (3, 1)
# Using np.newaxis (more readable)
print(arr[np.newaxis, :].shape) # (1, 3)
print(arr[:, np.newaxis].shape) # (3, 1)Conclusion
numpy.reshape() is one of the most frequently used functions in the NumPy library. It lets you convert between 1D, 2D, 3D, and higher-dimensional arrays without copying data (in most cases). The key points to remember:
- The total number of elements must stay the same before and after reshaping.
- Use
-1for one dimension to let NumPy calculate it automatically. reshape()usually returns a view, not a copy. Changes to the view affect the original.- The default
order='C'fills elements row by row. Useorder='F'for column-major data from MATLAB or Fortran. - When scikit-learn complains about 1D arrays,
.reshape(-1, 1)is your fix.
Master these patterns and you will handle shape mismatches confidently, whether you are preparing tabular data for machine learning or reshaping image tensors for deep learning.