pandas
data cleaning
python programming
data manipulation
data analysis

How to Remove Rows from Pandas Data Frame that Contains any String in a Particular Column

Master System Design with Codemia

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

Introduction

Removing rows based on string content in one pandas column is a common cleaning step, but the exact solution depends on what "contains any string" means in your dataset. Sometimes you want to drop rows containing a specific substring such as "NA", and sometimes you want to drop every row where the column is not numeric.

Remove Rows That Contain a Particular Substring

If the goal is to remove rows where a column contains some specific text, str.contains is usually the cleanest solution. Build a boolean mask and negate it.

python
1import pandas as pd
2
3df = pd.DataFrame(
4    {
5        "name": ["Ana", "Bob", "Cara", "Dan"],
6        "status": ["ok", "NA", "pending", "NA"],
7    }
8)
9
10clean = df[~df["status"].str.contains("NA", na=False)]
11print(clean)

Output:

text
   name   status
0   Ana       ok
2  Cara  pending

The na=False part matters because missing values otherwise produce NaN in the mask, which can complicate filtering.

Remove Rows That Contain Any Alphabetic Text

If your column is supposed to be numeric but sometimes contains strings such as "bad" or "missing", you can filter rows that contain letters with a regular expression.

python
1import pandas as pd
2
3df = pd.DataFrame(
4    {
5        "id": [1, 2, 3, 4],
6        "amount": ["10", "25", "bad", "40"],
7    }
8)
9
10mask = df["amount"].astype(str).str.contains(r"[A-Za-z]", na=False)
11clean = df[~mask]
12print(clean)

This keeps rows whose amount values do not contain alphabetic characters.

That approach is useful when your data contains mixed strings and numbers as text, but it assumes letters are the thing you want to reject. If your bad rows include other symbols, use numeric conversion instead.

Remove Rows That Are Not Truly Numeric

For mixed columns, the most reliable method is usually pd.to_numeric(..., errors="coerce"). Any value that cannot be parsed as a number becomes NaN, and then you can filter those rows out.

python
1import pandas as pd
2
3df = pd.DataFrame(
4    {
5        "id": [1, 2, 3, 4, 5],
6        "amount": ["10", "25.5", "bad", None, "40"],
7    }
8)
9
10numeric_amount = pd.to_numeric(df["amount"], errors="coerce")
11clean = df[numeric_amount.notna()].copy()
12clean["amount"] = numeric_amount[numeric_amount.notna()]
13
14print(clean)

This version is better than a letter-based regex when the column should contain real numeric values, because it handles decimals, missing values, and invalid strings in one place.

Use Exact Matches for Placeholder Tokens

If your bad values are specific markers such as "NA", "unknown", or "n/a", exact matching is faster and clearer than a regex.

python
1import pandas as pd
2
3df = pd.DataFrame(
4    {
5        "name": ["Ana", "Bob", "Cara", "Dan"],
6        "status": ["ok", "unknown", "ok", "n/a"],
7    }
8)
9
10bad_values = {"unknown", "n/a"}
11clean = df[~df["status"].isin(bad_values)]
12print(clean)

Use isin when you know the exact set of unwanted strings ahead of time.

Pick the Method That Matches the Data Contract

A good rule of thumb is:

  • use str.contains when you want substring or regex filtering
  • use isin when you want exact token removal
  • use pd.to_numeric when the column should be numeric and bad strings must be dropped

That choice matters because a regex may accidentally keep malformed numeric values, while to_numeric tells you unambiguously whether the value is usable as a number.

Common Pitfalls

The most common mistake is calling .str.contains on a column that contains missing values and forgetting na=False. Another frequent issue is using a simple alphabetic regex for a column that should be numeric, which can miss other invalid cases such as punctuation or whitespace. Developers also sometimes convert the filtered result but forget to update the column dtype, leaving numeric-looking strings in the cleaned DataFrame. Finally, apply with a row-wise lambda is usually slower and less clear than vectorized pandas operations for this kind of filtering.

Summary

  • Use str.contains and ~ to drop rows containing a particular substring.
  • Use isin when the unwanted values are exact tokens such as "NA" or "unknown".
  • Use pd.to_numeric(..., errors="coerce") when the column is supposed to be numeric.
  • Remember na=False when building string masks over columns with missing values.
  • Prefer vectorized pandas filters over row-by-row apply for both speed and clarity.

Course illustration
Course illustration

All Rights Reserved.