Pandasdrill

Grouping and aggregation Updated November 2026

groupby

df.groupby("col") splits the rows into groups with the same value and the following method (sum, mean, count, agg, ...) computes one result per group. By default the group keys become the index; pass as_index=False to keep them as columns.

Syntax

df.groupby(by, as_index=True, sort=True, dropna=True)[cols].aggfunc()
PartWhat it is
byColumn name, list of names, or a Series/function to group by
as_indexFalse keeps group keys as regular columns in the result
sortSort group keys (default True); False is faster and keeps first-seen order
dropnaDefault True drops rows whose key is NaN; False keeps a NaN group

Examples

import pandas as pd

df = pd.DataFrame({"dept": ["Sales", "IT", "Sales", "HR", "IT"],
                   "salary": [50000, 62000, 58000, 45000, 70000],
                   "years": [3, 5, 2, 8, 6]})
df.groupby("dept")["salary"].sum()

Result: dept HR 45000 IT 132000 Sales 108000 Name: salary, dtype: int64

df.groupby("dept", as_index=False)["salary"].mean()

Result: dept salary 0 HR 45000.0 1 IT 66000.0 2 Sales 54000.0

as_index=False gives a flat table, handy for merging or plotting.

df.groupby("dept").size()

Result: dept HR 1 IT 2 Sales 2 dtype: int64

size counts rows per group including NaN values; count counts non-null values per column.

Common mistakes

  • Printing df.groupby("dept") shows an object address, not a table: you still need an aggregation like .sum() or .agg().
  • TypeError about non-numeric columns on groupby().sum(): select the numeric columns first, df.groupby("k")[["a", "b"]].sum(), or pass numeric_only=True.
  • Groups with a NaN key silently disappear; pass dropna=False to keep them.

Practice groupby

These drills check your answer on live data, free, no account needed.

  • Total by groupReturn the total `revenue` for each region as a Series indexed by region.
  • Group means as a flat tableReturn the average `units` per product as a DataFrame with two columns, `product` and `units`, and a plain 0, 1, 2 index.
  • Count rows per groupReturn the number of orders each rep has, as a Series indexed by rep in alphabetical order.

Questions

How do I group by two columns?

Pass a list: df.groupby(["dept", "year"])["salary"].sum(). The result has a two-level index; add .reset_index() for a flat table.

How do I apply several aggregations at once?

Use agg: df.groupby("dept")["salary"].agg(["mean", "max", "count"]) or named aggregations: .agg(avg=("salary", "mean"), n=("salary", "size")).

How do I add a group total to every row?

Use transform: df["dept_total"] = df.groupby("dept")["salary"].transform("sum"). It returns a value per original row.

Related

  • aggHow to use agg in pandas to compute several statistics per group, different functions per column, named aggregations with flat column names, and lambdas.
  • transformHow groupby transform works in pandas: broadcast a group sum or mean to each row, share of group total, group-wise normalization, and transform versus agg.
  • pivot_tableHow to build a pivot table in pandas with pivot_table: index, columns, values, aggfunc, fill_value for empty cells, margins for totals, several aggregations.
  • value_countsHow to count values in a pandas column with value_counts: counts sorted by frequency, percentages with normalize=True, including NaN, and two-column combos.

Previous: sort_valuesNext: agg