3D Indexing & Slicing
Navigate a 3D array (seasons × players × matches) with arr[i, j, k], and slice any combination of axes.
Two IPL seasons, three players, eight matches each — that is a 3D array of shape (2, 3, 8). Think of it as a stack of 2D tables: one scores table per season. Colour images are also 3D (height × width × colour channels), so this skill comes back in image processing.
text
two_seasons.shape = (2, 3, 8)
│ │ └─ axis 2: match (0..7)
│ └──── axis 1: player (0 Virat, 1 Rohit, 2 Hardik)
└─────── axis 0: season (0 = 2023, 1 = 2024)
season 0 (2023) season 1 (2024)
[[72 45 88 31 64 0 103 52] [[65 80 44 91 33 58 22 71]
[56 0 74 88 32 45 61 17] [39 55 82 0 77 21 64 48]
[45 32 0 67 18 54 78 22]] [28 44 63 37 82 0 55 71]]Definition
3D indexing selects data from a three-dimensional array by giving up to three comma-separated indexes or slices — one per axis — in the form
arr[i, j, k]. Hereipicks the "table" (axis 0),jthe row inside that table (axis 1) andkthe column (axis 2). Each integer removes its axis from the result; each slice keeps it.
- Up to three — three integers give one scalar; fewer integers give a smaller array.
- Missing trailing indexes mean "all":
arr[0]=arr[0, :, :]= the whole 2023 table. - Ellipsis
...— shorthand for "as many:as needed":arr[..., 0]=arr[:, :, 0](match 1 for every season and player).
Syntax
python
arr[i, j, k] # one element -> scalar
arr[i] # 2D table i (shape: axis1 x axis2)
arr[i, j] # 1D row j of table i (shape: axis2)
arr[:, j, :] # row j from every table (2D)
arr[:, :, k] # column k from every table (2D)
arr[..., k] # same as arr[:, :, k]| Index position | Axis | Meaning here | Valid range |
|---|---|---|---|
| 1st | 0 | season | 0…1 |
| 2nd | 1 | player | 0…2 |
| 3rd | 2 | match | 0…7 |
Example — single values and whole tables
python
import numpy as np
two_seasons = np.array([
[ # Season 1 (2023)
[72, 45, 88, 31, 64, 0, 103, 52], # Virat
[56, 0, 74, 88, 32, 45, 61, 17], # Rohit
[45, 32, 0, 67, 18, 54, 78, 22], # Hardik
],
[ # Season 2 (2024)
[65, 80, 44, 91, 33, 58, 22, 71], # Virat
[39, 55, 82, 0, 77, 21, 64, 48], # Rohit
[28, 44, 63, 37, 82, 0, 55, 71], # Hardik
],
])
print("shape:", two_seasons.shape, " ndim:", two_seasons.ndim)
print("Season 1, Virat, match 1 :", two_seasons[0, 0, 0])
print("Season 2, Rohit, match 3 :", two_seasons[1, 1, 2])
print("Season 2 table:")
print(two_seasons[1])
print("Season 1, Hardik:", two_seasons[0, 2])text
shape: (2, 3, 8) ndim: 3
Season 1, Virat, match 1 : 72
Season 2, Rohit, match 3 : 82
Season 2 table:
[[65 80 44 91 33 58 22 71]
[39 55 82 0 77 21 64 48]
[28 44 63 37 82 0 55 71]]
Season 1, Hardik: [45 32 0 67 18 54 78 22]How it works: [1, 1, 2] → season index 1 (2024), player 1 (Rohit), match index 2 → 82. two_seasons[1] fixes only the season, so the full 3×8 table for 2024 comes back.
Example — slicing across seasons
python
two_seasons = np.array([
[ # Season 1 (2023)
[72, 45, 88, 31, 64, 0, 103, 52], # Virat
[56, 0, 74, 88, 32, 45, 61, 17], # Rohit
[45, 32, 0, 67, 18, 54, 78, 22], # Hardik
],
[ # Season 2 (2024)
[65, 80, 44, 91, 33, 58, 22, 71], # Virat
[39, 55, 82, 0, 77, 21, 64, 48], # Rohit
[28, 44, 63, 37, 82, 0, 55, 71], # Hardik
],
])
print("Virat in both seasons:")
print(two_seasons[:, 0, :])
print("Match 1 of every player, both seasons:")
print(two_seasons[:, :, 0])
print("Same with Ellipsis:")
print(two_seasons[..., 0])
print("Season 1, all players, match 1:", two_seasons[0, :, 0])text
Virat in both seasons:
[[ 72 45 88 31 64 0 103 52]
[ 65 80 44 91 33 58 22 71]]
Match 1 of every player, both seasons:
[[72 56 45]
[65 39 28]]
Same with Ellipsis:
[[72 56 45]
[65 39 28]]
Season 1, all players, match 1: [72 56 45]How it works: [:, 0, :] keeps axis 0 (both seasons) and axis 2 (all matches) but fixes player 0 → a 2×8 table of Virat's runs. [:, :, 0] fixes the match → a 2×3 table (season × player).
Example — shapes of different selections
python
two_seasons = np.array([
[ # Season 1 (2023)
[72, 45, 88, 31, 64, 0, 103, 52], # Virat
[56, 0, 74, 88, 32, 45, 61, 17], # Rohit
[45, 32, 0, 67, 18, 54, 78, 22], # Hardik
],
[ # Season 2 (2024)
[65, 80, 44, 91, 33, 58, 22, 71], # Virat
[39, 55, 82, 0, 77, 21, 64, 48], # Rohit
[28, 44, 63, 37, 82, 0, 55, 71], # Hardik
],
])
for expr in ["two_seasons[0]", "two_seasons[0, 1]", "two_seasons[0, 1, 2]",
"two_seasons[:, 1]", "two_seasons[:, :, -2:]", "two_seasons[:, 0:1, :]"]:
print(f"{expr:<24} -> shape {np.shape(eval(expr))}")text
two_seasons[0] -> shape (3, 8)
two_seasons[0, 1] -> shape (8,)
two_seasons[0, 1, 2] -> shape ()
two_seasons[:, 1] -> shape (2, 8)
two_seasons[:, :, -2:] -> shape (2, 3, 2)
two_seasons[:, 0:1, :] -> shape (2, 1, 8)How it works: count the integers — each integer removes one axis. [0, 1, 2] removes all three → shape () (a scalar). Slices like -2: or 0:1 keep their axis.
Comparison — 1D vs 2D vs 3D indexing
| Array | Shape | Full address | Example | Meaning |
|---|---|---|---|---|
| 1D | (14,) | [match] | virat_runs[6] | Virat, match 7 |
| 2D | (3, 8) | [player, match] | scores[1, 2] | Rohit, match 3 |
| 3D | (2, 3, 8) | [season, player, match] | two_seasons[1, 1, 2] | 2024, Rohit, match 3 |
The pattern never changes: one comma-separated position per axis, in shape order.
Common mistakes
- ❌
two_seasons[0][0][0]— works, but indexes three times and breaks with slices (same problem as 2D). ✅two_seasons[0, 0, 0]. - ❌ Guessing the axis order. ✅ Print
.shapefirst and write the meaning of each axis in a comment, e.g.# (season, player, match). - ❌
two_seasons[2, 0, 0]— there are only 2 seasons →IndexError: index 2 is out of bounds for axis 0 with size 2. - ❌ Thinking
arr[..., 0]is special syntax only for 3D. ✅...works for any number of dimensions.
Interview tip
Q: A colour image has shape (480, 640, 3). How do you get the red channel?
A: img[:, :, 0] (or img[..., 0]) — all rows, all columns, channel 0. The result is a 2D array of shape (480, 640).
Key points to remember
- A 3D array is a stack of 2D tables; shape (2, 3, 8) here means (season, player, match).
- Use one comma-separated index or slice per axis: arr[i, j, k].
- Three integers return a scalar; arr[i] returns a whole 2D table; arr[i, j] returns a 1D row.
- Missing trailing indexes mean 'all': arr[0] == arr[0, :, :].
- The Ellipsis ... stands for as many : as needed — arr[..., 0] == arr[:, :, 0].
- Every integer removes its axis from the result; every slice keeps it.
Try it yourself
Values, tables and rows of a 3D array
Ellipsis and season totals
Practice: Rohit's improvement
Revision Flashcards
Tap a card to flip it and see the answer.
