NumPy: Boolean and Fancy Indexing

Last updated: 2026-08-26

1. What You'll Learn



2. Story

Alice has 100,000 temperature readings and needs to find all readings above 40°C. She writes temps[temps > 40] and gets the result instantly. Bob is amazed: "A Python loop with if statements would take at least 5 lines — NumPy does it in one line, nearly 100x faster!" This is the power of NumPy advanced indexing — complex data filtering with concise expressions.



3. Boolean Masks

(1) What Is a Boolean Mask

A boolean mask is a True/False array with the same shape as the original. NumPy comparison operators work element-wise and return boolean arrays.

PYTHON
import numpy as np

arr = np.array([3, -1, 4, -2, 5])
mask = arr > 0
print(mask)   # [ True False  True False  True]
print(arr[mask])  # [3 4 5]
TEXT 📖 Display only
> **Output:** Run NumPy 2.x in your local Python environment to see the ndarray output. The Piston server does not have NumPy pre-installed — install it locally (`pip install numpy`) and compare. Actual values may vary by NumPy version and random seed.

(2) Comparison Operators

Operator Meaning Equivalent Function
> Greater than np.greater
>= Greater or equal np.greater_equal
< Less than np.less
<= Less or equal np.less_equal
== Equal np.equal
!= Not equal np.not_equal

(3) Logical Combinations

Combine multiple conditions with logical operators — use & (and), | (or), ~ (not), not Python's and/or/not. Each condition must be wrapped in parentheses.

PYTHON
arr = np.array([1, 5, 8, 3, 9, 2])
mask = (arr > 3) & (arr < 8)   # 3 < arr < 8
print(arr[mask])  # [5]
TEXT 📖 Display only
> **Output:** Run NumPy 2.x in your local Python environment to see the ndarray output. The Piston server does not have NumPy pre-installed — install it locally (`pip install numpy`) and compare. Actual values may vary by NumPy version and random seed.
Logical Op Meaning Equivalent Function
& Logical AND np.logical_and
| Logical OR np.logical_or
~ Logical NOT np.logical_not


4. np.where and Conditional Selection

(1) Three-argument form: np.where(condition, x, y)

Returns elements from x where condition is True, from y where False.

PYTHON
import numpy as np

arr = np.array([-3, 5, -1, 8, -2, 7])
result = np.where(arr > 0, arr, 0)
print(result)  # [0 5 0 8 0 7]
TEXT 📖 Display only
> **Output:** Run NumPy 2.x in your local Python environment to see the ndarray output. The Piston server does not have NumPy pre-installed — install it locally (`pip install numpy`) and compare. Actual values may vary by NumPy version and random seed.

(2) One-argument form: np.where(condition)

Returns the indices where the condition is True.

PYTHON
indices = np.where(arr > 0)
print(indices)  # (array([1, 3, 5]),)
print(arr[indices])  # [5 8 7]
TEXT 📖 Display only
> **Output:** Run NumPy 2.x in your local Python environment to see the ndarray output. The Piston server does not have NumPy pre-installed — install it locally (`pip install numpy`) and compare. Actual values may vary by NumPy version and random seed.


5. Fancy Indexing

Fancy indexing uses integer arrays to select elements in any order.

PYTHON
import numpy as np

a = np.arange(10)  # [0 1 2 3 4 5 6 7 8 9]

# Select specific indices
print(a[[0, 3, 7]])      # [0 3 7]

# Select in any order, with repeats
print(a[[5, 5, 1, 9]])   # [5 5 1 9]

# 2D fancy indexing
b = np.arange(12).reshape(3, 4)
print(b[[0, 2]])          # rows 0 and 2
print(b[:, [0, 2, 3]])    # columns 0, 2, 3 for all rows
TEXT 📖 Display only
> **Output:** Run NumPy 2.x in your local Python environment to see the ndarray output. The Piston server does not have NumPy pre-installed — install it locally (`pip install numpy`) and compare. Actual values may vary by NumPy version and random seed.
⚠️ Note: The code below needs to run in a local Python environment.


▶ Example

TEXT 📖 Display only
> **Output:** Run NumPy 2.x in your local Python environment to see the ndarray output. The Piston server does not have NumPy pre-installed — install it locally (`pip install numpy`) and compare. Actual values may vary by NumPy version and random seed.

: Boolean mask filtering (Difficulty ⭐)

PYTHON
import numpy as np

scores = np.array([55, 82, 91, 47, 73, 100, 68])

passing = scores[scores >= 60]
print("Passing:", passing)  # [82 91 73 100 68]

excellent = scores[scores >= 90]
print("Excellent:", excellent)  # [91 100]

# Multiple conditions
mid = scores[(scores >= 60) & (scores < 90)]
print("Mid-range:", mid)  # [82 73 68]
TEXT 📖 Display only
> **Output:** Run NumPy 2.x in your local Python environment to see the ndarray output. The Piston server does not have NumPy pre-installed — install it locally (`pip install numpy`) and compare. Actual values may vary by NumPy version and random seed.
⚠️ Note: The code below needs to run in a local Python environment.

