Boolean indexing filters pandas DataFrame rows with a True/False condition, called a Boolean mask. For instance, df[df["Salary"] > 90000] selects rows where the salary exceeds 90,000. Combine comparisons with &, | and ~, surrounding each comparison with parentheses. This guide includes tested pandas examples and avoids older, removed .ix syntax.
Create a DataFrame for the examples
import pandas as pd
employees = pd.DataFrame({
"ID": [90, 40, 80, 98],
"Name": ["Joe", "Parth", "Sunny", "Lauren"],
"Dept": ["Manager", "Dev", "Admin", "Manager"],
"Salary": [90000, 65000, 50000, 92000]
})
These examples run locally without a downloaded CSV file. They were checked with pandas 2.2.3 and compared with the official pandas Boolean indexing guidance. If you are new to pandas, see the existing PickupBrain DataFrame introduction.
Filter rows with a single condition
mask = employees["Salary"] > 90000
print(mask.tolist()) # [False, False, False, True]
result = employees[mask]
print(result["Name"].tolist()) # ["Lauren"]
A Boolean Series is created by comparing each salary with 90,000. The last row remains because 92,000 is greater than the threshold. The salary equal to 90,000 is excluded: use >= if that should be included.
The original video is retained. It may show older pandas interfaces; use the updated examples in this article for new code.
Use .loc to filter rows and choose columns
result = employees.loc[
employees["Salary"] > 90000,
["Name", "Salary"]
]
print(result["Name"].tolist()) # ["Lauren"]
The .loc[rows, columns] syntax is label-based. Passing a Boolean mask in the row position filters rows, and supplying column names returns only the required fields.
Combine conditions using AND (&)
manager_and_high = (
(employees["Dept"] == "Manager") &
(employees["Salary"] >= 90000)
)
print(employees.loc[manager_and_high, "Name"].tolist())
# ["Joe", "Lauren"]
Use & for an elementwise AND operation, not Python’s and. The latter attempts to evaluate a whole Series as one truth value and raises an error. Parenthesize every comparison because Python operator precedence can otherwise change the meaning.
Use OR (|), NOT (~) and isin()
dev_or_admin = (employees["Dept"] == "Dev") | (employees["Dept"] == "Admin")
print(employees.loc[dev_or_admin, "Name"].tolist())
# ["Parth", "Sunny"]
not_manager = ~(employees["Dept"] == "Manager")
print(employees.loc[not_manager, "Name"].tolist())
# ["Parth", "Sunny"]
listed = employees["Dept"].isin(["Dev", "Admin"])
print(employees.loc[listed, "Name"].tolist())
# ["Parth", "Sunny"]
The isin() method is convenient when matching a list of allowed values. For text matching instead of exact equality, you can use employees["Name"].str.contains("a", case=False, na=False).
Filter by row index value
by_id = employees.set_index("ID")
result = by_id.loc[by_id.index > 80, "Name"]
print(result.tolist()) # ["Joe", "Lauren"]
Here, the index values are employee IDs, and the Boolean mask selects labels greater than 80. Important distinction: .loc[True] looks for an index label called True; it does not mean “select all True rows.” Build a Boolean mask explicitly. .iloc uses row positions, whereas the old .ix indexer was removed from pandas.
Nullable Boolean values (pd.NA)
nullable = pd.array([True, False, pd.NA, True], dtype="boolean")
print(employees[nullable]["Name"].tolist())
# ["Joe", "Lauren"]
# Include unknown rows only when that policy makes sense:
print(employees[nullable.fillna(True)]["Name"].tolist())
# ["Joe", "Sunny", "Lauren"]
A nullable Boolean mask treats pd.NA as False when selecting rows by default. You can explicitly change this with fillna(True), but only if treating missing/unknown as included is correct for your application.
Filtering rows vs where(): not the same
filtered = employees[employees["Salary"] > 90000]
print(len(filtered)) # 1
masked = employees.where(employees["Salary"] > 90000)
print(len(masked)) # 4, other rows become missing
employees[mask] selects a subset of rows. employees.where(mask) preserves the DataFrame shape, replacing values in nonmatching rows with missing values. This difference matters for downstream calculations and data-quality checks.
Common errors and troubleshooting
- “Truth value of a Series is ambiguous”: use parentheses and elementwise
&/|, rather thanand/or. - Boolean Series is unalignable: create the mask from the same DataFrame you are filtering or explicitly align index labels.
- Missing results: verify capitalization, missing values, and the difference between strict
>and inclusive>=. .ixnot found: use.locfor labels and.ilocfor positions.- Nullable data: choose intentionally whether unknown mask values are excluded or included.
- Unexpected rows: print
mask.tolist()or inspect the mask alongside index labels to debug the condition.
Summary
Boolean masks make pandas filtering readable and reproducible. Use comparisons to create masks, .loc to select rows and columns, correct operators with parentheses for multiple conditions, and an explicit missing-data policy. Also see our indexing guide and head() and tail() examples.
You may also like

C P Gupta is a YouTuber and Blogger. He is expert in Microsoft Word, Excel and PowerPoint. His YouTube channel @pickupbrain is very popular and has crossed 9.9 Million Views.