Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 40 additions & 2 deletions numpy-reshape/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,44 @@
# Image Repository For Using NumPy reshape() to Change the Shape of an Array
# Using NumPy reshape() to Change the Shape of an Array

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.
This folder contains the sample code and image that accompany the Real Python
tutorial [Using NumPy reshape() to Change the Shape of an Array](https://realpython.com/numpy-reshape/).

## Setup

Create and activate a virtual environment, then install the requirements:

```console
$ python -m venv venv
$ source venv/bin/activate
(venv) $ python -m pip install -r requirements.txt
```

## Scripts

Each script is self-contained and mirrors one section of the tutorial. The
scripts that use random data seed the generator so that the output is
reproducible.

| Script | Tutorial section |
| --- | --- |
| `array_shape.py` | Understand the shape of NumPy arrays |
| `change_shape.py` | Change an array's shape using `reshape()` |
| `reduce_dimensions.py` | Reduce an array's number of dimensions |
| `increase_dimensions.py` | Increase an array's number of dimensions |
| `compatible_shapes.py` | Ensure the new shape is compatible |
| `order_parameter.py` | Control how data is rearranged using `order` |
| `color_image.py` | Reduce a 3D color image to two dimensions |
| `wildcard.py` | Use `-1` as an argument in `reshape()` |

Run any script with Python:

```console
(venv) $ python change_shape.py
```

`color_image.py` reads `poppy.jpg` from this folder and opens the reshaped
images in your default image viewer, so run it from this directory.

## Image Credit

- poppy.jpg: [Pixabay](https://pixabay.com/photos/poppy-summer-red-nature-flower-2381645/) by [kellepics](https://pixabay.com/users/kellepics-4893063/)
8 changes: 8 additions & 0 deletions numpy-reshape/array_shape.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
"""Inspect the shape and number of dimensions of a NumPy array."""

import numpy as np

numbers = np.array([[1, 2, 3, 4], [5, 6, 7, 8]])
print(numbers)
print(f"Shape: {numbers.shape}")
print(f"Number of dimensions: {numbers.ndim}")
19 changes: 19 additions & 0 deletions numpy-reshape/change_shape.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
"""Change an array's shape with reshape() without changing its data.

The random generator is seeded so that the output is reproducible.
"""

import numpy as np

rng = np.random.default_rng(seed=42)
results = rng.integers(0, 100, size=(5, 10))
print(f"Original results, shape {results.shape}:")
print(results)

# Reshape the five classes of ten scores into a single row
year_results = results.reshape((1, 50))
print(f"\nReshaped to one row, shape {year_results.shape}:")
print(year_results)

# year_results is still 2D, so you index it with both a row and a column
print(f"\nFirst score: {year_results[0, 0]}")
23 changes: 23 additions & 0 deletions numpy-reshape/color_image.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
"""Reshape a 3D color image into a 2D triptych of its color channels.

Run this script from the folder that contains poppy.jpg. Each reshaped
image opens in your default image viewer.
"""

import numpy as np
from PIL import Image

with Image.open("poppy.jpg") as photo:
image_array = np.array(photo)

print(f"Image shape: {image_array.shape}")
height, width, _ = image_array.shape

# The default order="C" interleaves each pixel's color channels
triptych_c = image_array.reshape((height, 3 * width))
print(f"Reshaped shape: {triptych_c.shape}")
Image.fromarray(triptych_c).show()

# order="F" places the red, green, and blue channels side by side
triptych_f = image_array.reshape((height, 3 * width), order="F")
Image.fromarray(triptych_f).show()
34 changes: 34 additions & 0 deletions numpy-reshape/compatible_shapes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
"""Reshape into compatible shapes by trimming or extending the data."""

import numpy as np

rng = np.random.default_rng(seed=42)
temperatures = rng.normal(18, 1, size=200)

# An incompatible shape raises a ValueError
try:
temperatures.reshape((3, 7, 8))
except ValueError as error:
print(f"ValueError: {error}")

days_per_week = 7
readings_per_day = 8
number_of_weeks = len(temperatures) // (days_per_week * readings_per_day)
trimmed_length = number_of_weeks * days_per_week * readings_per_day

# Option 1: trim the data so that it fits a whole number of weeks
temperatures_week = temperatures[:trimmed_length].reshape(
(number_of_weeks, days_per_week, readings_per_day)
)
print(f"Trimmed shape: {temperatures_week.shape}")

# Option 2: extend the data with np.nan filler values
extended_length = (number_of_weeks + 1) * (days_per_week * readings_per_day)
additional_length = extended_length - len(temperatures)
temperatures_extended = np.append(
temperatures, np.full(additional_length, np.nan)
)
temperatures_week = temperatures_extended.reshape(
(number_of_weeks + 1, days_per_week, readings_per_day)
)
print(f"Extended shape: {temperatures_week.shape}")
13 changes: 13 additions & 0 deletions numpy-reshape/increase_dimensions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
"""Increase the number of dimensions of an array with reshape()."""

import numpy as np

rng = np.random.default_rng(seed=42)
temperatures = rng.normal(18, 1, size=200)
print(f"Original shape: {temperatures.shape}")

# 200 readings, eight per day, gives 25 rows of eight columns
temperatures_day = temperatures.reshape((25, 8))
print(f"Reshaped into days, shape: {temperatures_day.shape}")
print("Second day's readings:")
print(temperatures_day[1])
13 changes: 13 additions & 0 deletions numpy-reshape/order_parameter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
"""Control how reshape() rearranges data with the order parameter."""

import numpy as np

numbers = np.array([1, 2, 3, 4, 5, 6, 7, 8])

# Row-major (C) order fills each row before moving to the next
print('order="C":')
print(numbers.reshape((2, 4), order="C"))

# Column-major (F) order fills each column before moving to the next
print('order="F":')
print(numbers.reshape((2, 4), order="F"))
15 changes: 15 additions & 0 deletions numpy-reshape/reduce_dimensions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
"""Reduce the number of dimensions of an array with reshape()."""

import numpy as np

rng = np.random.default_rng(seed=42)
results = rng.integers(0, 100, size=(5, 10))

# Pass a one-element tuple to reshape the 2D array into a 1D array
year_results = results.reshape((50,))
print(f"Shape: {year_results.shape}, dimensions: {year_results.ndim}")
print(f"First score: {year_results[0]}")

# Passing a single integer gives the same 1D result
same_results = results.reshape(50)
print(f"Integer argument gives the same shape: {same_results.shape}")
2 changes: 2 additions & 0 deletions numpy-reshape/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
numpy==2.5.0
Pillow==12.2.0
16 changes: 16 additions & 0 deletions numpy-reshape/wildcard.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
"""Use -1 as a wildcard dimension in reshape()."""

import numpy as np

rng = np.random.default_rng(seed=42)
temperatures = rng.normal(18, 1, size=200)

# Let reshape() infer the first dimension's length with -1
temperatures_day = temperatures.reshape((-1, 8))
print(f"Inferred shape: {temperatures_day.shape}")

# Use -1 to flatten an array of any shape into a single dimension
numbers = rng.integers(1, 100, (2, 4, 3, 3))
print(f"Original shape: {numbers.shape}")
numbers_flattened = numbers.reshape(-1)
print(f"Flattened shape: {numbers_flattened.shape}")
Loading