Filter pandas DataFrame by substring criteria
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
To filter a pandas DataFrame by substring, use df[df['column'].str.contains('substring')]. This returns rows where the specified column contains the given substring. For case-insensitive matching, pass case=False. For exact pattern matching, use regex patterns. Other useful methods include str.startswith(), str.endswith(), str.match(), and str.fullmatch(). Always handle NaN values with na=False to avoid errors.
Basic Substring Filtering with str.contains
Handling NaN Values
str.contains() returns NaN for missing values, which causes a boolean indexing error. Use na=False to treat NaN as non-matching:
Regex Pattern Matching
str.contains() supports regular expressions by default:
Multiple Substring Matching
Filter by multiple substrings using regex OR (|):
str.startswith and str.endswith
Negating the Filter (NOT Contains)
Use the ~ operator to invert the boolean mask:
Filtering Across Multiple Columns
Performance Comparison
For large DataFrames with simple literal substring matching, passing regex=False is significantly faster. Python list comprehensions can be even faster for simple cases.
Common Pitfalls
- Not passing
na=Falsewhen the column contains NaN:str.contains()returnsNaNfor missing values, which cannot be used as a boolean index. Always addna=False(orna=Trueto include NaN rows) to avoidValueError. - Forgetting that
str.containsuses regex by default: Special regex characters like.,*,+,(,)are interpreted as patterns. To search for a literal period, useregex=Falseor escape with\.. For example,str.contains('file.txt')matchesfiletxttoo. - Using
str.containswhenisinis more appropriate:str.contains('apple')matches partial substrings (e.g., "pineapple"). For exact value matching, usedf['col'].isin(['apple'])instead. - Applying substring filters to non-string columns: If the column dtype is not
objectorstring,str.contains()fails. Convert first withdf['col'].astype(str).str.contains(...). - Chaining multiple
str.containscalls instead of using regex OR: Writingdf[df['col'].str.contains('a')] & df[df['col'].str.contains('b')]creates intermediate DataFrames. Usedf['col'].str.contains('a|b')for a single efficient pass.
Summary
df[df['col'].str.contains('text', na=False)]is the standard substring filter- Pass
case=Falsefor case-insensitive matching - Use
regex=Falsefor literal string matching (faster and avoids regex escaping) - Use
str.startswith()andstr.endswith()for prefix/suffix matching - Negate with
~operator to get rows that do NOT match - Always include
na=Falseto handle NaN values safely

