Grouping and Summarising with groupby
🎧 Focus sounds
Soft beat sounds that many learners like while reading. Pick one, press Play, and keep studying.
Keep the volume low. These sounds are for comfort while studying, not a medical treatment. If you have epilepsy or are sensitive to pulsing sounds, use the background noise only.
In this lesson
Most business questions contain the word per: sales per city, average marks per class, orders per month. In Pandas the answer is groupby. It works in three steps: split the rows into groups, apply a calculation to each group, and combine the results. Watch it happen:
import pandas as pd
df = pd.DataFrame({
"name": ["Asha", "Rahul", "Meera", "Kabir", "Zoya", "Dev"],
"city": ["Pune", "Surat", "Delhi", "Pune", "Delhi", "Surat"],
"marks": [82, 64, 91, 58, 77, 88],
})
print(df.groupby("city")["marks"].mean())
Output:
city
Delhi 84.0
Pune 70.0
Surat 76.0
Name: marks, dtype: float64
Read it as: “group by city, take the marks column, compute the mean”. The cities become the index, sorted A to Z.
Several statistics at once: agg#
summary = df.groupby("city")["marks"].agg(["count", "mean", "max"])
print(summary)
Output:
count mean max
city
Delhi 2 84.0 91
Pune 2 70.0 82
Surat 2 76.0 88
Name the result columns yourself with “named aggregation”:
summary = df.groupby("city").agg(
students=("name", "count"),
average=("marks", "mean"),
best=("marks", "max"),
).reset_index()
print(summary)
Output:
city students average best
0 Delhi 2 84.0 91
1 Pune 2 70.0 82
2 Surat 2 76.0 88
reset_index() turns the city index back into a normal column, which is easier to sort, chart or save.
A real example: sales by month and product#
sales = pd.DataFrame({
"month": ["Jan", "Jan", "Jan", "Feb", "Feb", "Feb"],
"product": ["Pen", "Book", "Bag", "Pen", "Book", "Bag"],
"revenue": [1500, 4200, 8500, 1800, 3900, 9600],
})
print(sales.groupby("month", sort=False)["revenue"].sum())
Output:
month
Jan 14200
Feb 15300
Name: revenue, dtype: int64
sort=False keeps the months in the order they appear instead of alphabetical (which would put Feb first).
Pivot tables#
A pivot table puts one category down the side and another across the top, exactly like Excel:
table = sales.pivot_table(index="product", columns="month", values="revenue", aggfunc="sum")
print(table[["Jan", "Feb"]])
Output:
month Jan Feb
product
Bag 8500 9600
Book 4200 3900
Pen 1500 1800
Now it’s easy to see Book sales dropped in February while Bag and Pen grew.
Group by several columns with a list: df.groupby(["city", "gender"])["marks"].mean() gives one row per city–gender pair.
Quick check
df.groupby("city").size() counts rows in each group, including rows with missing values; count() skips missing values. For “how many orders per city”, size() is usually what you want.
Summary#
df.groupby("col")["value"].sum(): split, apply, combine..agg([...])or named aggregation for several results at once.reset_index()makes the groups a normal column again.pivot_table(index=..., columns=..., values=..., aggfunc=...)for Excel-style tables.
Quick quiz
3 questions. Check what stuck and earn 2 XP for each right answer.
Progress is saved in this browser. Create a free account to keep it on every device.
Get new lessons in your inbox
One email when we publish a new tutorial or guide. No spam, unsubscribe in one click.