Track both count and running sum per category in a single loop, then derive the mean from those two accumulators. With pandas, .agg(['count', 'mean']) applies both aggregations at once and returns a DataFrame with one column per aggregation — avoiding the need to loop twice or store two separate dicts.

By hand

With pandas

df.groupby('cat')['val'].agg(['count', 'mean']) returns a DataFrame indexed by category with count and mean columns. The snapshot shows the columns, index, and each aggregation's values before the final result dict.

naive.py
cats = ['a', 'b', 'a', 'c', 'b', 'a']
vals = [10, 20, 30, 40, 50, 60]
counts = {}
totals = {}
for cat, val in zip(cats, vals):
    counts[cat] = counts.get(cat, 0) + 1
    totals[cat] = totals.get(cat, 0) + val
result = {}
for k in sorted(counts):
    result[k] = (counts[k], round(totals[k] / counts[k], 2))
print('RESULT:', result)
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})
agg = df.groupby('cat')['val'].agg(['count', 'mean'])
result = {
    k: (int(agg.loc[k, 'count']), round(float(agg.loc[k, 'mean']), 2))
    for k in sorted(agg.index)
}
print('columns:', agg.columns.tolist())
print('index:', sorted(agg.index.tolist()))
print('count:', [int(agg.loc[k, 'count']) for k in sorted(agg.index)])
print('mean:', [round(float(agg.loc[k, 'mean']), 2) for k in sorted(agg.index)])
print('RESULT:', result)
columns: ['count', 'mean']
index: ['a', 'b', 'c']
count: [3, 2, 1]
mean: [33.33, 35.0, 40.0]
RESULT: {'a': (3, 33.33), 'b': (2, 35.0), 'c': (1, 40.0)}

Implementation notes

  • .agg(['count', 'mean']) returns a DataFrame (not a Series), because there is more than one aggregation result per group. The columns are the aggregation names; the index is the group keys.
  • Passing a dict to .agg allows renaming and mixing aggregations per column: df.groupby('cat').agg({'val': ['sum', 'mean'], 'score': 'max'}).
  • int() and float() convert numpy scalars to Python natives for stable repr. agg.loc[k, 'count'] is np.int64; agg.loc[k, 'mean'] is np.float64 — both need conversion for a clean RESULT.
  • Cross-reference: group-mean (python-data-basics) for the pure-Python mean-from-accumulators version; groupby-mean (this chapter) for the single-aggregation pandas version.