Pandas: drop vs Boolean Filtering vs df.filter() — What Each One Actually Does
Quick answer
df.drop removes rows or columns by label — df.drop(index=[0,1]) or df.drop(columns=['a']). To keep rows by a CONDITION, use boolean masking: df[df['age'] > 30] (or df.query('age > 30')). df.filter() is a different tool: it selects labels by name with items=, like=, or regex= — it does NOT accept a boolean mask, so df.filter(df.a > 2) is wrong. Use drop to remove known labels, boolean masking to select by condition, and df.filter for name/pattern-based column/row selection.
Short answer: df.drop removes rows/columns by label. To keep rows by condition, use boolean masking (df[df.a > 2]), not df.filter. df.filter() is a third, different tool — it selects labels by name/regex (items=, like=, regex=) and does not accept a boolean mask.
These three get conflated constantly — including in tutorials that wrongly pass a boolean mask to df.filter(). Here's what each actually does.
drop — remove by label
import pandas as pd
df = pd.DataFrame({"A": [1, 2, 3, 4], "B": [5, 6, 7, 8], "C": [9, 10, 11, 12]})
df.drop(index=[1, 3]) # remove rows with labels 1 and 3
df.drop(columns=["B"]) # remove column Bdrop operates on labels you name. df.drop([1, 3]) defaults to axis=0 (rows); use columns= (or axis=1) for columns.
Boolean masking — keep by condition
To keep rows that satisfy a condition, index with a boolean Series:
df[df["A"] > 2] # keep rows where A > 2
df.loc[df["A"] > 2] # same, explicit
df.query("A > 2") # readable equivalentThis is what people usually mean by "filtering rows." Removing by condition is just the inverse mask (df[df["A"] <= 2]).
df.filter() — select labels by name/pattern
df.filter() is a different method: it selects rows or columns by their labels, not by a condition.
df.filter(items=["A", "C"]) # columns named A and C
df.filter(like="A", axis=1) # columns whose name contains "A"
df.filter(regex="^A|C$", axis=1) # columns matching a regex
df.filter(items=[0, 2], axis=0) # rows with index labels 0 and 2# ❌ WRONG — filter does not take a boolean mask
df.filter(df["A"] > 2)
# ✅ use boolean masking instead
df[df["A"] > 2]Which to use
| Goal | Use |
|---|---|
| Remove specific known rows/columns | df.drop(index=…) / df.drop(columns=…) |
| Keep rows meeting a condition | df[mask] / df.query(...) |
| Select columns/rows by name or pattern | df.filter(items=/like=/regex=) |
Related guides
Sources
Key takeaways
- •df.drop removes by LABEL: df.drop(index=[...]) for rows, df.drop(columns=[...]) for columns.
- •To keep rows by a CONDITION, use boolean masking: df[df['a'] > 2] — not df.filter.
- •df.filter() selects LABELS via items=/like=/regex=; it does NOT take a boolean mask.
- •df.filter(df['a'] > 2) is a bug — passing a mask to filter doesn't do condition-based row selection.
- •drop and boolean masking are opposites: drop names what to remove, masking names what to keep.
Frequently asked questions
What's the difference between drop and filtering in pandas?
df.drop removes rows or columns by their labels (df.drop(index=[1,3]) or df.drop(columns=['B'])). Boolean 'filtering' keeps rows that satisfy a condition (df[df['age'] > 30]). One names what to remove; the other names what to keep.
Does df.filter() filter rows by a condition?
No. df.filter() selects labels by name — items=['a','b'] for exact names, like='2023' for substrings, regex='e$' for patterns — along an axis. It does not take a boolean mask, so df.filter(df.a > 2) does not do condition-based row selection. Use df[df.a > 2] for that.
How do I remove rows by condition in pandas?
Keep the rows you want with a boolean mask — df = df[df['age'] >= 18] — which is the inverse of dropping. If you specifically want drop syntax, compute the labels to remove first: df.drop(index=df[df['age'] < 18].index).
Software Engineering Leader & Technical Author · Updated August 26, 2026