Skip to content

Python Pandas: How to Replace Entire String in Column if Contains Substring

Learn how to replace entire string values in a Pandas DataFrame column when they contain a specific substring using str.contains(), regex, or apply() methods.

When cleaning or transforming text data in Pandas, a common task is to replace the entire string value in a column if it contains a specific substring. For example, you might want to standardize job titles by replacing any title containing "Dev" or "Engineer" with a generic "Developer" or "Engineering Role".

This guide explains several effective methods to achieve this conditional whole-string replacement in Pandas, using str.contains(), str.replace() with regex, and Series.apply().

The Goal: Conditional Full String Replacement

Given a Pandas DataFrame and a specific column containing string values, we want to identify rows where the string in that column includes a certain substring. For all such identified rows, we want to replace the entire string value in that column with a new, specified string.

Example DataFrame

import pandas as pd
import re # For regex flags

data = {
    'EmployeeID': [101, 102, 103, 104, 105, 106],
    'JobTitle_Original': [
        'Software Developer',
        'Senior Web Developer',
        'Data Analyst',
        'DevOps Engineer',
        'Project Manager (Dev)',
        'Lead Analyst'
    ],
    'Department': ['Tech', 'Tech', 'Analytics', 'Tech', 'Management', 'Analytics']
}

df_original = pd.DataFrame(data)
print("Original DataFrame:")
print(df_original)

Output:

Original DataFrame:
   EmployeeID      JobTitle_Original  Department
0         101     Software Developer        Tech
1         102   Senior Web Developer        Tech
2         103           Data Analyst   Analytics
3         104        DevOps Engineer        Tech
4         105  Project Manager (Dev)  Management
5         106           Lead Analyst   Analytics

Our goal is to replace any JobTitle_Original containing "Dev" or "Developer" (case-insensitive) with a standardized "Software Engineering Role".

This is often the most readable and idiomatic Pandas approach.

  1. Use Series.str.contains(substring) to create a boolean mask identifying rows where the column contains the substring.
  2. Use DataFrame.loc[mask, 'ColumnName'] = new_value to assign the new value to the specified column for the matched rows.

Case-Sensitive Replacement

import pandas as pd

df = df_original.copy() # Work on a copy

substring_to_find = 'Dev' # Case-sensitive
new_value = 'Standardized Developer Role'

mask = df['JobTitle_Original'].str.contains(substring_to_find, na=False) # na=False treats NaN as no match
print("Boolean mask for 'Dev':")
print(mask)
print()

df.loc[mask, 'JobTitle_Original'] = new_value

print("DataFrame after case-sensitive replacement using str.contains():")
print(df)

Output:

Boolean mask for 'Dev':
0     True
1     True
2    False
3     True
4     True
5    False
Name: JobTitle_Original, dtype: bool

DataFrame after case-sensitive replacement using str.contains():
   EmployeeID            JobTitle_Original  Department
0         101  Standardized Developer Role        Tech
1         102  Standardized Developer Role        Tech
2         103                 Data Analyst   Analytics
3         104  Standardized Developer Role        Tech
4         105  Standardized Developer Role  Management
5         106                 Lead Analyst   Analytics
  • na=False in str.contains() ensures that if your column has NaN values, they don't cause errors and are treated as not containing the substring.

Case-Insensitive Replacement (case=False)

Set the case=False parameter in str.contains().

import pandas as pd

df = df_original.copy()

substring_to_find_ci = 'dev' # Search for 'dev' case-insensitively
new_value_ci = 'Software Engineering Role'

mask_ci = df['JobTitle_Original'].str.contains(substring_to_find_ci, case=False, na=False)
print("Boolean mask for 'dev' (case-insensitive):")
print(mask_ci)
print()

df.loc[mask_ci, 'JobTitle_Original'] = new_value_ci

print("DataFrame after case-insensitive replacement using str.contains():")
print(df)

Output:

Boolean mask for 'dev' (case-insensitive):
0     True
1     True
2    False
3     True
4     True
5    False
Name: JobTitle_Original, dtype: bool

DataFrame after case-insensitive replacement using str.contains():
   EmployeeID          JobTitle_Original  Department
0         101  Software Engineering Role        Tech
1         102  Software Engineering Role        Tech
2         103               Data Analyst   Analytics
3         104  Software Engineering Role        Tech
4         105  Software Engineering Role  Management
5         106               Lead Analyst   Analytics

Method 2: Using Series.str.replace() with Regular Expressions (Regex)

The Series.str.replace(pattern, replacement_string, regex=True) method can replace occurrences of a pattern (which can be a regex) with replacement_string. To replace the entire string if a substring is found, the regex pattern needs to match the whole string while ensuring the substring is present.

Case-Sensitive Replacement

import pandas as pd

df = df_original.copy()

regex_pattern = r'^.*Dev.*$'
new_value_regex = 'Standardized Developer (Regex)'

df['JobTitle_Original'] = df['JobTitle_Original'].str.replace(
    regex_pattern,
    new_value_regex,
    regex=True
)

