Pandasdrill

Selecting and filtering Updated November 2026

where, mask and np.where

np.where(cond, a, b) returns a for rows where cond is True and b elsewhere, the vectorized if-else used to build conditional columns. Series.where(cond, other) keeps the original value where cond is True and replaces the rest; Series.mask does the opposite.

Syntax

np.where(cond, x, y)   |   np.select([c1, c2], [v1, v2], default)   |   Series.where(cond, other=nan)   |   Series.mask(cond, other=nan)
PartWhat it is
condBoolean Series or array
x / ynp.where: values (scalars or arrays) used where cond is True / False
otherwhere/mask: replacement value, default NaN

Examples

import pandas as pd
import numpy as np

df = pd.DataFrame({"name": ["Ana", "Ben", "Cara"], "score": [82, 45, 67]})
df["result"] = np.where(df["score"] >= 60, "pass", "fail")
df

Result: name score result 0 Ana 82 pass 1 Ben 45 fail 2 Cara 67 pass

conds = [df["score"] >= 80, df["score"] >= 60]
df["grade"] = np.select(conds, ["A", "B"], default="C")
df["grade"].tolist()

Result: ['A', 'C', 'B']

np.select tests the conditions in order, like if/elif/else.

df["score"].where(df["score"] >= 60)

Result: 0 82.0 1 NaN 2 67.0 Name: score, dtype: float64

where keeps passing values and blanks the rest.

Common mistakes

  • Series.where seems backwards: it keeps values where the condition is True, unlike SQL WHERE filtering; to replace matching values use mask.
  • np.where returns a numpy array, so the result has no index; assign it to a column directly rather than aligning it.
  • Integers turn into floats after where: NaN was introduced; pass other=0 or another integer.

Practice where, mask and np.where

These drills check your answer on live data, free, no account needed.

  • Classify with applyWrite a function that labels an order "small" when qty is under 5, "medium" from 5 to 19, and "large" at 20 or more. Apply it to the `qty` column and return the labels as a Series.
  • Filter with a boolean maskReturn every employee in `emp` whose salary is strictly greater than 80,000. Keep all columns and the original row labels.

Questions

How do I write if-elif-else for a column?

np.select with a list of conditions and matching values, or pd.cut for numeric ranges. apply with a function works but is slower.

DataFrame.where vs filtering with df[cond]?

df[cond] drops rows; df.where(cond) keeps the shape and sets failing cells to NaN.

Related

  • applyHow to use apply in pandas on a Series or DataFrame, with axis=1 for row-wise logic, lambdas, returning several columns, and why vectorized code is faster.
  • Filter rowsHow to filter rows in a pandas DataFrame by one or several conditions using boolean masks, with the & | ~ operators, parentheses, isin, between and query.
  • cut and qcutHow to bin numeric data in pandas: pd.cut for fixed ranges with labels like age bands, pd.qcut for equal-sized quantile groups, right-closed edges and labels.
  • fillnaHow to fill NaN values in pandas with fillna: a constant, a different value per column, the column mean or median, forward and backward fill, and by group.

Previous: unique and nuniqueNext: idxmax and idxmin