String methods

The .str accessor — strip, case, contains, extract, split, replace.

Object/string columns grow a .str accessor: vectorized Python-string operations that return a Series. They skip (or NA) missing values.

Goal

Trim, case-fold, test, extract, split, and replace text without a Python for loop.

Strip and case

names = pd.Series(
    [" ada kwon", "ALAN TURING", "Grace Hopper", "linus", "  nia "],
    name="name",
)
clean = names.str.strip().str.title()
print(names)
print()
print(clean)

Common chain: striplower or title → then match.

Contains, starts, ends

names = pd.Series(
    [" ada kwon", "ALAN TURING", "Grace Hopper", "linus", "  nia "],
    name="name",
)
clean = names.str.strip()
print(clean.str.contains("a", case=False, na=False))
print()
print(clean[clean.str.lower().str.startswith("a")])

na=False makes missing values False so they do not leak into a filter as NA.

Replace and length

clean = pd.Series(["Ada Kwon", "Alan Turing", "Grace Hopper"], name="name")
print(clean.str.replace(" ", "_", regex=False))
print()
print(clean.str.len())

Use regex=True only when you mean it. For a literal dot, regex=False is safer.

Split into columns

clean = pd.Series(["Ada Kwon", "Alan Turing", "Grace Hopper", "Linus"], name="name")
parts = clean.str.split(n=1, expand=True)
parts.columns = ["first", "last"]
print(parts)

expand=True returns a DataFrame. Without it you get a Series of lists.

Extract with a regex

codes = pd.Series(["A-12", "B-7", "C-31", "bad"], name="sku")
print(codes.str.extract(r"([A-Z])-(\d+)"))

Unmatched rows are NA.

Slice

clean = pd.Series(["Ada Kwon", "Alan Turing", "Grace Hopper"], name="name")
print(clean.str[:4])
print(clean.str[-3:])
You should see

messy.csv in the Files chapter needs .str.strip() and .str.title() before you can drop duplicate people.