pandas·Lesson 14·12 min·0/3 exercises

GroupBy: split, apply, combine

The three motions hiding inside every .groupby() call.

df.groupby().sum().mean().size().agg()as_index=False.reset_index()

Watch it happen

Play it through, or step back and forth yourself.

df
city
item
cups
revenue
0
Delhi
masala
120
2400.0
1
Mumbai
ginger
80
2000.0
2
Delhi
Ginger
95
1852.5
3
Pune
masala
150
3000.0
4
Mumbai
masala
60
NaN
5
Delhi
elaichi
110
2530.0
splitone pile per group key
applyaggregate each pile
combinestack the answers

Six rows, three cities. The question: how many cups did each city sell? You could loop. Don't — groupby does it in one pass, and it does exactly three things.

The idea

groupby has a reputation for being the point where pandas gets hard. It isn't hard — it's just three steps compressed into one line, and the middle step is the only one you ever change.

  1. Split. Look at the key column, and put every row into a pile with the other rows that share its value.
  2. Apply. Run a function on each pile independently. Each pile becomes one answer.
  3. Combine. Stack those answers into a single result, labelled by the group keys.

That's it. df.groupby("city")["cups"].sum() splits by city, sums the cups column in each pile, and stacks the three totals. Swap .sum() for .mean() and only step two changed.

The GroupBy object is a plan, not a result

Try running df.groupby("city") on its own and you'll get something unhelpful like <DataFrameGroupBy object at 0x…>. That's not a bug. The split has been worked out but nothing has been computed, because pandas doesn't know yet what you want applied. It's waiting for step two.

The group keys become the index

Look at the result of the animation above: the row labels are Delhi, Mumbai, Pune. The thing you grouped by stops being a column and becomes the index. That's usually what you want — but if you'd rather keep it as an ordinary column, either pass as_index=False or call .reset_index() afterwards.

More than one thing at a time

You can group by several columns (df.groupby(["city", "item"]), which gives you a MultiIndex), and you can apply several functions at once with .agg():

df.groupby("city").agg(
    total_cups=("cups", "sum"),
    best_day=("cups", "max"),
    sales=("cups", "count"),
)

That named form is worth learning early — it names your output columns instead of leaving you with a stack of tuples to untangle.

See it run

The lesson's code, ready to run and to fiddle with.

Putting the kettle on…

Starting up…

Worked example

not graded

Already written and ready to go — press Run to see what it does, then change a number, a column name, anything, and run it again.

try.mean(), .max(), or .size() in place of .sum().

Press Run — the output appears here.

Your turn

3 exercises. Write the code yourself, then press Check — a nudge and the answer are there if you want them.

Total revenue per city.

your answer

Average cups sold per item.

your answer

How many rows are in each city group? Return a Series of counts.

your answer