Pandas DataFrame
Python
Programming
Data Filtering
Substring Criteria

Filter pandas DataFrame by substring criteria

ML System Design practice on Codemia

Design recommenders, ranking systems and training pipelines the way ML interviews actually ask for them, with worked solutions.

Practice ML system design

Introduction

In pandas, substring filtering is usually done with the str accessor, most often str.contains. The important details are not the basic syntax but the edge cases: missing values, case sensitivity, whether the pattern should be treated as a regular expression, and whether you want contains, starts-with, or ends-with behavior.

Basic Substring Filtering

For “keep rows where a column contains some text,” use str.contains.

python
1import pandas as pd
2
3
4df = pd.DataFrame(
5    {
6        "name": ["Alice Blue", "Bob Redford", "Charlie Grey", None],
7        "city": ["Toronto", "Boston", "Calgary", "Berlin"],
8    }
9)
10
11filtered = df[df["name"].str.contains("Red", na=False)]
12print(filtered)

na=False matters. Without it, missing values can propagate NaN into the boolean mask and make filtering less predictable.

Case Sensitivity and Literal Matching

By default, str.contains is case-sensitive and treats the pattern as a regular expression.

That means these two questions are different:

  • “does the text contain the literal string C++
  • “does the text match this regex pattern”

For a literal search, disable regex mode:

python
filtered = df[df["name"].str.contains("red", case=False, regex=False, na=False)]
print(filtered)

This is often the safest default when you are searching for ordinary user-provided text.

startswith and endswith

If the rule is positional rather than “contains anywhere,” use the dedicated helpers.

python
1starts = df[df["name"].str.startswith("Alice", na=False)]
2ends = df[df["name"].str.endswith("Grey", na=False)]
3
4print(starts)
5print(ends)

These methods are clearer than writing equivalent regular expressions by hand.

Filter Multiple Columns

Sometimes the substring can appear in more than one column. In that case, build a combined boolean mask.

python
mask = (
    df["name"].str.contains("o", case=False, na=False)
| df["city"].str.contains("o", case=False, na=False) ) print(df[mask]) ``` Using masks explicitly keeps the logic readable when multiple text conditions are involved. It is also a good habit to normalize the column before matching when data quality is uneven. Converting values to string, trimming spaces, or standardizing case once up front is often cleaner than embedding those fixes into every filter expression. ## Regex Filtering When You Actually Need It Regular expressions are still useful when the matching rule is more complex than a plain substring. For example, filter names that start with `A`, `B`, or `C`: ```python regex_filtered = df[df["name"].str.contains(r"^[ABC]", na=False)] print(regex_filtered) ``` Use regex deliberately. Do not leave it on by default if the search text comes from users and should be treated literally. For larger data-cleaning pipelines, it is often worth storing the mask in a named variable instead of filtering inline. That makes debugging easier because you can inspect how many rows matched before applying the final selection. That same pattern also helps when multiple substring rules need to be combined with `&` and `|`, because each intermediate mask can be tested independently. ## Common Pitfalls The most common mistake is forgetting `na=False`. Missing values then create a mask with null entries, which often causes confusing behavior. Another mistake is forgetting that `str.contains` uses regex by default. A pattern such as `.` or `+` has special meaning unless `regex=False` is set. A third mistake is filtering non-string columns without converting them first. If the column contains mixed types, clean or cast the data before applying string methods. ## Summary - Use `str.contains` for general substring filtering in pandas. - Add `na=False` so missing values do not break the filter mask. - Use `case=False` for case-insensitive matching. - Set `regex=False` when the search term should be treated as a literal string. - Prefer `startswith` and `endswith` when the matching rule is positional rather than “contains anywhere.”

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

ML System Design practice on Codemia

Design recommenders, ranking systems and training pipelines the way ML interviews actually ask for them, with worked solutions.

Practice ML system design

All Rights Reserved.