Exploding Lists into Rows (explode)
Reviewed & published by Brayan K
explode() unpacks a column of lists so that every element gets its own row, copying the other column values down to match — turning one wide, nested row into several tidy ones.
Part of the free Pandas course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.
You'll learn df.explode("col"), how to split strings into lists first, and how to reverse the operation with groupby().agg(list).
What You'll Learn in This Lesson
- Turn a list cell into one row per element
- Why the other columns are duplicated down
- Reset labels with ignore_index=True
- Split strings with .str.split() then explode
- Rebuild lists with groupby().agg(list)
- Count items after exploding
1 The Basic Explode — One Row Per List Item
Data often arrives with multiple values crammed into a single cell — an order with several items, a user with several tags. df.explode("col") spreads that list out: each element becomes its own row, and the values in the other columns are duplicated so every new row stays complete.
import pandas as pd
df = pd.DataFrame({
"order": [1, 2, 3],
"items": [["pen", "pad"], ["mug"], ["hat", "scarf", "gloves"]],
})
df.explode("items") # 2 + 1 + 3 = 6 rowsimport pandas as pd
df = pd.DataFrame({
"order": [1, 2, 3],
"items": [["pen", "pad"], ["mug"], ["hat", "scarf", "gloves"]],
})
print(df)
# One row per item; "order" is repeated to match
print(df.explode("items"))
# ✅ Expected output:
# order items
# 0 1 [pen, pad]
# 1 2 [mug]
# 2 3 [hat, scarf, gloves]
# order items
# 0 1 pen
# 0 1 pad
# 1 2 mug
# 2 3 hat
# 2 3 scarf
# 2 3 gloves2 Split a String, Then Explode
Very often the "list" is really a delimited string like "math,art". explode() will not split that for you — it only unpacks real list-like values. The two-step recipe is: turn the string into a list with .str.split(","), then explode the resulting list column.
df["courses"] = df["courses"].str.split(",") # "math,art" -> ["math", "art"]
df.explode("courses") # then one row eachimport pandas as pd
df = pd.DataFrame({
"student": ["Ana", "Ben"],
"courses": ["math,art", "bio,chem,phys"],
})
# Step 1: split the delimited string into a list
df["courses"] = df["courses"].str.split(",")
# Step 2: explode the list into rows
print(df.explode("courses"))
# ✅ Expected output:
# student courses
# 0 Ana math
# 0 Ana art
# 1 Ben bio
# 1 Ben chem
# 1 Ben phys3 The Inverse — groupby().agg(list)
Exploding is reversible. To collapse the tidy rows back into one row per original entity, group by the identifying column and aggregate the item column with the built-in list function. This gathers each group's values back into a single list.
exploded = df.explode("items")
# Collapse back: one list per order
exploded.groupby("order")["items"].agg(list).reset_index()import pandas as pd
df = pd.DataFrame({
"order": [1, 2, 3],
"items": [["pen", "pad"], ["mug"], ["hat", "scarf", "gloves"]],
})
exploded = df.explode("items")
# Rebuild the original list-per-order shape
back = exploded.groupby("order")["items"].agg(list).reset_index()
print(back)
# ✅ Expected output:
# order items
# 0 1 [pen, pad]
# 1 2 [mug]
# 2 3 [hat, scarf, gloves]import pandas as pd
df = pd.DataFrame({
"recipe": ["Soup", "Salad"],
"ingredients": [["water", "salt", "carrot"], ["lettuce", "oil"]],
})
# 🎯 YOUR TURN:
# Give every ingredient its own row AND use a clean 0..n index.
# Fill in the method name and the keyword argument.
print(df.____("ingredients", ____=True))
# Expected output:
# recipe ingredients
# 0 Soup water
# 1 Soup salt
# 2 Soup carrot
# 3 Salad lettuce
# 4 Salad oil! Common Errors (And How to Fix Them)
❌ Exploding a string does nothing useful
A raw string is not a list, so each character is not split out — the row is returned unchanged:
pd.DataFrame({"tags": ["a,b,c"]}).explode("tags") # ❌ still one row "a,b,c"✅ Fix: split into a list first:
df["tags"] = df["tags"].str.split(",")
df.explode("tags") # ✅ a, b, c on three rows❌ Surprised by repeated index labels
df.explode("items") # index -> 0, 0, 1, 2, 2, 2✅ Fix: reset it when you need unique labels:
df.explode("items", ignore_index=True) # index -> 0..n🎯 Mini Challenge: Tag Popularity
Each post has pipe-separated tags. Find out which tags appear most often.
- Split the tags string on "|"
- Explode into one tag per row
- Count tags with value_counts()
import pandas as pd
df = pd.DataFrame({
"post": [1, 2, 3],
"tags": ["python|data", "data|viz|python", "ml"],
})
df["tags"] = df["tags"].str.split("|")
exploded = df.explode("tags")
print(exploded["tags"].value_counts())
# ✅ Expected output:
# tags
# python 2
# data 2
# viz 1
# ml 1
# Name: count, dtype: int64❓ Frequently Asked Questions
Lesson complete — nested data is no longer scary!
You can unpack list columns with explode(), split strings into lists first, reset labels with ignore_index=True, and rebuild the nested shape with groupby().agg(list).
Practice quiz
What does df.explode('items') do?
- Deletes the items column
- Gives every list element its own row
- Joins lists into one string
- Counts the items
Answer: Gives every list element its own row. explode unpacks a list cell so each element becomes its own row.
When a row's list is exploded, what happens to the other columns?
- They are set to NaN
- They are dropped
- They are summed
- Their values are duplicated down to match
Answer: Their values are duplicated down to match. The other column values are copied so every new row stays complete.
If column 'items' holds [['pen','pad'],['mug'],['hat','scarf','gloves']], how many rows does explode produce?
- 3
- 9
- 6
- 1
Answer: 6. 2 + 1 + 3 = 6 rows after exploding.
What index labels result from exploding rows 0, 1, 2 with 2, 1, 3 items?
- 0, 0, 1, 2, 2, 2
- 0, 1, 2, 3, 4, 5
- 0, 1, 2
- All zeros
Answer: 0, 0, 1, 2, 2, 2. explode keeps each original label, so you get 0, 0, 1, 2, 2, 2.
How do you give the exploded result a clean 0..n index?
- reset_index=True
- ignore_index=True
- new_index=True
- fresh=True
Answer: ignore_index=True. Pass ignore_index=True to get a fresh RangeIndex.
What happens if you explode a column of plain comma-separated strings?
- Each character becomes a row
- It raises an error
- It splits on commas automatically
- Nothing useful — the row is returned unchanged
Answer: Nothing useful — the row is returned unchanged. explode only splits list-like values, not raw strings; the row stays as one.
What is the correct two-step recipe to explode 'math,art'?
- .str.split(',') then explode
- explode then .str.split(',')
- astype(list) then sum
- groupby then explode
Answer: .str.split(',') then explode. First .str.split(',') makes a real list, then explode flattens it.
How do you reverse an explode and collapse rows back into lists?
- df.implode()
- df.unstack()
- df.groupby('id')['items'].agg(list)
- df.melt()
Answer: df.groupby('id')['items'].agg(list). Group by the identifying column and aggregate with list to rebuild the nested shape.
After splitting tags on '|' and exploding ['python|data','data|viz|python','ml'], how many times does 'python' appear in value_counts()?
- 1
- 2
- 3
- 0
Answer: 2. python appears in posts 1 and 2, so its count is 2.
Which form is best for filtering, counting, and joining individual items?
- The nested list form
- The exploded long form
- A pivot table
- A JSON string
Answer: The exploded long form. The exploded (long) form gives one item per row, ideal for filtering and counting.
Continue this course
- Previous: Interpolation & Filling Gaps
- Next: Cross-Tabulation (crosstab) — Count and summarise category combinations with pd.crosstab
- Quick reference: Pandas cheat sheet
Frequently asked questions
What does df.explode() actually do?
explode('col') takes a column whose cells contain lists (or other list-like values) and gives every element its own row, duplicating the other column values to match. A single row holding a 3-item list becomes three rows that share the same other fields.
Why do the index labels repeat after exploding?
explode keeps the original row's index on every element it produces, so a row with index 2 and three items yields three rows all labelled 2. Pass ignore_index=True to get a fresh 0..n-1 RangeIndex instead.
How do I explode a column of comma-separated strings?
First turn each string into a real list with the string accessor — df['col'] = df['col'].str.split(',') — and then call df.explode('col'). explode itself only splits list-like values, not raw strings.
How do I undo an explode and collapse rows back into lists?
Group by the columns that identify the original row and aggregate the exploded column with list: df.groupby('id')['items'].agg(list). That rebuilds one row per group with the items gathered back into a list.