Boolean Masks
Combine Two Masks
Build a combined boolean mask from two conditions (lower and upper bound) and
use it to filter a list. The first loop produces the mask with and; the
second loop applies it with if m. The replay shows combined growing one
boolean at a time, then filtered collecting only the values that pass both
conditions.
By hand
With NumPy
(a > lo) & (a < hi) applies both comparisons elementwise and combines them
with bitwise AND. The result is a boolean array, passed directly to a[mask]
for boolean indexing.
naive.py
values = [1, 5, 3, 8, 4, 9]
lo = 2
hi = 6
combined = []
for v in values:
combined.append(v > lo and v < hi)
filtered = []
for v, m in zip(values, combined):
if m:
filtered.append(v)
print('RESULT:', (combined, filtered))
library.py
import numpy as np
values = [1, 5, 3, 8, 4, 9]
lo, hi = 2, 6
a = np.array(values)
mask = (a > lo) & (a < hi)
filtered = a[mask]
print('mask: shape:', mask.shape, 'dtype:', mask.dtype, 'values:', mask.tolist())
print('filtered: shape:', filtered.shape, 'dtype:', filtered.dtype, 'values:', filtered.tolist())
print('RESULT:', (mask.tolist(), filtered.tolist()))
mask: shape: (6,) dtype: bool values: [False, True, True, False, True, False]
filtered: shape: (3,) dtype: int64 values: [5, 3, 4]
RESULT: ([False, True, True, False, True, False], [5, 3, 4])
Implementation notes
- Use
&(bitwise AND) and|(bitwise OR) on NumPy boolean arrays, not Python'sand/or. Python'sand/oroperate on the truthiness of the whole array (raising an error for ambiguous multi-element arrays). - Parentheses are required:
(a > lo) & (a < hi). Without them,&binds tighter than>and<, soa > lo & a < hiis parsed asa > (lo & a) < hi— a comparison chain, not two masked conditions. - The combined mask
(a > lo) & (a < hi)is equivalent toa[a > k]fromfilter-with-maskgeneralized to a range. - Shape, dtype, and values are shown explicitly here because
ndarray.__repr__output varies with NumPy version and print options.