Data AnalyticsPandas wrangling and data checks

Pandas groupby with missing categories and explicit denominators

PK
Pankit Kumar
Sr. Data Scientist at Parexel (a Goldman Sachs–backed company) · 20 September 2026 · 3 min read
Technically reviewed by Ishaan Sharma
In this article (6 sections)

Use groupby(dropna=False) when missing grouping values must remain visible, and specify what each denominator counts. size counts rows; count counts nonmissing values in a selected column. Those quantities differ whenever the measure is incomplete.

A grouped report should reconcile to the same population as its headline. Otherwise, an unknown region or missing amount can disappear behind a polished percentage.

Reproduce the disappearing category

The pandas quality lab has seven Paid orders with a known subtotal of 57,000 paise. Two orders have no region after enrichment: one matched customer lacks a region, and one customer did not match.

python
from build_and_verify import paid_enriched

paid = paid_enriched()
default_groups = paid.groupby('region')['amount_paise'].sum(min_count=1)
retained_groups = paid.groupby('region', dropna=False, observed=True)['amount_paise'].sum(min_count=1)
assert int(default_groups.sum()) == 50000
assert int(retained_groups.sum()) == 57000
assert int(retained_groups.loc[retained_groups.index.isna()].iloc[0]) == 7000
print(retained_groups)

The default result excludes the missing-region group and loses 7,000 paise from the displayed subtotals. The underlying rows still exist, so the omission can be easy to miss if only the grouped table is inspected.

The groupby reference documents dropna and observed. This article specifies both for clarity and was executed with pandas 3.0.2.

Put denominators beside the measure

python
from build_and_verify import paid_enriched

paid = paid_enriched()
group = paid.groupby('region', dropna=False, observed=True)
summary = group.agg(order_rows=('order_id', 'size'),
                    observed_amounts=('amount_paise', 'count'))
summary['known_subtotal_paise'] = group['amount_paise'].sum(min_count=1)
summary['missing_amounts'] = summary['order_rows'] - summary['observed_amounts']
assert summary.loc['North', 'order_rows'] == 3
assert summary.loc['North', 'observed_amounts'] == 2
assert summary.loc['North', 'known_subtotal_paise'] == 15000
assert summary.loc['North', 'missing_amounts'] == 1
assert int(summary['order_rows'].sum()) == 7
print(summary)

North's known subtotal is 15,000 paise across two observed amounts, with a third order whose amount is unknown. Calling 15,000 the complete North revenue would overstate what the data establishes.

Decide what an average means

Across all seven Paid orders, six amounts are observed. The observed-amount mean is 57,000 / 6 = 9,500 paise. Dividing by all seven orders gives about 8,142.86 paise and implicitly allocates zero to the missing amount.

Neither denominator should be hidden. If the business question requires average value across all Paid orders, the incomplete amount prevents a complete observed answer. Report the available-case mean with coverage, or apply an approved estimation method and label it separately.

Zero-value P04 is observed and belongs in the amount count. Missing-value P08 is not observed. Treating both as false-like values collapses the distinction.

Preserve all-missing groups

sum(min_count=1) prevents an all-missing measure group from automatically becoming zero. It does not make a partially observed subtotal complete. The count and missing-count columns remain necessary even when min_count is set.

If categorical grouping includes possible but unobserved categories, decide whether the report should display them. observed controls category expansion; it does not establish whether an absent category means a true zero or unavailable source coverage.

Reconcile before calculating shares

If reporting each region's share of known observed value, use the same retained population in numerator and denominator and name the measure accordingly. A North share of known value is not necessarily North's share of complete value while one North amount is missing.

Exercise: change every North amount to missing in a copied dataframe. Verify that its row count stays three, observed count becomes zero and its min_count subtotal stays missing. Explain why displaying zero would be misleading.

NeuraPath's Data Analytics with Generative AI course connects pandas aggregation with denominator design. A useful summary makes both the result and its coverage visible.

Continue learning

This article is part of the Pandas wrangling and data checks sequence. Use the neighbouring tasks when you need the prerequisite or the next application.

PK
Pankit Kumar
Lead Instructor, NeuraPath Academy

Pankit Kumar has 10 years in Data Science & AI, building and shipping production systems in regulated pharma and clinical environments. He is a freelance trainer at Boston Institute of Analytics, AnalytixLabs and Scaler, and has taught this material to thousands of working professionals.

This article is part of our Data Analytics with Generative AI programme — 3–4 months. The full analyst stack — Excel, SQL, Power BI and Python pipelines — then a generative-AI layer you can prove is right.

Explore Data Analytics with Generative AI
Counselling is free · no obligation

Not sure which programme fits?

Tell us your background and we will map it to the right entry point — including saying so when a cheaper programme is the better fit. A counsellor replies within one working day.