iwantcoding.com
🔥 Daily 👥 Rooms 🏆 Top Log in Sign up

.str accessor

pandas string accessor `.str` exposes vectorised text operations on a Series of strings — split, contains, extract, replace, slice, lower, strip, and dozens more. They handle missing values gracefully and run in C-speed loops, which is dramatically faster than Series.apply(lambda x: x.foo()).

Vectorised string ops for cleaning and feature work

EXAMPLE
import pandas as pd
import numpy as np

df = pd.DataFrame({
    'email':   ['Alice@Example.com', ' bob@example.com ', None, 'CAROL@example.com'],
    'name':    ['Alice Smith', 'Bob Jones', 'Carol Lee', 'Daniel O\'Connor'],
    'address': ['12 Oak St, Sydney NSW 2000',
                '34 Pine Rd, Melbourne VIC 3000',
                None,
                '78 Birch Ln, Brisbane QLD 4000'],
})

# 1) Normalise emails: trim, lowercase
df['email_norm'] = df['email'].str.strip().str.lower()

# 2) Filter rows whose email looks valid
mask = df['email_norm'].str.contains(r'^[^@]+@[^@]+\.[^@]+$', na=False, regex=True)
print(df.loc[mask, ['email_norm']])

# 3) Split a name into first/last
df[['first', 'last']] = df['name'].str.split(' ', n=1, expand=True)

# 4) Extract structured fields with named groups
addr_re = r'(?P<street>[^,]+),\s*(?P<city>[A-Za-z ]+)\s+(?P<state>[A-Z]{2,3})\s+(?P<postcode>\d{4})'
df = df.join(df['address'].str.extract(addr_re))
print(df[['street','city','state','postcode']])

# 5) Multiple replacements at once via a regex dict
title_fix = {
    r'^Mr ': 'Mr. ',
    r'^Mrs ': 'Mrs. ',
    r'^Dr ': 'Dr. ',
}
df['name'] = df['name'].replace(title_fix, regex=True)

# 6) Slice characters by position (e.g. first 3 chars as a code)
df['email_user'] = df['email_norm'].str.split('@').str[0]

# 7) Length, startswith, endswith — all vectorised, all NA-aware
df['email_len'] = df['email_norm'].str.len()
df['gov_email'] = df['email_norm'].str.endswith('.gov.au', na=False)

# 8) Concatenate Series with separators
full = df['first'].str.cat(df['last'], sep=' ', na_rep='?')

# 9) Performance tip: ensure the column is a real string dtype (not object)
df['email_norm'] = df['email_norm'].astype('string')   # nullable string dtype
# String dtype enables the same str. operations but with better NA handling.

Why it matters

Reach for the `string` (StringDtype) dtype over the legacy object dtype on text columns. It preserves missing values as `pd.NA` consistently across operations, which spares you a stream of \"object inference\" surprises when you concatenate, groupby, or write to parquet.

Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.

Example

Example
import pandas as pd
df['domain']  = df['email'].str.split('@').str[1]
df['is_corp'] = df['email'].str.contains(r'\.com\$', regex=True)
df['name']    = df['name'].str.strip().str.title()
Try it Yourself »

Discussion

Loading…