Python NumPy: How to Use numpy.where() with Multiple Conditions
The numpy.where() function is a powerful tool for selecting elements from arrays based on conditions - similar to a vectorized if-else statement. When you need to apply multiple conditions simultaneously, you combine them using logical operators. This guide explains how to use numpy.where() with AND, OR, and complex conditions across 1D and multi-dimensional arrays.
Understanding numpy.where() Syntax
numpy.where(condition, x, y)
| Parameter | Description |
|---|---|
condition | A boolean array or expression. Where True, select from x; where False, select from y |
x | Values to use where condition is True |
y | Values to use where condition is False |
When called with only the condition (no x or y), it returns the indices where the condition is True.
import numpy as np
arr = np.array([10, 25, 30, 45, 50])
# With x and y: returns values
result = np.where(arr > 30, arr, 0)
print("Values:", result)
# Without x and y: returns indices
indices = np.where(arr > 30)
print("Indices:", indices)
Output:
Values: [ 0 0 0 45 50]
Indices: (array([3, 4]),)
Combining Multiple Conditions
Using Logical AND (&)
The & operator requires both conditions to be True:
import numpy as np
arr = np.array([5, 12, 18, 25, 30, 42, 55, 60])
# Select elements greater than 10 AND less than 50
result = np.where((arr > 10) & (arr < 50), arr, 0)
print("AND result:", result)
Output:
AND result: [ 0 12 18 25 30 42 0 0]
Elements that satisfy both conditions keep their values; others are replaced with 0.
Using Logical OR (|)
The | operator requires at least one condition to be True:
import numpy as np
arr = np.array([5, 12, 18, 25, 30, 42, 55, 60])
# Select elements less than 10 OR greater than 50
result = np.where((arr < 10) | (arr > 50), arr, 0)
print("OR result:", result)
Output:
OR result: [ 5 0 0 0 0 0 55 60]
Elements satisfying either condition are kept.
Always wrap each condition in parentheses when using & and |. Due to Python's operator precedence, arr > 10 & arr < 50 is interpreted as arr > (10 & arr) < 50, which produces incorrect results.
# WRONG: missing parentheses
result = np.where(arr > 10 & arr < 50, arr, 0) # Unexpected behavior
# CORRECT: each condition in parentheses
result = np.where((arr > 10) & (arr < 50), arr, 0)
Practical Examples
Categorizing Values
Use numpy.where() to assign categories based on multiple conditions:
import numpy as np
scores = np.array([92, 45, 78, 61, 88, 33, 71, 55])
# Categorize: 'Pass' if score >= 60, 'Fail' otherwise
result = np.where(scores >= 60, 'Pass', 'Fail')
print("Pass/Fail:", result)
Output:
Pass/Fail: ['Pass' 'Fail' 'Pass' 'Pass' 'Pass' 'Fail' 'Pass' 'Fail']
Nested Conditions for Multiple Categories
For more than two categories, nest numpy.where() calls:
import numpy as np
scores = np.array([92, 45, 78, 61, 88, 33, 71, 55])
# Grade: A (>=80), B (>=60), C (<60)
grades = np.where(scores >= 80, 'A',
np.where(scores >= 60, 'B', 'C'))
print("Grades:", grades)
Output:
Grades: ['A' 'C' 'B' 'B' 'A' 'C' 'B' 'C']
Selecting from Two Arrays Based on Conditions
import numpy as np
arr1 = np.array([10, 20, 30, 40, 50])
arr2 = np.array([100, 200, 300, 400, 500])
# Take from arr1 where value is even AND > 15, otherwise take from arr2
result = np.where((arr1 % 2 == 0) & (arr1 > 15), arr1, arr2)
print("Result:", result)
Output:
Result: [100 20 30 40 50]
- Index 0:
10is even but not > 15 → takes100fromarr2 - Index 1:
20is even AND > 15 → takes20fromarr1 - Indices 2–4:
30,40,50are even AND > 15 → takes fromarr1
Multi-Dimensional Arrays
numpy.where() works with arrays of any shape:
import numpy as np
arr1 = np.array([[6, 13, 22, 7],
[7, 11, 16, 32]])
arr2 = np.array([[44, 20, 8, 35],
[98, 23, 42, 6]])
# Where arr1 is even AND arr2 is odd, take from arr1; otherwise from arr2
result = np.where((arr1 % 2 == 0) & (arr2 % 2 == 1), arr1, arr2)
print("arr1:\n", arr1)
print("arr2:\n", arr2)
print("Result:\n", result)
Output:
arr1:
[[ 6 13 22 7]
[ 7 11 16 32]]
arr2:
[[44 20 8 35]
[98 23 42 6]]
Result:
[[44 20 8 35]
[98 23 42 6]]
Only at position [0, 3] is arr1 even (22) while arr2 is odd (35) - wait, let's check: arr1[0,2]=22 (even) and arr2[0,2]=8 (even) → condition False → takes 8 from arr2. The actual output reflects the element-wise evaluation of both conditions.
Getting Indices Where Conditions Are Met
Call numpy.where() with only the condition to get the positions of matching elements:
import numpy as np
arr = np.array([15, 22, 8, 33, 45, 12, 50, 5])
# Find indices where value is between 10 and 40 (inclusive)
indices = np.where((arr >= 10) & (arr <= 40))
print("Indices:", indices[0])
print("Values at those indices:", arr[indices])
Output:
Indices: [0 1 3 5]
Values at those indices: [15 22 33 12]
Common Mistake: Using Python's and/or Instead of &/|
Python's and and or keywords do not work with NumPy arrays:
import numpy as np
arr = np.array([10, 20, 30, 40, 50])
# WRONG: Python's 'and' cannot evaluate element-wise on arrays
try:
result = np.where((arr > 15) and (arr < 45), arr, 0)
except ValueError as e:
print(f"Error: {e}")
Output:
Error: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
The correct approach
# CORRECT: use & for element-wise AND
result = np.where((arr > 15) & (arr < 45), arr, 0)
print("Result:", result)
Output:
Result: [ 0 20 30 40 0]
NumPy arrays require bitwise operators (&, |, ~) for element-wise logical operations. Python's and, or, not keywords attempt to evaluate the entire array as a single boolean, which is ambiguous and raises a ValueError.
Using numpy.select() for Many Conditions
When you have more than two or three conditions, numpy.select() is cleaner than nested where() calls:
import numpy as np
scores = np.array([92, 45, 78, 61, 88, 33, 71, 55])
conditions = [
scores >= 90,
(scores >= 80) & (scores < 90),
(scores >= 60) & (scores < 80),
scores < 60
]
choices = ['A', 'B', 'C', 'F']
grades = np.select(conditions, choices, default='Unknown')
print("Grades:", grades)
Output:
Grades: ['A' 'F' 'C' 'C' 'B' 'F' 'C' 'F']
Use np.select() when you have three or more conditions. It is more readable and maintainable than deeply nested np.where() calls.
Quick Reference
| Operation | Code |
|---|---|
| Single condition | np.where(arr > 5, arr, 0) |
| AND (both true) | np.where((arr > 5) & (arr < 20), arr, 0) |
| OR (either true) | np.where((arr < 5) | (arr > 20), arr, 0) |
| NOT (negate) | np.where(~(arr > 5), arr, 0) |
| Get indices only | np.where((arr > 5) & (arr < 20)) |
| Nested categories | np.where(c1, v1, np.where(c2, v2, v3)) |
| Many conditions | np.select([c1, c2, c3], [v1, v2, v3]) |
The numpy.where() function combined with & (AND) and | (OR) operators provides a fast, vectorized way to apply conditional logic across entire arrays without explicit loops - essential for efficient numerical computing in Python.