🐼 Section 2 · Pandas 🟡 Intermediate MODULE 10

Filtering, Sorting & Selecting Data

⏱️ 26 min read
📖 Theory + Code
🧩 5 Quiz Questions
🏗️ 1 Challenge
Your progress in Section 250%
🎯 What you'll learn: Boolean filtering with df[df['col'] > x], combining multiple conditions with & and |, sorting rows with .sort_values() and .sort_index(), writing readable filters with .query(), selecting multiple columns at once, and matching against a list of values with .isin().

Boolean Filtering

This is the single most-used Pandas pattern. A comparison on a column produces a Series of True/False values — a boolean mask — and passing that mask back into df[...] keeps only the rows where it's True. It's the exact same idea as NumPy boolean masking from Section 1, applied to a whole table instead of one array.

boolean_filtering.py
PYTHON
import pandas as pd

df = pd.DataFrame({
    "product": ["Laptop", "Mouse", "Monitor", "Keyboard", "Webcam"],
    "region": ["North", "South", "North", "East", "South"],
    "sales": [1200, 45, 890, 65, 150],
})

# The mask itself — a Series of True/False
mask = df["sales"] > 100
print(mask)
# 0     True
# 1    False
# 2     True
# 3    False
# 4     True

# Applying the mask — only rows where it's True survive
high_sales = df[df["sales"] > 100]
print(high_sales)
#    product region  sales
# 0   Laptop  North   1200
# 2  Monitor  North    890
# 4   Webcam  South    150
Same idea as NumPy's arr[arr > 10]
If arr[arr > 10] from Section 1 made sense, df[df['sales'] > 100] is the same mechanism — a boolean array/Series selecting matching positions — just applied to an entire table's rows instead of a flat array.

Combining Multiple Conditions

To filter on more than one condition at once, use & (and) and | (or) — never Python's and/or, which don't work element-wise on a Series. Every individual condition needs its own parentheses.

combining_conditions.py
PYTHON
# AND — both conditions must be True
result = df[(df["sales"] > 100) & (df["region"] == "North")]

# OR — either condition can be True
result = df[(df["region"] == "South") | (df["region"] == "East")]

# NOT — negate a condition with ~
result = df[~(df["region"] == "North")]   # everything NOT in the North
⚠️
The parentheses are not optional
Because & binds more tightly than comparison operators in Python, df["sales"] > 100 & df["region"] == "North" without parentheses either raises an error or silently evaluates in the wrong order. Always wrap each individual comparison: (df["sales"] > 100) & (df["region"] == "North").

Sorting: sort_values() and sort_index()

.sort_values() reorders rows by one or more column's values. .sort_index() reorders rows back to index order — useful after a filter or groupby has scrambled or subset the index.

sorting.py
PYTHON
# Sort by one column, ascending (the default)
df.sort_values("sales")

# Sort by one column, descending
df.sort_values("sales", ascending=False)

# Sort by multiple columns — region first, then sales within each region
df.sort_values(["region", "sales"], ascending=[True, False])

# Sort back into index order (e.g. after a filter re-shuffled row order)
df.sort_index()
📝
sort_values() also returns a new DataFrame
Like .dropna() in Lesson 9, .sort_values() doesn't modify df in place by default — assign the result to a variable (or pass inplace=True) if you want to keep the sorted order.

The .query() Method

.query() lets you write a filter condition as a plain string, using column names directly instead of repeating df[...] everywhere. Many people find it more readable once there's more than one condition.

query_method.py
PYTHON
# Equivalent to df[df["sales"] > 100]
df.query("sales > 100")

# Combine conditions with plain "and" / "or" inside the string
df.query("sales > 100 and region == 'North'")

# Reference a Python variable inside the string with an @ prefix
threshold = 100
df.query("sales > @threshold")
Two ways to filter, same result
df.query("sales > 100 and region == 'North'") and df[(df["sales"] > 100) & (df["region"] == "North")] do exactly the same thing. Use whichever reads more clearly for the filter you're writing — .query() tends to win as the number of conditions grows.

Selecting Multiple Columns & .isin()

Two more everyday tools: pulling out several columns at once, and checking whether a column's value belongs to a known list.

columns_and_isin.py
PYTHON
# Select multiple columns — note the DOUBLE brackets
subset = df[["product", "sales"]]

# .isin() — keep rows where the column's value is in a given list
target_regions = ["North", "East"]
result = df[df["region"].isin(target_regions)]

# Negate it with ~ to exclude those values instead
result = df[~df["region"].isin(target_regions)]   # everything EXCEPT North and East
⚠️
Single vs. double brackets
df["sales"] (single brackets, one column name) returns a Series. df[["sales"]] or df[["product", "sales"]] (double brackets, a list of names) returns a DataFrame — even with just one column inside. Mixing these up is a very common source of "why doesn't this method exist on my result" errors.

Lesson Summary

Let's recap everything you learned in this lesson:

Boolean filteringdf[df['col'] > x] — keeps rows where a condition is True.
Combine conditions with &/|/~, each condition wrapped in parentheses — never and/or.
.sort_values() orders by value(s); .sort_index() restores index order.
.query() writes filters as readable strings, with @variable for Python values.
Double brackets df[[...]] select multiple columns; .isin(list) filters against a set of values.
🧩 Knowledge Check — Lesson 10
Answer all 5 questions to test your understanding. Instant feedback on every answer.
1. What does df[df['sales'] > 100] return?
2. Which operator combines two conditions on a DataFrame with "and" logic?
3. What does df.sort_values("sales", ascending=False) do?
4. Which is equivalent to df[(df["sales"] > 100) & (df["region"] == "North")]?
5. What's the difference between df["sales"] and df[["sales"]]?
💪
Coding Challenge — Lesson 10
Apply what you learned · Intermediate Level

Filter and sort a small sales DataFrame using several techniques from this lesson.

Challenge: Top Regional Performers 🏆

Using the df from Section 1 (product, region, sales), write code that: (1) filters to rows where sales > 100 AND region is either "North" or "South" (use .isin() for the region check), (2) sorts the result by sales descending, and (3) selects only the product and sales columns from the final result. Then rewrite step 1's filter using .query() instead, and confirm it produces the same rows.

Rules: Combine the sales condition and the isin() condition with &, with each part in parentheses.
💡 Show hints if you're stuck
  • Combine: df[(df["sales"] > 100) & (df["region"].isin(["North", "South"]))]
  • Sort after filtering: .sort_values("sales", ascending=False)
  • query() version: df.query("sales > 100 and region in ['North', 'South']")
Finished this lesson?
Mark it complete to track your progress.
🎉

Lesson 10 Complete!

You can filter, sort, and select exactly the data you need. Next up: GroupBy, aggregation, and pivot tables — turning raw rows into summarized answers.

Module 10 of 13 Section 2 — Pandas: Data Analysis Powerhouse