Filtering, Sorting & Selecting Data
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.
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
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.
# 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
& 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.
# 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()
.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.
# 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")
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.
# 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
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:
df[df['col'] > x] — keeps rows where a condition is True.&/|/~, 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.df[[...]] select multiple columns; .isin(list) filters against a set of values.df[df['sales'] > 100] return?df.sort_values("sales", ascending=False) do?df[(df["sales"] > 100) & (df["region"] == "North")]?df["sales"] and df[["sales"]]?Filter and sort a small sales DataFrame using several techniques from this lesson.
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']")