Boolean & Fancy Indexing
Boolean indexing selects array elements by a True/False condition, while fancy indexing selects them by an array of integer positions — together they let you filter and gather data without writing a single loop.
Learn Boolean & Fancy Indexing in our free NumPy course — a beginner-friendly interactive lesson with worked examples, a practice exercise and a quick…
Part of the free Numpy course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.
In this lesson you'll build boolean masks, filter with conditions, combine tests with & and | , overwrite values that match a rule, and grab arbitrary elements with integer index arrays.
A comparison like arr > 5 doesn't return a single answer — it compares every element and returns a boolean mask : an array of True / False the same shape as the original. That mask is the foundation of filtering, where each True marks a position you want to keep.
Expected output: [False True False True False True] and (6,) .
Put the mask inside the brackets — arr[arr > 5] — and NumPy returns only the elements where the mask is True . This is the single most common way to filter data in NumPy, and the result is always a 1D copy of the matching values.
To combine two tests, use & for "and" and | for "or". Wrap each comparison in parentheses — these operators bind tighter than > or < , so without parentheses NumPy reads the expression wrong and errors out.
A mask can sit on the left of an assignment too. arr[arr < 0] = 0 finds every negative value and replaces it with zero in place — a clean way to clip or clean data.
Expected output: [0 5 0 8 0 2] then [0 5 0 6 0 2] .
Fancy indexing uses a list or array of positions to pick elements in any order: arr[[0, 2, 4]] . It also works on 2D arrays — pass an array of row indices and an array of column indices to gather specific cells.
Expected output: [10 30 50] , [50 10 20] , and [2 7] .
Replace each ___ so the program filters, combines conditions, and uses fancy indexing.
Expected output: [ 9 11] , [4 6] , [ 2 11] . (Answers: > , & , 0 .)
❌ ValueError: The truth value of an array with more than one element is ambiguous
You combined conditions with and / or instead of the bitwise operators.
✅ Fix: use & and | — for example (arr > 2) & (arr < 9) .
❌ Wrong results when combining two conditions
You left out the parentheses, so & ran before the comparisons.
✅ Fix: wrap each test: (arr > 2) & (arr < 9) , never arr > 2 & arr < 9 .
A sensor reports some impossible negative readings. Clip them to zero, then count how many readings are above 50.
Lesson 7 complete — you can filter like a pro!
You now build boolean masks, filter with conditions, combine tests with & and | (always in parentheses), overwrite matching values, and gather arbitrary elements with fancy integer indexing.
🚀 Up next: Reshaping and Flattening — change an array's shape without touching its data.
Practice quiz
What does arr > 5 return for a NumPy array?
- A single True or False
- A boolean mask of True/False values
- The elements greater than 5
- The count of large elements
Answer: A boolean mask of True/False values. A comparison returns a boolean mask the same shape as the array.
For arr = [3, 8, 1, 10, 5, 7], what is arr[arr > 5]?
Boolean indexing keeps only the elements where the mask is True.
For arr = [3, 8, 1, 10, 5, 7], what is arr[arr % 2 == 0]?
The mask keeps the even numbers: 8 and 10.
How do you combine two array conditions for AND?
- (a) & (b)
- a and b
- a && b
- and(a, b)
Answer: (a) & (b). Use the bitwise & with each comparison in parentheses.
Why must each comparison be wrapped in parentheses with & and |?
- To make it run faster
- Because & binds tighter than the comparison operators
- Because NumPy requires tuples
- Parentheses are optional
Answer: Because & binds tighter than the comparison operators. & and | bind tighter than > or <, so parentheses force the comparisons first.
For arr = [3, 8, 1, 10, 5, 7], what is arr[(arr > 2) & (arr < 9)]?
Elements that are both > 2 and < 9 are 3, 8, 5, and 7.
What does arr[arr < 0] = 0 do?
- Returns a new copy of arr
- Raises an error
- Deletes negative values
- Replaces every negative value with 0 in place
Answer: Replaces every negative value with 0 in place. Assigning through a mask overwrites the matching positions in place.
For arr = [10, 20, 30, 40, 50], what is arr[[4, 0, 1]]?
Fancy indexing returns elements in the exact order of the index list.
For grid = [[1,2,3],[4,5,6],[7,8,9]], what is grid[[0, 2], [1, 0]]?
It pairs (0,1) and (2,0), giving grid[0,1]=2 and grid[2,0]=7.
Do boolean indexing and fancy indexing return a copy or a view?
- A view that shares memory
- It depends on dtype
- A new copy of the data
- Neither; they error
Answer: A new copy of the data. Both boolean and fancy indexing always return a new copy.