Q&A library Python

How do I select elements of a NumPy array by condition?

Python Advanced boolean-maskfancy-indexingnumpy

Short answer

Build a boolean array from a condition and use it to index, or pass a list of positions for fancy indexing. Both return a copy, and boolean masks combine with the bitwise operators, not and or.

The short version

Index a NumPy array with a boolean array to keep the elements where it is True, or with a list of integer positions to pick those positions (fancy indexing). Both return a new array (a copy), not a view. Combine boolean conditions with the bitwise operators &, | and ~, each condition in brackets, because Python's and and or do not work element by element.

Boolean masking

import numpy as np

arr = np.array([10, 20, 30, 40])

print(arr[arr > 20])   # [30 40]

The expression arr > 20 produces a boolean array [False, False, True, True], and indexing with it keeps the True positions. This is the array equivalent of filtering.

Combining conditions

Use bitwise operators, and bracket each condition.

arr[(arr > 15) & (arr < 35)]   # [20 30]

Writing arr > 15 and arr < 35 raises ValueError: The truth value of an array is ambiguous, because and tries to collapse a whole array to one True or False. Always use & and | on arrays.

Fancy indexing by position

Passing a list or array of integers selects those positions, in the order given, which also lets you repeat or reorder elements.

arr[[0, 2]]        # [10 30]
arr[[2, 2, 0]]     # [30 30 10], repeats and reorders

Both return copies

Unlike a basic slice, both boolean masking and fancy indexing return an independent copy, so modifying the result does not touch the original. If you want to modify the original at those positions, assign back into it using the same index.

arr[arr > 20] = 0        # sets matching elements in arr itself
print(arr)               # [10 20  0  0]

Assigning through the mask writes back to arr, which is the idiomatic way to update selected elements in place.

Two-dimensional selection

For a 2D array, you can mask the whole thing (which flattens the result) or select rows and columns with integer arrays.

grid = np.array([[1, 2], [3, 4]])
grid[grid > 2]        # [3 4], flattened
grid[[0, 1], [1, 0]]  # [2 3], element (0,1) and (1,0)

The paired lists in the last example select specific coordinates, which is powerful but easy to misread, so comment it when you use it.

Why this matters for performance

Masking and fancy indexing run in fast compiled code across the whole array, so they replace explicit Python loops over elements. Reaching for a boolean mask instead of a for loop is one of the core habits that makes NumPy code both short and quick.

Need this solved on your own data?

The library is free and always will be. When the problem is bigger than an answer, we take on the work.

Start a project