dataframe
filtering
pandas
python
duplicates

Filter dataframe rows if value in column is in a set list of values

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Filtering a pandas DataFrame by checking whether a column value belongs to a set of allowed values is a very common operation. The standard tool for this is Series.isin, which creates a Boolean mask you can use for row selection, negation, or method chaining.

Use isin for Membership Filtering

The basic pattern is:

python
1import pandas as pd
2
3df = pd.DataFrame(
4    {
5        "name": ["Ana", "Ben", "Cara", "Drew"],
6        "team": ["red", "blue", "red", "green"],
7        "score": [10, 12, 9, 14],
8    }
9)
10
11allowed = {"red", "green"}
12
13filtered = df[df["team"].isin(allowed)]
14print(filtered)

isin returns a Boolean series. Rows where the column value belongs to the set are True, and those rows are kept when the mask is applied to the DataFrame.

Using a Python set is a good habit for readability when the idea is membership testing. Pandas accepts lists, tuples, sets, and other iterables here.

Negate the Filter When You Want the Opposite

If you want all rows whose value is not in the given collection, negate the mask with ~.

python
excluded = df[~df["team"].isin({"red", "green"})]
print(excluded)

This pattern is clearer than building a chain of multiple != comparisons, especially once the allowed or blocked value set becomes larger.

Filter in a Method Chain

isin works well inside larger pandas pipelines:

python
1result = (
2    df[df["team"].isin({"red", "green"})]
3    .sort_values("score", ascending=False)
4    .reset_index(drop=True)
5)
6
7print(result)

This makes it easy to keep filtering, sorting, grouping, and aggregation in one readable flow.

Be Deliberate About Missing Values

NaN handling matters. isin returns False for missing values unless the missing value itself is represented in a matching way.

python
1import pandas as pd
2
3df = pd.DataFrame({"team": ["red", None, "blue"]})
4mask = df["team"].isin({"red", "green"})
5print(mask)

If missing values should be preserved, combine conditions explicitly:

python
mask = df["team"].isin({"red", "green"}) | df["team"].isna()
print(df[mask])

That makes your intent clear instead of letting null-handling become an accidental side effect.

Avoid Slow Manual Loops

Beginners sometimes write row-by-row loops such as:

python
1rows = []
2for _, row in df.iterrows():
3    if row["team"] in {"red", "green"}:
4        rows.append(row)

This is slower and less idiomatic than using pandas vectorized operations. isin is built for exactly this kind of column-wide membership test.

If you need case-insensitive matching on strings, normalize the column first:

python
mask = df["team"].str.lower().isin({"red", "green"})
print(df[mask])

That is usually cleaner than mixing string normalization logic into a manual loop or apply call.

Selecting Specific Columns After Filtering

Membership filtering often appears as the first step in a larger analysis. After applying the mask, it is common to keep only the columns you need:

python
result = df.loc[df["team"].isin({"red", "green"}), ["name", "score"]]
print(result)

Using .loc makes the row filter and the column selection explicit in one expression, which is often easier to maintain in analysis notebooks and production data pipelines.

Common Pitfalls

  • Comparing one column against many values with repeated == checks instead of using isin.
  • Forgetting to negate the mask with ~ when the goal is exclusion rather than inclusion.
  • Ignoring missing values and then being surprised when NaN rows disappear.
  • Using Python loops or iterrows() for something pandas already vectorizes well.
  • Mixing string case inconsistently and then assuming isin is broken when the real issue is data normalization.

Summary

  • Use df[column].isin(values) to build a membership filter in pandas.
  • Apply the Boolean mask to keep only matching rows.
  • Use ~ to invert the filter when you want rows not in the list or set.
  • Handle missing values explicitly if they should remain in the result.
  • Prefer isin over manual loops because it is clearer, faster, and more idiomatic.

Course illustration
Course illustration

All Rights Reserved.