GroupBy
GroupBy Sum
Accumulate a running total per category by looping over paired category and
value lists. With pandas, df.groupby('cat')['val'].sum() splits the rows by
category, applies sum to the value column of each group, and combines the
results — the split-apply-combine pattern in one call.
By hand
Loop over zip(cats, vals), accumulating into totals[cat] with .get(cat, 0)
to handle first-time keys. Sort the keys for a stable result.
naive.py
Replay: real traced execution (multi-file project)
cats = ['a', 'b', 'a', 'c', 'b', 'a']
vals = [10, 20, 30, 40, 50, 60]
totals = {}
for cat, val in zip(cats, vals):
totals[cat] = totals.get(cat, 0) + val
result = {k: totals[k] for k in sorted(totals)}
print('RESULT:', result)
cats ← ['a', 'b', 'a', 'c', 'b', 'a']
1cats = ['a', 'b', 'a', 'c', 'b', 'a']2vals = [10, 20, 30, 40, 50, 60]values this step['a', 'b', 'a', 'c', 'b', 'a']catsvals ← [10, 20, 30, 40, 50, 60]
1cats = ['a', 'b', 'a', 'c', 'b', 'a']2vals = [10, 20, 30, 40, 50, 60]3totals = {}values this step[10, 20, 30, 40, 50, 60]valstotals ← {}
2vals = [10, 20, 30, 40, 50, 60]3totals = {}4for cat, val in zip(cats, vals):values this step{}totalscat ← 'a', val ← 10
3totals = {}4for cat, val in zip(cats, vals):5 totals[cat] = totals.get(cat, 0) + valvalues this step'a'cat10valtotals ← {'a': 10}
4for cat, val in zip(cats, vals):5 totals[cat] = totals.get(cat, 0) + val6result = {k: totals[k] for k in sorted(totals)}values this step{} → {'a': 10}totalscat ← 'b', val ← 20
3totals = {}4for cat, val in zip(cats, vals):5 totals[cat] = totals.get(cat, 0) + valvalues this step'a' → 'b'cat10 → 20valtotals ← {'a': 10, 'b': 20}
4for cat, val in zip(cats, vals):5 totals[cat] = totals.get(cat, 0) + val6result = {k: totals[k] for k in sorted(totals)}values this step{'a': 10} → {'a': 10, 'b': 20}totalscat ← 'a', val ← 30
3totals = {}4for cat, val in zip(cats, vals):5 totals[cat] = totals.get(cat, 0) + valvalues this step'b' → 'a'cat20 → 30valtotals ← {'a': 40, 'b': 20}
4for cat, val in zip(cats, vals):5 totals[cat] = totals.get(cat, 0) + val6result = {k: totals[k] for k in sorted(totals)}values this step{'a': 10, 'b': 20} → {'a': 40, 'b': 20}totalscat ← 'c', val ← 40
3totals = {}4for cat, val in zip(cats, vals):5 totals[cat] = totals.get(cat, 0) + valvalues this step'a' → 'c'cat30 → 40valtotals ← {'a': 40, 'b': 20, 'c': 40}
4for cat, val in zip(cats, vals):5 totals[cat] = totals.get(cat, 0) + val6result = {k: totals[k] for k in sorted(totals)}values this step{'a': 40, 'b': 20} → {'a': 40, 'b': 20, 'c': 40}totalscat ← 'b', val ← 50
3totals = {}4for cat, val in zip(cats, vals):5 totals[cat] = totals.get(cat, 0) + valvalues this step'c' → 'b'cat40 → 50valtotals ← {'a': 40, 'b': 70, 'c': 40}
4for cat, val in zip(cats, vals):5 totals[cat] = totals.get(cat, 0) + val6result = {k: totals[k] for k in sorted(totals)}values this step{'a': 40, 'b': 20, 'c': 40} → {'a': 40, 'b': 70, 'c': 40}totalscat ← 'a', val ← 60
3totals = {}4for cat, val in zip(cats, vals):5 totals[cat] = totals.get(cat, 0) + valvalues this step'b' → 'a'cat50 → 60valtotals ← {'a': 100, 'b': 70, 'c': 40}
4for cat, val in zip(cats, vals):5 totals[cat] = totals.get(cat, 0) + val6result = {k: totals[k] for k in sorted(totals)}values this step{'a': 40, 'b': 70, 'c': 40} → {'a': 100, 'b': 70, 'c': 40}totalsfor cat, val in zip(cats, vals):
3totals = {}4for cat, val in zip(cats, vals):5 totals[cat] = totals.get(cat, 0) + valresult ← {'a': 100, 'b': 70, 'c': 40}
5 totals[cat] = totals.get(cat, 0) + val6result = {k: totals[k] for k in sorted(totals)}7print('RESULT:', result)values this step{'a': 100, 'b': 70, 'c': 40}resultstdout ← RESULT: {'a': 100, 'b': 70, 'c': 40}
6result = {k: totals[k] for k in sorted(totals)}7print('RESULT:', result)values this stepRESULT: {'a': 100, 'b': 70, 'c': 40}stdout
With pandas
df.groupby('cat')['val'].sum() groups by category, selects the val column,
and sums each group. int() converts numpy scalars for a stable result dict.
library.py
import pandas as pd
from dalib.display import set_display
set_display()
cats = ['a', 'b', 'a', 'c', 'b', 'a']
vals = [10, 20, 30, 40, 50, 60]
df = pd.DataFrame({'cat': cats, 'val': vals})
sums = df.groupby('cat')['val'].sum()
result = {k: int(sums[k]) for k in sorted(sums.index)}
print('index:', sorted(sums.index.tolist()))
print('values:', [int(sums[k]) for k in sorted(sums.index)])
print('dtype:', sums.dtype)
print('RESULT:', result)
index: ['a', 'b', 'c']
values: [100, 70, 40]
dtype: int64
RESULT: {'a': 100, 'b': 70, 'c': 40}
Implementation notes
groupby('cat')['val']selects a single column from the grouped object before aggregating. Without the column selection,.sum()would sum every numeric column in the DataFrame.- The three-step pattern —
groupby(split) → column select → aggregation (apply) → result Series (combine) — is the core of split-apply-combine and applies to all aggregations:sum,mean,min,max,std. - Cross-reference:
group-sum(python-data-basics) for the pure-Python accumulator version;groupby-mean(this chapter) for the mean variant.