Combine pandas row conditions with the bitwise operators & (AND), | (OR) and ~ (NOT), and put parentheses around each comparison. For example, df[(df["A"] > 2) & (df["B"] < 3)] keeps rows where both conditions are true.
Combine conditions with boolean indexing
Each comparison produces a Boolean Series: a mask with one true-or-false result for each row. Combine masks with pandas’ element-wise operators, then pass the result to the DataFrame to select matching rows.
As an Amazon Associate I earn from qualifying purchases.
both = (df["A"] > 2) & (df["B"] < 3)
filtered = df[both]
For rows that match either condition, use |:
filtered = df[(df["A"] < 0) | (df["B"] > 10)]
To keep rows that do not meet a condition, invert its mask with ~:
Quick wins for a faster PC:
Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Repair Windows errors before they cause bigger problemsFix Now →filtered = df[~(df["A"] > 2)]
Use &, | and ~ rather than Python’s and, or and not for Series masks. Python’s logical operators do not combine each row’s truth value element by element. The pandas indexing and selecting data guide documents boolean indexing and these operators.
#1 Best Overall
Why parentheses matter
Parenthesize each comparison before combining it. Without parentheses, Python’s operator precedence can group an expression such as df["A"] > 2 & df["B"] < 3 in a way that does not mean “A is greater than 2 and B is less than 3.” Write (df["A"] > 2) & (df["B"] < 3) instead.
Choose boolean indexing, .loc or .query()
These forms select rows in different ways. Choose based on whether you want to reuse a mask, select columns at the same time, or express the conditions in a compact string.
Rank #2
| Form | Example | Useful when |
|---|---|---|
| Boolean indexing | df[mask] |
The mask is already stored in a variable, or you want the row-selection logic visible and reusable. |
.loc |
df.loc[mask, ["A", "B"]] |
You want to apply a row mask and choose columns in the same operation. |
.query() |
df.query("A > 2 and B < 3") |
The conditions are naturally expressed as a compact, column-oriented expression. |
The pandas indexing guide covers boolean indexing, .loc and .query(). It does not establish that one form is always faster, so choose for clarity and fit rather than assuming a speed advantage.
Use .loc with an index-aligned mask
.loc accepts a Boolean Series and applies it with label-aware indexing. This is useful when the mask is associated with the DataFrame’s index:
mask = (df["A"] > 2) & (df["B"] < 3)
selected = df.loc[mask, ["A", "B"]]
.iloc does not accept a Boolean Series as its indexer; it accepts a boolean array. When you have a Series mask aligned to the DataFrame index, prefer .loc.
Use .query() for trusted expressions
.query() lets you write the conditions in a string, using and and or in the expression:
filtered = df.query("A > 2 and B < 3")
Do not pass untrusted user input directly as a query expression: the pandas.DataFrame.query API reference warns that query expressions can run arbitrary code. If a condition comes from user input, construct and validate the filtering logic safely rather than treating the input as trusted expression text.
Decide what missing values should do
A nullable Boolean mask can contain pd.NA, meaning the condition’s result is unknown for that row. When such a mask is used for indexing, pandas treats missing Boolean entries as False, so those rows are not selected by that mask. The nullable Boolean data type guide describes this behavior.
Best Value
If your rule is to keep rows where the condition is unknown, fill missing mask values with True before indexing. Use False instead when unknown rows should be excluded explicitly:
# Exclude rows whose condition is unknown
filtered = df[mask.fillna(False)]
# Keep rows whose condition is unknown
filtered = df[mask.fillna(True)]
Choose the fill value according to the meaning of the filter; treating unknown as true or false changes which rows are returned.
Filtering rows is different from assigning values
Boolean indexing removes nonmatching rows from the result. If instead you want to assign a value based on several conditions, use numpy.select(conditions, choices, default=...) to choose values for rows. That is conditional value selection, not DataFrame row filtering; pandas documents it alongside its selection tools in the indexing guide.
Recommended Free Tools
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




