Module 2 · Lesson 5

np.newaxis and ... (Ellipsis)

np.newaxis (an alias for None) inserts a new length-1 axis at the position you place it — the standard way to turn a 1-D array into an explicit row or column vector, which matters a lot once you start broadcasting (Module 3). ... (Ellipsis) means “as many full slices : as needed to cover the remaining axes” — handy for indexing deep into a high-dimensional array without writing a : for every axis in between.

v = np.array([1, 2, 3])
print(v.shape)                       # (3,)
print(v[:, np.newaxis].shape)        # (3, 1) -- column vector
print(v[np.newaxis, :].shape)        # (1, 3) -- row vector

cube = np.arange(24).reshape(2, 3, 4)
print(cube[..., 0].shape)            # same as cube[:, :, 0] -> (2, 3)
print(cube[0, ...].shape)            # same as cube[0, :, :] -> (3, 4)

grid = np.zeros((3, 3))
grid[1, :] = [7, 8, 9]               # assign into a slice
print(grid)

Output:

(3,)
(3, 1)
(1, 3)
(2, 3)
(3, 4)
[[0. 0. 0.]
 [7. 8. 9.]
 [0. 0. 0.]]
5.1

To column vector

Write to_column(v) that takes a 1-D array of shape (n,) and returns it reshaped to a column vector of shape (n, 1) using np.newaxis (not .reshape).

💡 Hint

v[:, np.newaxis] adds a new axis at position 1.

✅ Solution
def to_column(v):
    return v[:, np.newaxis]
5.2

First channel of any stack of images

Write first_channel(images) that takes an array of shape (n_images, height, width, n_channels) (or any number of leading axes followed by a channel axis last) and returns just channel 0 for every image, using ... so your function works regardless of how many leading axes there are.

💡 Hint

images[..., 0] takes channel 0 regardless of how many axes come before it.

✅ Solution
def first_channel(images):
    return images[..., 0]

🎯 Key Takeaways

Next up: Module 3 — Array Operations & Broadcasting, where the shapes you’ve been building here start combining with each other automatically.