How do I work with text columns using the str accessor in pandas?
Short answer
Use the .str accessor to run string methods on a whole column at once, such as split, contains and extract. It is vectorised, so it is faster and cleaner than looping or using apply.
The short version
The .str accessor applies string operations to every value in a column at once. Common ones are .str.split, .str.contains and .str.extract. Because it is vectorised, it is faster and clearer than looping or wrapping str functions in apply. It also skips missing values sensibly rather than erroring on them.
Splitting a column
import pandas as pd
s = pd.Series(["pen-red", "mug-blue"])
print(s.str.split("-", expand=True))
0 1
0 pen red
1 mug blue
expand=True turns the split pieces into separate columns, which is how you break a combined field like product-colour into two.
Testing for a substring
.str.contains returns a boolean column, ideal for filtering.
s.str.contains("red") # [True, False]
s[s.str.contains("red")] # keep only rows containing 'red'
By default contains treats its argument as a regular expression, so special characters like . or ( have meaning. Pass regex=False for a literal substring match, or case=False to ignore case.
Extracting with a pattern
.str.extract pulls out parts of each value using a regular expression with capture groups.
s.str.extract(r"(\w+)-(\w+)")
Each bracketed group becomes a column, so this cleanly separates the two halves. It returns NaN for any value that does not match, which is a useful way to spot rows in an unexpected format.
Why not use apply
You could write s.apply(lambda x: x.split("-")), but that runs a Python function per row and does not handle missing values gracefully. The .str methods are implemented for whole columns, so they are faster and treat NaN as NaN rather than raising an AttributeError.
Chaining string operations
The methods chain, because each returns a Series you can call .str on again.
s.str.upper().str.replace("-", " ")
This uppercases and then swaps the separator, reading left to right as a small pipeline.
The missing-value behaviour
A real benefit is that .str methods return NaN for missing entries instead of crashing. So a column with the occasional gap can be cleaned without special handling, whereas a raw apply calling .split on a NaN would raise. This alone is a good reason to prefer .str for column-wide text work.