Skip to main content
v2026.11,858 entries · CC-BY 4.0

NumPy where: Syntax, Multiple Conditions and np.select

How np.where(condition, x, y) works, how to combine multiple conditions, and when np.select or nonzero is the better NumPy tool.

Written and maintained by CASRAI Editorial Board

Last updated

numpy.where picks values from one of two arrays depending on a True/False condition, element by element. Called with three arguments, np.where(condition, x, y) returns a new array with elements from x where condition is True and from y elsewhere. Called with only a condition, it returns the positions where the condition is True. For three or more outcomes, np.select is the cleaner tool, and for plain filtering the NumPy documentation prefers nonzero or boolean indexing.

What np.where is used for in research

In research data work, np.where is the vectorised “if/else”: it recodes a variable in one step, with no loop. Typical uses are replacing a sentinel code with np.nan, capping or flagging values above a threshold, and creating a binary indicator from a continuous measure. It sits in the recoding stage of a data cleaning workflow and is one of the basic operations behind data wrangling for research.

The signature in the NumPy manual (v2.5) is numpy.where(condition, [x, y, ]/). The arguments are positional-only, so write them without keywords. The manual describes condition as a boolean array_like and states that “x, y and condition need to be broadcastable to some shape.”

Install or access

The NumPy installation page states that the only prerequisite is Python itself. Any one of these official commands installs it:

  • pip install numpy
  • conda install numpy
  • uv pip install numpy
  • pixi add numpy

If you work in an isolated environment, create it first with python -m venv my-env, then activate it with source my-env/bin/activate (macOS and Linux) or my-env\Scripts\activate (Windows). If you prefer a notebook interface, see Anaconda for Jupyter Notebook. Check the install with:

import numpy as np
print(np.__version__)

Step-by-step: using np.where

1. Replace values with np.where(condition, x, y)

This is the example in the NumPy manual. Values below 5 are kept and the rest are multiplied by 10:

import numpy as np
a = np.arange(10)
np.where(a < 5, a, 10*a)
# array([ 0,  1,  2,  3,  4, 50, 60, 70, 80, 90])

A scalar works as x or y because of broadcasting. The manual’s 2-D example replaces every element of 4 or more with -1:

a = np.array([[0, 1, 2], [0, 2, 4], [0, 3, 6]])
np.where(a < 4, a, -1)
# array([[ 0,  1,  2],
#        [ 0,  2, -1],
#        [ 0,  3, -1]])

A research-style use is converting a sentinel code to a missing value. The array below is illustrative, with -999.0 standing in for “not recorded”:

d = np.array([4.2, -999.0, 5.1, -999.0])
np.where(d == -999.0, np.nan, d)
# array([4.2, nan, 5.1, nan])

2. Use np.where with multiple conditions

Python’s and and or do not work on arrays, so combine conditions with the array operators. The numpy.logical_and page says that “the & operator can be used as a shorthand for np.logical_and on boolean ndarrays”, and the numpy.logical_or page says the same of | and np.logical_or. Put each comparison in its own parentheses, because in Python the & and | operators bind more tightly than comparisons such as > (see the operator precedence table in the Python language reference):

v = np.arange(5)
np.where((v > 1) & (v < 4), 1, 0)
# array([0, 0, 1, 1, 0])
np.where((v < 1) | (v > 3), 'edge', 'mid')
# array(['edge', 'mid', 'mid', 'mid', 'edge'], dtype='<U4')

The manual’s own logical_and example, np.logical_and(x > 1, x < 4) with x = np.arange(5), returns array([False, False, True, True, False]). That boolean array is exactly what np.where receives as its condition, so np.where(np.logical_and(v > 1, v < 4), 1, 0) gives the same result as the & version above. Note that bitwise_and is a separate function.

3. Handle three or more outcomes: np.select

Nesting np.where calls works, but np.select(condlist, choicelist, default=0) states the cases side by side. The manual specifies three rules: when multiple conditions are satisfied, “the first one encountered in condlist is used”; choicelist “has to be of the same length as condlist“; and default is “the element inserted in output when all conditions evaluate to False.” The manual’s example:

x = np.arange(6)
np.select([x < 3, x > 3], [-x, x**2], 42)
# array([ 0, -1, -2, 42, 16, 25])

The nested equivalent, np.where(x < 3, -x, np.where(x > 3, x**2, 42)), returns the same array. The np.select form keeps the order of precedence visible, which matters when cases overlap.

4. Get positions with np.where(condition) only

With one argument, the manual says the function “is a shorthand for np.asarray(condition).nonzero(). Using nonzero directly should be preferred, as it behaves correctly for subclasses.” The result is a tuple of arrays, one per dimension. With the numpy.nonzero page’s array:

a = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
np.nonzero(a > 3)
# (array([1, 1, 1, 2, 2, 2]), array([0, 1, 2, 0, 1, 2]))

