Unit 7 • Lesson 1

Split, Apply, Combine

Overview

The shape of every group-by, named once so the rest makes sense.

Intermediate 20–25 min

What You Will Learn in This Lesson

By the end of this lesson, you will be able to:

  • Name the three steps of a group-by.
  • Say why df.groupby("x") on its own computes nothing.
  • Read the result, and get the key back as a column.
  • Report the group size beside the group summary.

Why This Matters

Every question of the form "per region", "by month", "for each subject" is this one operation. Naming its three steps once means the rest of the unit is variations rather than new material — and it makes the error messages legible, because they nearly always come from the apply step.

Step 1: Three steps in one call

Split the table into groups by a key, apply a summary to each group, combine the answers into one result. pandas does all three in one expression, which is why it helps to be able to name them separately.

1

Nothing happens until you name the summary

The grouped object is a plan, not a result. Printing it tells you almost nothing, which is confusing until you know it is deliberate.

import pandas as pd

df = pd.DataFrame({"subject": ["maths", "art", "maths"], "score": [90, 70, 80]})
grouped = df.groupby("subject")
print(grouped)
print(grouped["score"].mean())
2

The three steps, visible

You will not write it this way, but seeing the split makes the rest concrete.

import pandas as pd

df = pd.DataFrame({"subject": ["maths", "art", "maths"], "score": [90, 70, 80]})

for key, piece in df.groupby("subject"):
    print(key, "->", piece["score"].tolist(), "-> mean", piece["score"].mean())

Mini Practice #1: Watch the split

Try It Yourself

Loop over the groups and print each key with the rows it holds, then get the same answer in one expression.

Press Run to see output

Step 2: The key becomes the index

The result is labelled by the group key, which is a Series indexed by whatever you grouped on.

1

Getting the key back as a column

Sometimes you want a plain table rather than an indexed Series. reset_index turns the key back into a column, and as_index=False asks for that from the start.

import pandas as pd

df = pd.DataFrame({"subject": ["maths", "art", "maths"], "score": [90, 70, 80]})
print(df.groupby("subject")["score"].mean().reset_index())
print(df.groupby("subject", as_index=False)["score"].mean())
2

Always report the size

A mean over two rows and a mean over two thousand are not comparable, and the group with the striking average is very often the group with three rows in it. Putting the count beside the summary is the cheapest honesty there is.

import pandas as pd

df = pd.DataFrame({"subject": ["maths", "art", "maths"], "score": [90, 70, 80]})
out = df.groupby("subject")["score"].agg(["mean", "size"])
print(out)
3

Where rows with a missing key go

A row whose key is NaN is dropped from the result by default, so your groups can silently fail to account for the whole table. dropna=False keeps them as their own group.

import pandas as pd
import numpy as np

df = pd.DataFrame({"subject": ["maths", np.nan], "score": [90, 70]})
print(df.groupby("subject")["score"].size().sum(), "of", len(df))
print(df.groupby("subject", dropna=False)["score"].size().sum(), "of", len(df))

Mini Practice #2: Mean and size together

Try It Yourself

Produce the mean and the row count per city in one result, and notice which group you would be wary of.

Press Run to see output

Step 3: When to Use It

Any question with “per” in it

Mean per team, total per month, count per category: group, summarise, and pandas combines.

df.groupby("team")["score"].mean()

Comparing groups

A grouped result is one row per group, ready to sort, chart or put in a table.

When Not to Use It

Do not loop over the unique values and filter each one by hand. It repeats the scan per group and is easy to get subtly wrong; groupby does it in one pass.

End-of-Lesson Exercises

Exercise 1: Mean score per subject

Write mean_by_subject(df) returning a dictionary of subject to mean score, each mean rounded to one decimal place.

groupby the subject, take the score column, ask for the mean, round it, and to_dict() at the end gives plain keys and values.

Press Run to try it, then Check my work to mark it.

Exercise 2: The mean, with the size beside it

Write summary_by(df) returning a dictionary of subject to a two-element list of [mean score rounded to one place, number of rows]. Reporting the size is what stops a group of two being read like a group of two thousand.

Group once and take both the mean and the size off the same grouped object, then build the dictionary with round() and int() so the values are plain Python.

Press Run to try it, then Check my work to mark it.