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

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 rows
import 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  gloves

2 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 each
import 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    phys

3 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.

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

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.