print("DataFrame after case-sensitive replacement using str.replace() with regex:")
print(df)

Output:

DataFrame after case-sensitive replacement using str.replace() with regex:
   EmployeeID               JobTitle_Original  Department
0         101  Standardized Developer (Regex)        Tech
1         102  Standardized Developer (Regex)        Tech
2         103                    Data Analyst   Analytics
3         104  Standardized Developer (Regex)        Tech
4         105  Standardized Developer (Regex)  Management
5         106                    Lead Analyst   Analytics

Case-Insensitive Replacement (flags=re.IGNORECASE)

Use the flags parameter with re.IGNORECASE.

import pandas as pd
import re

df = df_original.copy()

regex_pattern_ci = r'^.*dev.*$' # Use lowercase in pattern for consistency with IGNORECASE
new_value_regex_ci = 'Software Engineering (Regex CI)'

df['JobTitle_Original'] = df['JobTitle_Original'].str.replace(
    regex_pattern_ci,
    new_value_regex_ci,
    regex=True,
    flags=re.IGNORECASE # ✅ Case-insensitive flag
)

print("DataFrame after case-insensitive replacement (str.replace() with regex):")
print(df)

Output:

DataFrame after case-insensitive replacement (str.replace() with regex):
   EmployeeID                JobTitle_Original  Department
0         101  Software Engineering (Regex CI)        Tech
1         102  Software Engineering (Regex CI)        Tech
2         103                     Data Analyst   Analytics
3         104  Software Engineering (Regex CI)        Tech
4         105  Software Engineering (Regex CI)  Management
5         106                     Lead Analyst   Analytics

Method 3: Using Series.apply() with a Lambda Function

The Series.apply() method can apply a custom function (or a lambda function) to each element of the Series.

Case-Sensitive Replacement

import pandas as pd

df = df_original.copy()

substring_to_check = 'Dev'
replacement_string = 'Developer via Apply'

df['JobTitle_Original'] = df['JobTitle_Original'].apply(
    lambda current_string: replacement_string if isinstance(current_string, str) and substring_to_check in current_string else current_string
)

print("DataFrame after case-sensitive replacement using apply():")
print(df)

Output:

DataFrame after case-sensitive replacement using apply():
   EmployeeID    JobTitle_Original  Department
0         101  Developer via Apply        Tech
1         102  Developer via Apply        Tech
2         103         Data Analyst   Analytics
3         104  Developer via Apply        Tech
4         105  Developer via Apply  Management
5         106         Lead Analyst   Analytics
  • isinstance(current_string, str): Good practice to check if the element is a string before applying string methods, especially if the column might contain NaN or other types.

Case-Insensitive Replacement (using .lower())

Convert both the current string and the substring to a consistent case (e.g., lowercase) for comparison.

import pandas as pd

df = df_original.copy()

substring_lower = 'dev'
replacement_ci_apply = 'Software Engineer (Apply CI)'

df['JobTitle_Original'] = df['JobTitle_Original'].apply(
    lambda current_string: replacement_ci_apply if isinstance(current_string, str) and substring_lower in current_string.lower() else current_string
)

print("DataFrame after case-insensitive replacement using apply():")
print(df)

Output:

DataFrame after case-insensitive replacement using apply():
   EmployeeID             JobTitle_Original  Department
0         101  Software Engineer (Apply CI)        Tech
1         102  Software Engineer (Apply CI)        Tech
2         103                  Data Analyst   Analytics
3         104  Software Engineer (Apply CI)        Tech
4         105  Software Engineer (Apply CI)  Management
5         106                  Lead Analyst   Analytics

Choosing the Right Method

  • Series.str.contains() with df.loc[] assignment (Method 1): Generally the most recommended for this specific task. It's clear, idiomatic Pandas, and handles case-insensitivity easily. Performance is usually very good.
  • Series.str.replace() with regex (Method 2): More powerful if you need complex pattern matching to define what part of the string to look for before replacing the whole string. Constructing a regex that correctly matches the entire string when a substring is present (like r'^.*substring.*$') is key.
  • Series.apply() (Method 3): Most flexible for complex custom logic that goes beyond simple substring checks or regex. However, it can be slower on large datasets compared to the vectorized .str methods.

Conclusion

To replace an entire string value in a Pandas DataFrame column if it contains a specific substring:

  1. Use df.loc[df['column'].str.contains(substring, case=..., na=False), 'column'] = new_value. This is typically the cleanest and most efficient approach.
  2. Alternatively, df['column'].str.replace(r'^.*substring_pattern.*$', new_value, regex=True, flags=...) can be used with a carefully crafted regular expression that matches the entire string.
  3. df['column'].apply(lambda x: ...) provides maximum flexibility for custom replacement logic but might be less performant.

Remember to handle case sensitivity (case=False or flags=re.IGNORECASE) and potential NaN values (na=False in str.contains) as needed for your specific use case.

Navigation