agg with Several Summaries
Overview
More than one answer per group, named as you want them.
What You Will Learn in This Lesson
By the end of this lesson, you will be able to:
- Ask for several summaries in one pass.
- Name the output columns rather than accepting the defaults.
- Apply different summaries to different columns.
- Build a summary that is not a built-in.
Why This Matters
One group-by per statistic means walking the table three times and then stitching the results together. agg does it in one pass and, more importantly, lets you name the columns — so the result is a table a reader can understand without you standing next to it.
Step 1: A list of functions
Pass a list and you get a column per summary, named after the function.
Several at once
One pass over the data, one table out.
import pandas as pd
df = pd.DataFrame({"k": ["a", "a", "b"], "v": [1, 4, 7]})
print(df.groupby("k")["v"].agg(["min", "max", "mean", "size"]))
Different summaries per column
A dictionary maps each column to what you want from it, which is how a real summary table usually looks.
import pandas as pd
df = pd.DataFrame({"k": ["a", "a"], "score": [90, 80], "hours": [2, 5]})
print(df.groupby("k").agg({"score": "mean", "hours": "sum"}))
Mini Practice #1: Four summaries, one pass
Try It YourselfProduce the minimum, maximum, mean and row count per key in a single call.
Step 2: Naming the outputs
Named aggregation gives you the columns you want with the names you want, and it is the form worth defaulting to.
Say what each column is
Each keyword becomes a column name, and the tuple says which column to summarise and how.
import pandas as pd
df = pd.DataFrame({"k": ["a", "a", "b"], "v": [1, 4, 7]})
print(df.groupby("k").agg(
lowest=("v", "min"),
highest=("v", "max"),
rows=("v", "size"),
))
Compare this with the default names from a list of functions. The difference is whether the person reading your output has to ask you what a column means.
A summary of your own
Anything that reduces a Series to one value works, including a lambda. The range — highest minus lowest — is the obvious example, and it has no built-in.
import pandas as pd
df = pd.DataFrame({"k": ["a", "a", "b"], "v": [1, 4, 7]})
print(df.groupby("k")["v"].agg(spread=lambda s: s.max() - s.min()))
Mini Practice #2: Name them yourself
Try It YourselfProduce the same table again, with the columns named lowest, highest and rows.
Step 3: When to Use It
Several numbers per group
Count, mean and max side by side, so every mean comes with the size behind it.
df.groupby("team")["score"].agg(["count", "mean", "max"])
Readable column names
Named aggregation gives each result the name a reader should see.
When Not to Use It
Do not produce a wide table of every summary for every column. Pick the few numbers the question needs; the rest hides them.
End-of-Lesson Exercises
Exercise 1: The spread within each group
Write range_by(df) returning a dictionary of each key to the difference between its highest and lowest v.
Group, take max and min of v for each group, subtract one from the other, then to_dict(). The second hidden case is the whole point: the range is per group.
Exercise 2: A named summary table
Write summary_table(df) that returns the column names of a grouped summary carrying, in this order, lowest, highest and rows per key. Name the columns rather than accepting the defaults.
df.groupby("k").agg(lowest=("v", "min"), highest=("v", "max"), rows=("v", "size")) then list(...columns). Passing a list of function names instead would give you min, max and size as the names.