Understanding Indexing in NumPy
At first glance, indexing in NumPy might seem like a small detail—but it’s actually one of the most powerful tools in your toolkit. It’s how you tap into specific values, reshape data, and slice through complex arrays with precision.
Think of it this way: if arrays are the foundation of NumPy, indexing is the key that unlocks their full potential.
1D Array Indexing
A 1-dimensional array behaves like a Python list. You can access elements by their zero-based index. Let’s start small:
import numpy as np
arr = np.array([10, 20, 30, 40, 50])
print(arr[0]) # First element
print(arr[-1]) # Last element
Expected Output
10
50
Explanation: arr[0]
returns the first item. arr[-1]
fetches the last item using negative indexing. NumPy mirrors Python’s indexing rules.
2D Array Indexing
Two-dimensional arrays are like grids: rows and columns. You access elements using arr[row, column]
syntax.
matrix = np.array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
print(matrix[0, 1]) # First row, second column
print(matrix[2, 2]) # Third row, third column
Expected Output
2
9
Explanation: matrix[0, 1]
picks the value 2, found at the intersection of the first row and second column. This format avoids nested indexing and is highly readable.
3D Array Indexing
Three-dimensional arrays add another layer of depth — literally. Think of them as a stack of 2D matrices.
tensor = np.array([[[1, 2],
[3, 4]],
[[5, 6],
[7, 8]]])
print(tensor[0, 1, 1]) # From first block, second row, second column
print(tensor[1, 0, 0]) # From second block, first row, first column
Expected Output
4
5
Explanation: In tensor[0, 1, 1]
, we’re navigating:
- 0 → first 2D matrix (or depth index)
- 1 → second row
- 1 → second column
tensor[1, 0, 0]
navigates to the second 2D matrix, first row, first column — returning 5.
Indexing Gotchas and Checks
When working with indexing, always verify:
- Shape Awareness: Use
arr.shape
to avoid index out-of-bounds errors. - Zero-based Indexing: Python and NumPy start at 0, not 1.
- Negative Indexing: It counts from the end but is limited to the axis you’re indexing.
print(tensor.shape) # (2, 2, 2)
print(tensor[2, 0, 0]) # Error: index 2 is out of bounds
Always check the shape before slicing or indexing to prevent runtime errors.
Layered Access for Beginners
If the full indexing syntax looks overwhelming, remember you can layer your access:
# Equivalent to tensor[0, 1, 1]
layer = tensor[0]
row = layer[1]
value = row[1]
print(value)
This style makes debugging easier and clarifies what’s happening at each step.
Key Takeaways
- 1D: Access with one index — like a list
- 2D: Use two indices —
[row, col]
- 3D: Use three indices —
[depth, row, col]
- Negative indices work on all dimensions
- Always check the array shape using
arr.shape