Python NumPy: How to Access Different Rows of a Multidimensional NumPy Array in Python
When working with multidimensional NumPy arrays, you frequently need to access specific rows - whether it's the first row, the last two rows, middle rows, or a combination of non-contiguous rows. NumPy provides powerful indexing and slicing syntax that makes row selection intuitive and efficient.
This guide covers how to access rows in 2D and 3D arrays using slicing, fancy indexing, and combined row-column selection.
Accessing Rows in a 2D Array
Selecting a Single Row
Use a single index to access one row:
import numpy as np
arr = np.array([
[10, 20, 30],
[40, 50, 60],
[70, 80, 90]
])
# First row
print("First row:", arr[0])
# Last row
print("Last row:", arr[-1])
# Middle row (index 1)
print("Middle row:", arr[1])
Output:
First row: [10 20 30]
Last row: [70 80 90]
Middle row: [40 50 60]
Selecting Multiple Rows with Slicing
Use the start:stop:step syntax to select a range of rows:
import numpy as np
arr = np.array([
[10, 20, 30],
[40, 50, 60],
[70, 80, 90],
[100, 110, 120]
])
# First two rows
print("First 2 rows:\n", arr[:2])
# Last two rows
print("Last 2 rows:\n", arr[-2:])
# Every other row
print("Every other row:\n", arr[::2])
Output:
First 2 rows:
[[10 20 30]
[40 50 60]]
Last 2 rows:
[[ 70 80 90]
[100 110 120]]
Every other row:
[[ 10 20 30]
[ 70 80 90]]
Selecting Non-Contiguous Rows (Fancy Indexing)
To select specific rows that aren't adjacent, pass a list of indices:
import numpy as np
arr = np.array([
[10, 20, 30],
[40, 50, 60],
[70, 80, 90],
[100, 110, 120]
])
# Select the first and last rows
selected = arr[[0, 3]]
print("First and last rows:\n", selected)
# Select rows 0, 2 (every other row, but explicitly)
selected = arr[[0, 2]]
print("Rows 0 and 2:\n", selected)
Output:
First and last rows:
[[ 10 20 30]
[100 110 120]]
Rows 0 and 2:
[[10 20 30]
[70 80 90]]
- Slicing (
arr[1:3]) - selects a contiguous range and returns a view (shares memory with the original). - Fancy indexing (
arr[[0, 2]]) - selects arbitrary rows and returns a copy (independent of the original).
import numpy as np
arr = np.array([[1, 2], [3, 4], [5, 6]])
# Slicing: view (modifications affect original)
view = arr[0:2]
view[0, 0] = 99
print("Original after slice modification:", arr[0, 0]) # 99
# Fancy indexing: copy (modifications don't affect original)
arr = np.array([[1, 2], [3, 4], [5, 6]])
copy = arr[[0, 1]]
copy[0, 0] = 99
print("Original after fancy index modification:", arr[0, 0]) # 1
Output:
Original after slice modification: 99
Original after fancy index modification: 1
Selecting Specific Rows AND Columns
Combine row and column indexing to extract a sub-matrix:
import numpy as np
arr = np.array([
[12, 15, 18],
[25, 30, 35],
[40, 45, 50]
])
# First 2 rows, first 2 columns
sub = arr[:2, :2]
print("Sub-matrix:\n", sub)
# Last row, last 2 columns
sub = arr[-1, -2:]
print("Last row, last 2 cols:", sub)
# Rows 0 and 2, column 1 only
sub = arr[[0, 2], 1]
print("Rows 0,2 column 1:", sub)
Output:
Sub-matrix:
[[12 15]
[25 30]]
Last row, last 2 cols: [45 50]
Rows 0,2 column 1: [15 45]
Accessing Rows in a 3D Array
A 3D array can be thought of as a collection of 2D matrices (or "slices"). The dimensions are typically: [slice, row, column].
import numpy as np
arr = np.array([
[[10, 25, 70],
[30, 45, 55],
[20, 45, 7]],
[[50, 65, 8],
[70, 85, 10],
[11, 22, 33]]
])
print("Shape:", arr.shape) # (2, 3, 3) → 2 slices, 3 rows, 3 columns
Output:
Shape: (2, 3, 3)
Selecting a Row Across All Slices
Use : for the first dimension to select from all slices, then specify the row index:
import numpy as np
arr = np.array([
[[10, 25, 70],
[30, 45, 55],
[20, 45, 7]],
[[50, 65, 8],
[70, 85, 10],
[11, 22, 33]]
])
# Middle row (index 1) from all slices
middle_rows = arr[:, 1]
print("Middle row from each slice:\n", middle_rows)
Output:
Middle row from each slice:
[[30 45 55]
[70 85 10]]
Selecting Multiple Rows Across All Slices
import numpy as np
arr = np.array([
[[10, 25, 70],
[30, 45, 55],
[20, 45, 7]],
[[50, 65, 8],
[70, 85, 10],
[11, 22, 33]]
])
# First and last rows from all slices
selected = arr[:, [0, 2]]
print("First and last rows from each slice:\n", selected)
Output:
First and last rows from each slice:
[[[10 25 70]
[20 45 7]]
[[50 65 8]
[11 22 33]]]
Selecting Specific Rows and Columns in 3D
import numpy as np
arr = np.array([
[[ 5, 10, 15],
[20, 25, 30],
[35, 40, 45]],
[[ 2, 4, 6],
[ 8, 10, 12],
[14, 16, 18]],
[[ 7, 14, 21],
[28, 35, 42],
[49, 56, 63]]
])
# First 2 rows and first 2 columns from each slice
sub = arr[:, :2, :2]
print("Sub-arrays:\n", sub)
Output:
Sub-arrays:
[[[ 5 10]
[20 25]]
[[ 2 4]
[ 8 10]]
[[ 7 14]
[28 35]]]
Conditional Row Selection
Select rows based on a condition applied to the data:
import numpy as np
arr = np.array([
[10, 20, 30],
[40, 50, 60],
[5, 15, 25],
[70, 80, 90]
])
# Select rows where the first column value is greater than 20
mask = arr[:, 0] > 20
selected = arr[mask]
print("Rows where first column > 20:\n", selected)
Output:
Rows where first column > 20:
[[40 50 60]
[70 80 90]]
This is especially useful for filtering data based on specific criteria.
Quick Reference
| Task | Syntax | Example |
|---|---|---|
| Single row | arr[i] | arr[2] |
| Row range | arr[start:stop] | arr[1:3] |
| Last N rows | arr[-N:] | arr[-2:] |
| Every Nth row | arr[::N] | arr[::2] |
| Specific rows | arr[[i, j, k]] | arr[[0, 2, 4]] |
| Rows + columns | arr[rows, cols] | arr[:2, :2] |
| 3D: row across slices | arr[:, i] | arr[:, 1] |
| Conditional rows | arr[condition] | arr[arr[:, 0] > 20] |
Conclusion
NumPy's indexing and slicing syntax makes accessing rows in multidimensional arrays both intuitive and efficient.
- Use slicing (
arr[1:3]) for contiguous row ranges, fancy indexing (arr[[0, 2]]) for non-contiguous selections, and boolean masks for conditional filtering. - For 3D arrays, remember the dimension order is
[slice, row, column]and use:to select across all elements of a dimension.
Understanding the difference between views (from slicing) and copies (from fancy indexing) helps you write correct and performant code.