Splitting & Joining Text
Split one text column into many with str.split (expand, n), pick pieces with str.get, and combine text with str.cat, str.join and +.
Watch the lesson
1 video on CodeWithMunnaX
Many columns pack several facts into one string: "Virat Kohli" (first + last name), "Maruti Swift Dzire VDI" (brand + model), "2020-10-10" (year + month + day), "RCB vs MI" (two teams). Splitting breaks such text into pieces you can analyse separately; joining does the opposite — builds labels like "Virat Kohli (RCB)" from several columns. In Munna's car-pricing notebook, df['name'].str.split(' ') is the first step to get each car's brand.
Definition
str.split(pat)cuts each string at every occurrence of a separator and returns the pieces — as a list per row, or, withexpand=True, as separate columns of a DataFrame.str.cat()concatenates strings (with each other or with another Series, using asep), andstr.join(sep)glues the elements of a list in each row into one string.
- Separator — the text to cut at (
" ",",","-"," vs ");Nonemeans any run of whitespace. - List per row —
["Virat", "Kohli"]; pick pieces from it with.str.get(i)or.str[i]. expand=True— each piece goes into its own column (0, 1, 2 …), padded withNaN/Nonewhen a row has fewer pieces.
Syntax
python
s.str.split(pat=None, n=-1, expand=False, regex=None)
s.str.rsplit(pat=None, n=-1, expand=False) # split starting from the right
s.str.get(i) / s.str[i] # element i of each list (or char i of each string)
s.str.join(sep) # join list elements in each row
s.str.cat(others=None, sep=None, na_rep=None)
s1 + " " + s2 # simple concatenation| Parameter | Meaning | Default |
|---|---|---|
pat | separator text or regex; None = any whitespace | None |
n | maximum number of splits; -1 = all | -1 |
expand | True = return a DataFrame with one column per piece | False |
regex | treat pat as regex (None = auto: regex only if longer than 1 char) | None |
i (get) | position of the piece (negative counts from the end) | — |
others (cat) | Series/list to join element-wise; None = join the whole column into one string | None |
sep | text placed between joined pieces | "" |
na_rep (cat) | text used for missing values; otherwise a missing value gives NaN | None |
Example — split into lists, then pick pieces
python
players = pd.Series(["Virat Kohli", "Rohit Gurunath Sharma", "Dhoni"])
parts = players.str.split()
print(parts)
print(parts.str.get(0).tolist()) # first piece
print(parts.str[-1].tolist()) # last piece
print(parts.str.len().tolist()) # how many piecestext
0 [Virat, Kohli]
1 [Rohit, Gurunath, Sharma]
2 [Dhoni]
dtype: object
['Virat', 'Rohit', 'Dhoni']
['Kohli', 'Sharma', 'Dhoni']
[2, 3, 1]How it works: with no separator, split() cuts at whitespace. Each row becomes a list. .str.get(0) / .str[0] takes the first element of each list, .str[-1] the last — safe even when a list is shorter (Dhoni has one word, so first and last are both "Dhoni").
Example — expand=True and n
python
print(players.str.split(expand=True))
print()
print(players.str.split(n=1, expand=True))text
0 1 2
0 Virat Kohli NaN
1 Rohit Gurunath Sharma
2 Dhoni NaN NaN
0 1
0 Virat Kohli
1 Rohit Gurunath Sharma
2 Dhoni NaNHow it works: expand=True creates columns 0, 1, 2. Rows with fewer pieces get NaN in the extra columns. n=1 splits only at the first space, so everything after it stays together — perfect for "first name / rest of the name".
Example — assign split columns to a DataFrame
python
df = pd.DataFrame({"fixture": ["CSK vs MI", "RCB vs KKR", "DC vs SRH"],
"date": ["2024-03-22", "2024-03-29", "2024-04-07"]})
df[["home", "away"]] = df["fixture"].str.split(" vs ", expand=True)
df[["year", "month", "day"]] = df["date"].str.split("-", expand=True)
print(df)text
fixture date home away year month day
0 CSK vs MI 2024-03-22 CSK MI 2024 03 22
1 RCB vs KKR 2024-03-29 RCB KKR 2024 03 29
2 DC vs SRH 2024-04-07 DC SRH 2024 04 07How it works: the number of new column names must equal the number of columns split(expand=True) produces. Note the parts are still text ("2024"); convert with astype(int) if you need numbers — or better, use pd.to_datetime for dates.
Example — rsplit: split from the right
python
cars = pd.Series(["Maruti Swift Dzire VDI", "Hyundai Verna 1.6 SX", "Tata Nano"])
print(cars.str.rsplit(n=1, expand=True))text
0 1
0 Maruti Swift Dzire VDI
1 Hyundai Verna 1.6 SX
2 Tata Nanorsplit(n=1) cuts only at the last space — handy when the useful piece is at the end (the variant VDI, SX).
Example — joining: cat, + and join
python
squad = pd.DataFrame({"first": ["Virat", "Rohit", "Shubman"],
"last": ["Kohli", "Sharma", None],
"team": ["RCB", "MI", "GT"]})
print((squad["first"] + " " + squad["last"]).tolist())
print(squad["first"].str.cat(squad["last"], sep=" ").tolist())
print(squad["first"].str.cat(squad["last"], sep=" ", na_rep="?").tolist())
print(squad["team"].str.cat(sep=", "))text
['Virat Kohli', 'Rohit Sharma', nan]
['Virat Kohli', 'Rohit Sharma', nan]
['Virat Kohli', 'Rohit Sharma', 'Shubman ?']
RCB, MI, GTHow it works:
+andstr.cat(others)join row by row; a missing value makes the result missing.na_rep="?"substitutes text for missing values.str.cat(sep=", ")with noothersjoins the whole column into one single string.
python
words = pd.Series([["Chennai", "Super", "Kings"], ["Mumbai", "Indians"]])
print(words.str.join("_").tolist())
print(words.str.join("").tolist())text
['Chennai_Super_Kings', 'Mumbai_Indians']
['ChennaiSuperKings', 'MumbaiIndians']str.join(sep) works on rows that hold lists — it is the reverse of split. (On plain strings it would put the separator between every character.)
Comparison — split options
| Want | Code |
|---|---|
| list per row | s.str.split(",") |
| separate columns | s.str.split(",", expand=True) |
| only the first cut | s.str.split(" ", n=1, expand=True) |
| only the last cut | s.str.rsplit(" ", n=1, expand=True) |
| one piece | s.str.split().str[0] / .str.get(0) |
| one row per piece | s.str.split(",").explode() |
Common mistakes
- ❌
df[["a", "b"]] = s.str.split(" ", expand=True)when some rows have 3 pieces →ValueError: Columns must be same length as key. ✅ Usen=1, or pick pieces with.str[0]/.str[-1]. - ❌ Expecting split pieces to be numbers. ✅ They are text; convert with
astype/pd.to_numeric. - ❌
s.str.join(" ")on plain strings →"V i r a t". ✅joinis for lists; usestr.catfor strings. - ❌
split(".")on"1.6"with regex assumptions. ✅ For a single character the separator is literal; passregex=False/Trueexplicitly when unsure.
Interview tip
Q: How do you split a "full_name" column into first and last name columns?
A: df[["first", "last"]] = df["full_name"].str.split(" ", n=1, expand=True) — n=1 guarantees exactly two columns even for names with middle names.
Key points to remember
- str.split(pat) cuts each string into a list; with no pat it splits on any whitespace.
- expand=True puts the pieces into separate DataFrame columns; missing pieces become NaN.
- n limits the number of splits — n=1 gives at most two pieces; rsplit(n=1) cuts at the last separator.
- Pick one piece with .str.get(i) or .str[i]; .str[-1] is the last piece.
- Split results are text — convert with astype/to_numeric before doing math.
- s1 + ' ' + s2 or s1.str.cat(s2, sep=' ') join row by row; str.cat(sep=', ') joins the whole column.
- str.join(sep) joins the elements of list values — the reverse of split.
Try it yourself
First and last names
Split a fixture and a date string
Join columns and whole columns
Practice: split car names into brand and model
Revision Flashcards
Tap a card to flip it and see the answer.
