Skip to content

Commit 2bc0fdb

Browse files
realpython-botclaudebzaczynski
authored
Add runnable scripts to numpy-reshape materials (#788)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Co-authored-by: Bartosz Zaczyński <bartosz.zaczynski@gmail.com>
1 parent f22da9d commit 2bc0fdb

10 files changed

Lines changed: 183 additions & 2 deletions

numpy-reshape/README.md

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,44 @@
1-
# Image Repository For Using NumPy reshape() to Change the Shape of an Array
1+
# Using NumPy reshape() to Change the Shape of an Array
22

3-
This image repository accompanies [Using NumPy reshape() to Change the Shape of an Array](https://realpython.com/numpy-reshape/). It contains an image that you'll need while exploring the code in the tutorial.
3+
This folder contains the sample code and image that accompany the Real Python
4+
tutorial [Using NumPy reshape() to Change the Shape of an Array](https://realpython.com/numpy-reshape/).
5+
6+
## Setup
7+
8+
Create and activate a virtual environment, then install the requirements:
9+
10+
```console
11+
$ python -m venv venv
12+
$ source venv/bin/activate
13+
(venv) $ python -m pip install -r requirements.txt
14+
```
15+
16+
## Scripts
17+
18+
Each script is self-contained and mirrors one section of the tutorial. The
19+
scripts that use random data seed the generator so that the output is
20+
reproducible.
21+
22+
| Script | Tutorial section |
23+
| --- | --- |
24+
| `array_shape.py` | Understand the shape of NumPy arrays |
25+
| `change_shape.py` | Change an array's shape using `reshape()` |
26+
| `reduce_dimensions.py` | Reduce an array's number of dimensions |
27+
| `increase_dimensions.py` | Increase an array's number of dimensions |
28+
| `compatible_shapes.py` | Ensure the new shape is compatible |
29+
| `order_parameter.py` | Control how data is rearranged using `order` |
30+
| `color_image.py` | Reduce a 3D color image to two dimensions |
31+
| `wildcard.py` | Use `-1` as an argument in `reshape()` |
32+
33+
Run any script with Python:
34+
35+
```console
36+
(venv) $ python change_shape.py
37+
```
38+
39+
`color_image.py` reads `poppy.jpg` from this folder and opens the reshaped
40+
images in your default image viewer, so run it from this directory.
441

542
## Image Credit
43+
644
- poppy.jpg: [Pixabay](https://pixabay.com/photos/poppy-summer-red-nature-flower-2381645/) by [kellepics](https://pixabay.com/users/kellepics-4893063/)

numpy-reshape/array_shape.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
"""Inspect the shape and number of dimensions of a NumPy array."""
2+
3+
import numpy as np
4+
5+
numbers = np.array([[1, 2, 3, 4], [5, 6, 7, 8]])
6+
print(numbers)
7+
print(f"Shape: {numbers.shape}")
8+
print(f"Number of dimensions: {numbers.ndim}")

numpy-reshape/change_shape.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
"""Change an array's shape with reshape() without changing its data.
2+
3+
The random generator is seeded so that the output is reproducible.
4+
"""
5+
6+
import numpy as np
7+
8+
rng = np.random.default_rng(seed=42)
9+
results = rng.integers(0, 100, size=(5, 10))
10+
print(f"Original results, shape {results.shape}:")
11+
print(results)
12+
13+
# Reshape the five classes of ten scores into a single row
14+
year_results = results.reshape((1, 50))
15+
print(f"\nReshaped to one row, shape {year_results.shape}:")
16+
print(year_results)
17+
18+
# year_results is still 2D, so you index it with both a row and a column
19+
print(f"\nFirst score: {year_results[0, 0]}")

numpy-reshape/color_image.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
"""Reshape a 3D color image into a 2D triptych of its color channels.
2+
3+
Run this script from the folder that contains poppy.jpg. Each reshaped
4+
image opens in your default image viewer.
5+
"""
6+
7+
import numpy as np
8+
from PIL import Image
9+
10+
with Image.open("poppy.jpg") as photo:
11+
image_array = np.array(photo)
12+
13+
print(f"Image shape: {image_array.shape}")
14+
height, width, _ = image_array.shape
15+
16+
# The default order="C" interleaves each pixel's color channels
17+
triptych_c = image_array.reshape((height, 3 * width))
18+
print(f"Reshaped shape: {triptych_c.shape}")
19+
Image.fromarray(triptych_c).show()
20+
21+
# order="F" places the red, green, and blue channels side by side
22+
triptych_f = image_array.reshape((height, 3 * width), order="F")
23+
Image.fromarray(triptych_f).show()

numpy-reshape/compatible_shapes.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
"""Reshape into compatible shapes by trimming or extending the data."""
2+
3+
import numpy as np
4+
5+
rng = np.random.default_rng(seed=42)
6+
temperatures = rng.normal(18, 1, size=200)
7+
8+
# An incompatible shape raises a ValueError
9+
try:
10+
temperatures.reshape((3, 7, 8))
11+
except ValueError as error:
12+
print(f"ValueError: {error}")
13+
14+
days_per_week = 7
15+
readings_per_day = 8
16+
number_of_weeks = len(temperatures) // (days_per_week * readings_per_day)
17+
trimmed_length = number_of_weeks * days_per_week * readings_per_day
18+
19+
# Option 1: trim the data so that it fits a whole number of weeks
20+
temperatures_week = temperatures[:trimmed_length].reshape(
21+
(number_of_weeks, days_per_week, readings_per_day)
22+
)
23+
print(f"Trimmed shape: {temperatures_week.shape}")
24+
25+
# Option 2: extend the data with np.nan filler values
26+
extended_length = (number_of_weeks + 1) * (days_per_week * readings_per_day)
27+
additional_length = extended_length - len(temperatures)
28+
temperatures_extended = np.append(
29+
temperatures, np.full(additional_length, np.nan)
30+
)
31+
temperatures_week = temperatures_extended.reshape(
32+
(number_of_weeks + 1, days_per_week, readings_per_day)
33+
)
34+
print(f"Extended shape: {temperatures_week.shape}")
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
"""Increase the number of dimensions of an array with reshape()."""
2+
3+
import numpy as np
4+
5+
rng = np.random.default_rng(seed=42)
6+
temperatures = rng.normal(18, 1, size=200)
7+
print(f"Original shape: {temperatures.shape}")
8+
9+
# 200 readings, eight per day, gives 25 rows of eight columns
10+
temperatures_day = temperatures.reshape((25, 8))
11+
print(f"Reshaped into days, shape: {temperatures_day.shape}")
12+
print("Second day's readings:")
13+
print(temperatures_day[1])

numpy-reshape/order_parameter.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
"""Control how reshape() rearranges data with the order parameter."""
2+
3+
import numpy as np
4+
5+
numbers = np.array([1, 2, 3, 4, 5, 6, 7, 8])
6+
7+
# Row-major (C) order fills each row before moving to the next
8+
print('order="C":')
9+
print(numbers.reshape((2, 4), order="C"))
10+
11+
# Column-major (F) order fills each column before moving to the next
12+
print('order="F":')
13+
print(numbers.reshape((2, 4), order="F"))

numpy-reshape/reduce_dimensions.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
"""Reduce the number of dimensions of an array with reshape()."""
2+
3+
import numpy as np
4+
5+
rng = np.random.default_rng(seed=42)
6+
results = rng.integers(0, 100, size=(5, 10))
7+
8+
# Pass a one-element tuple to reshape the 2D array into a 1D array
9+
year_results = results.reshape((50,))
10+
print(f"Shape: {year_results.shape}, dimensions: {year_results.ndim}")
11+
print(f"First score: {year_results[0]}")
12+
13+
# Passing a single integer gives the same 1D result
14+
same_results = results.reshape(50)
15+
print(f"Integer argument gives the same shape: {same_results.shape}")

numpy-reshape/requirements.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
numpy==2.5.0
2+
Pillow==12.2.0

numpy-reshape/wildcard.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
"""Use -1 as a wildcard dimension in reshape()."""
2+
3+
import numpy as np
4+
5+
rng = np.random.default_rng(seed=42)
6+
temperatures = rng.normal(18, 1, size=200)
7+
8+
# Let reshape() infer the first dimension's length with -1
9+
temperatures_day = temperatures.reshape((-1, 8))
10+
print(f"Inferred shape: {temperatures_day.shape}")
11+
12+
# Use -1 to flatten an array of any shape into a single dimension
13+
numbers = rng.integers(1, 100, (2, 4, 3, 3))
14+
print(f"Original shape: {numbers.shape}")
15+
numbers_flattened = numbers.reshape(-1)
16+
print(f"Flattened shape: {numbers_flattened.shape}")

0 commit comments

Comments
 (0)