Tally how many rows fall into each category by looping over a category list and incrementing a per-key counter. With pandas, df.groupby('cat').size() performs the same split-and-count in one call and returns a Series indexed by the category labels.

By hand

Loop over cats, incrementing counts[cat] for each occurrence using .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']
counts = {}
for cat in cats:
    counts[cat] = counts.get(cat, 0) + 1
result = {k: counts[k] for k in sorted(counts)}
print('RESULT:', result)
  1. cats ← ['a', 'b', 'a', 'c', 'b', 'a']

    1cats = ['a', 'b', 'a', 'c', 'b', 'a']2counts = {}
    values this step['a', 'b', 'a', 'c', 'b', 'a']cats
  2. counts ← {}

    1cats = ['a', 'b', 'a', 'c', 'b', 'a']2counts = {}3for cat in cats:
    values this step{}counts
  3. cat ← 'a'

    2counts = {}3for cat in cats:4    counts[cat] = counts.get(cat, 0) + 1
    values this step'a'cat
  4. counts ← {'a': 1}

    3for cat in cats:4    counts[cat] = counts.get(cat, 0) + 15result = {k: counts[k] for k in sorted(counts)}
    values this step{} {'a': 1}counts
  5. cat ← 'b'

    2counts = {}3for cat in cats:4    counts[cat] = counts.get(cat, 0) + 1
    values this step'a' 'b'cat
  6. counts ← {'a': 1, 'b': 1}

    3for cat in cats:4    counts[cat] = counts.get(cat, 0) + 15result = {k: counts[k] for k in sorted(counts)}
    values this step{'a': 1} {'a': 1, 'b': 1}counts
  7. cat ← 'a'

    2counts = {}3for cat in cats:4    counts[cat] = counts.get(cat, 0) + 1
    values this step'b' 'a'cat
  8. counts ← {'a': 2, 'b': 1}

    3for cat in cats:4    counts[cat] = counts.get(cat, 0) + 15result = {k: counts[k] for k in sorted(counts)}
    values this step{'a': 1, 'b': 1} {'a': 2, 'b': 1}counts
  9. cat ← 'c'

    2counts = {}3for cat in cats:4    counts[cat] = counts.get(cat, 0) + 1
    values this step'a' 'c'cat
  10. counts ← {'a': 2, 'b': 1, 'c': 1}

    3for cat in cats:4    counts[cat] = counts.get(cat, 0) + 15result = {k: counts[k] for k in sorted(counts)}
    values this step{'a': 2, 'b': 1} {'a': 2, 'b': 1, 'c': 1}counts
  11. cat ← 'b'

    2counts = {}3for cat in cats:4    counts[cat] = counts.get(cat, 0) + 1
    values this step'c' 'b'cat
  12. counts ← {'a': 2, 'b': 2, 'c': 1}

    3for cat in cats:4    counts[cat] = counts.get(cat, 0) + 15result = {k: counts[k] for k in sorted(counts)}
    values this step{'a': 2, 'b': 1, 'c': 1} {'a': 2, 'b': 2, 'c': 1}counts
  13. cat ← 'a'

    2counts = {}3for cat in cats:4    counts[cat] = counts.get(cat, 0) + 1
    values this step'b' 'a'cat
  14. counts ← {'a': 3, 'b': 2, 'c': 1}

    3for cat in cats:4    counts[cat] = counts.get(cat, 0) + 15result = {k: counts[k] for k in sorted(counts)}
    values this step{'a': 2, 'b': 2, 'c': 1} {'a': 3, 'b': 2, 'c': 1}counts
  15. for cat in cats:

    2counts = {}3for cat in cats:4    counts[cat] = counts.get(cat, 0) + 1
  16. result ← {'a': 3, 'b': 2, 'c': 1}

    4    counts[cat] = counts.get(cat, 0) + 15result = {k: counts[k] for k in sorted(counts)}6print('RESULT:', result)
    values this step{'a': 3, 'b': 2, 'c': 1}result
  17. stdout ← RESULT: {'a': 3, 'b': 2, 'c': 1}

    5result = {k: counts[k] for k in sorted(counts)}6print('RESULT:', result)
    values this stepRESULT: {'a': 3, 'b': 2, 'c': 1}stdout

With pandas

df.groupby('cat').size() groups the rows by category and returns the row count per group as a Series. 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']
df = pd.DataFrame({'cat': cats})
counts = df.groupby('cat').size()
result = {k: int(counts[k]) for k in sorted(counts.index)}
print('index:', sorted(counts.index.tolist()))
print('values:', [int(counts[k]) for k in sorted(counts.index)])
print('dtype:', counts.dtype)
print('RESULT:', result)
index: ['a', 'b', 'c']
values: [3, 2, 1]
dtype: int64
RESULT: {'a': 3, 'b': 2, 'c': 1}

Implementation notes

  • groupby('cat').size() counts all rows per group, including rows with NaN in other columns. Use .count() instead to count non-null values in a specific column: df.groupby('cat')['val'].count().
  • The result Series is indexed by the group keys in sorted order (pandas sorts group keys by default). This matches the sorted-key dict produced in the naive half.
  • Cross-reference: group-count (python-data-basics) for the pure-Python counter version.