▶ Example

TEXT 📖 Display only
> **Output:** Run NumPy 2.x in your local Python environment to see the ndarray output. The Piston server does not have NumPy pre-installed — install it locally (`pip install numpy`) and compare. Actual values may vary by NumPy version and random seed.

: np.where for conditional replacement (Difficulty ⭐⭐)

PYTHON
import numpy as np

# Clip to range: replace values outside [0, 100]
data = np.array([-5, 120, 30, -20, 80, 200])
clipped = np.where(data < 0, 0, np.where(data > 100, 100, data))
print("Clipped:", clipped)  # [  0 100  30   0  80 100]

# Categorize
grades = np.array([45, 72, 88, 55, 91])
letter = np.where(grades >= 85, 'A',
          np.where(grades >= 70, 'B',
          np.where(grades >= 60, 'C', 'D')))
print("Grades:", letter)  # ['D' 'B' 'A' 'D' 'A']
TEXT 📖 Display only
> **Output:** Run NumPy 2.x in your local Python environment to see the ndarray output. The Piston server does not have NumPy pre-installed — install it locally (`pip install numpy`) and compare. Actual values may vary by NumPy version and random seed.
⚠️ Note: The code below needs to run in a local Python environment.



6. Comparison Tables

(1) Indexing Methods

Method Syntax Returns Copies? Use Case
Basic slice a[1:3] View No Sub-array, contiguous range
Integer index a[2] Scalar N/A Single element
Boolean mask a[mask] 1D array Yes Conditional filtering
Fancy indexing a[[1,3,5]] Array Yes Arbitrary order selection
np.where np.where(cond, x, y) Array Yes Ternary selection

(2) Boolean vs Fancy

Feature Boolean Mask Fancy Indexing
Syntax arr[arr > 0] arr[[1, 3, 5]]
Selection logic Condition-based Position-based
Result shape 1D (flattened) Same shape as index array
Speed Fast for large masks Fast for sparse selection

▶ Example: 2D fancy indexing with np.ix_ (Difficulty ⭐⭐)

PYTHON
import numpy as np

arr = np.arange(20).reshape(4, 5)
print("Original:\n", arr)

# Select specific rows and columns
rows = [0, 2, 3]
cols = [1, 3]
result = arr[np.ix_(rows, cols)]
print("Rows [0,2,3], Cols [1,3]:\n", result)

# Modify selected elements
arr[np.ix_([0, 1], [0, 4])] = -1
print("After modification:\n", arr)

Output:

TEXT 📖 Display only
Original:
 [[ 0  1  2  3  4]
 [ 5  6  7  8  9]
 [10 11 12 13 14]
 [15 16 17 18 19]]
Rows [0,2,3], Cols [1,3]:
 [[ 1  3]
 [11 13]
 [16 18]]
After modification:
 [[-1  1  2  3 -1]
 [-1  6  7  8 -1]
 [10 11 12 13 14]
 [15 16 17 18 19]]


❓ FAQ

Q Can I use a boolean mask to modify values?
A Yes! arr[arr > 0] = 0 sets all positive values to 0. This is an in-place modification. np.where(arr > 0, 0, arr) returns a new array instead.
Q What's the difference between arr[mask] and np.where(mask)?
A arr[mask] returns the values where mask is True. np.where(mask) returns the indices where mask is True. Use arr[mask] for the values, np.where(mask) when you need positions.
Q Can I use fancy indexing with 2D arrays?
A Yes. arr[[0,2], [1,3]] selects elements at (0,1) and (2,3). For independent row/column selection, use arr[np.ix_([0,2], [1,3])].
Q Do boolean masks always return 1D arrays?
A For 2D+ arrays, yes — the mask flattens the result to 1D. Use np.where(mask) to get the original shape indices.

📖 Summary



📝 Exercises

  1. Beginner (Difficulty ⭐): Create an array of 20 random integers between -10 and 10. Use a boolean mask to extract all positive values. Use np.where to replace all negative values with 0.

  2. Intermediate (Difficulty ⭐⭐): Create a 5x5 array of random integers 0-100. Use boolean masks to: (a) count values above 50, (b) replace values below 20 with 20, (c) extract the row and column indices of all values > 80 using np.where.

  3. Advanced (Difficulty ⭐⭐⭐): Create a 10x4 array of student scores (10 students, 4 subjects). Use fancy indexing to: (a) select students at positions [0,3,7] for all subjects, (b) select subjects at positions [1,3] for all students, (c) compute the average of the top 3 students by total score.

Web-Tutorial.com

Web-Tutorial Tech Team

A team of developers maintaining programming tutorials. Each tutorial is written and reviewed by developers with expertise in that field. We work to keep our content accurate and reliable — if you spot an issue, please let us know.

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