The first array holds row indices and the second holds column indices. If you only want the values, the nonzero page recommends boolean indexing, a[a > 3], instead.

Which function to choose

Situation Function What the NumPy manual says
Two outcomes per element np.where(cond, x, y) Elements from x where True, from y elsewhere
Three or more outcomes np.select(condlist, choicelist, default) First matching condition in condlist is used; default fills the rest
Positions of True values np.nonzero(cond) Preferred over one-argument np.where; returns a tuple of arrays, one per dimension
Only the matching values a[a > 3] Recommended on the nonzero page for plain filtering

Output and how to read it

The three-argument form returns an ndarray of the broadcast shape, with no change to the inputs. A mental model from the manual is the 1-D list comprehension [xv if c else yv for c, xv, yv in zip(condition, x, y)]: for each position, take x if the condition is True there, else y.

Broadcasting extends this to arrays of different shapes. The manual’s example uses x, y = np.ogrid[:3, :4], a column of 3 and a row of 4:

np.where(x < y, x, 10 + y)
# array([[10,  0,  0,  0],
#        [10, 11,  1,  1],
#        [10, 11, 12,  2]])

Each cell compares its row value x with its column value y. Where x < y it shows x, and otherwise 10 + y. With a boolean condition and explicit arrays, np.where([[True, False], [True, True]], [[1, 2], [3, 4]], [[9, 8], [7, 6]]) returns array([[1, 8], [3, 4]]).

Troubleshooting

  • ImportError “Importing the numpy c-extensions failed”. The NumPy install page links its ImportError troubleshooting guide for this message.
  • You get a tuple of arrays instead of values. That is the one-argument form returning indices. Pass x and y for values, or use a[condition].
  • Multiple conditions do not combine as expected. Use & and | (or np.logical_and and np.logical_or) with each comparison in parentheses, not and and or.
  • Shapes do not match. x, y and condition must be broadcastable to a common shape.

For another NumPy function used to build arrays to test, see NumPy linspace. If the array holds column data, renaming columns in a pandas DataFrame is a common next step.

Free alternatives

All of these ship with NumPy, which is free to install from the commands above:

Function Use it when Source
numpy.where Choosing between two arrays on a condition NumPy manual
numpy.select Several conditions with an explicit default NumPy manual
numpy.nonzero You need indices of True values NumPy manual
numpy.logical_and Combining conditions without the & operator NumPy manual

FAQ

How does Python numpy where work?

After import numpy as np, np.where(condition, x, y) returns an array with elements from x where the condition is True and from y elsewhere. With only condition, it returns the indices of True elements as a tuple of arrays.

How do I use numpy where with multiple conditions?

Combine boolean arrays with & (and) or | (or), wrapping each comparison in parentheses, for example np.where((v > 1) & (v < 4), 1, 0). For three or more distinct outcomes, use np.select, where the first matching condition wins.

Should I use np.where or np.nonzero to find indices?

The NumPy manual says that using nonzero directly should be preferred, because it behaves correctly for subclasses.

Sources

Follow CASRAI

Research-administration guidance, standards updates and independent tool reviews.

Ask CASRAI · free to try

Ask about NumPy where: Syntax, Multiple Conditions and np.select

Ask your first 2 questions free below. Subscribers get 150 a day for $29 a month.

An AI assistant specialized in research administration. It cites the sources behind every answer, labels web answers and says when it can't answer.

Answers draw on CASRAI's guides and dictionary plus the federal and funder documents we index: Federal Register, Grants.gov, Regulations.gov and UKRI.

Works on this site and inside Claude, Cursor and the AI tools you already use.

Everything CASRAI publishes — this page, the dictionary, the guides and the news — stays free to read, with no account and no card.

Referenced across the research world

University of Cambridge logoColumbia University logoCrossref logoUniversity of Edinburgh logoHarvard University logoUniversity of Oxford logoPrinceton University logoStanford School of Medicine logoUniversity College London logoORCID logoUniversity of Cambridge logoColumbia University logoCrossref logoUniversity of Edinburgh logoHarvard University logoUniversity of Oxford logoPrinceton University logoStanford School of Medicine logoUniversity College London logoORCID logo
  • University of Cambridge logo
  • Columbia University logo
  • Crossref logo
  • University of Edinburgh logo
  • Harvard University logo
  • University of Oxford logo
  • Princeton University logo
  • Stanford School of Medicine logo
  • University College London logo
  • ORCID logo

View CASRAI adoption →

Ask CASRAI · Regulatory Radar

Research-admin question? Get an answer that links its sources.

An AI assistant specialized in research administration. Every answer links its sources to check before you act. 2 questions free, no account. $29/month after.

  • Answers draw on CASRAI's guides and dictionary plus the federal and funder documents we index: Federal Register, Grants.gov, Regulations.gov and UKRI.
  • Every answer numbers its sources and links each one, so you can check the source yourself.