Repository navigation
Guard weighted incidence calculations against zero totals - #2448
Merged
Merged
Conversation
vahid-ahmadi
left a comment
Collaborator
There was a problem hiding this comment.
Looks right, fine to approve.
@juaristi22, the guard now tests the weighted denominator, which is the one the formula divides by. That is the fix #2296 asked for, and each formula keeps its old fallback. One follow-up point.
- nit,
policyengine_uk/variables/contrib/policyengine/employer_ni/employer_ni_response_capital_incidence.py:31andemployer_ni_response_consumer_incidence.py:30: these two divide by a weighted total with no zero check at all, so the same zero-weight holder givesinforNaNthere when the employer NI response reform is on. They are outside #2296, so a follow-up issue is enough.corporate_land_value.py:16already guards its total.
What I checked
- Read the three changed formulas against the issue's reproduction. Computing
household_weightbefore the check, rather than only when the raw total is non-zero, does not change any result. pytest policyengine_uk/tests/test_weighted_incidence.py: 19 passed. With the three formula changes reversed: 5 failed, 14 passed.ruff checkandruff format --checkon the four changed Python files: clean.- #2363 also edits
shareholding.pyandconsumption_share.py(unit only).git merge-treeshows no conflict. - Reproducer and axiom lines are present;
fixedfragment type is right. CI is green on the current head. I did not run a population calculation.
🤖 Generated with Claude Code
vahid-ahmadi
approved these changes
Oct 18, 2026
vahid-ahmadi
left a comment
Collaborator
There was a problem hiding this comment.
Approving, per my review above. The shoulds and nits can follow.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #2296
A dataset can contain wealth or consumption held only by households with zero weight. The raw total is then positive while the weighted total is zero, causing infinite or NaN shares that propagate into corporate incidence and household tax.
Check the actual weighted denominator in
shareholding,consumption_shareholdingandconsumer_incident_tax_revenue_change. If it is zero, retain each formula's existing fallback. Nonzero weighted normalisation, incidence assumptions and policy parameters are unchanged.Reproducer: policyengine_uk/tests/test_weighted_incidence.py::test_zero_weight_holder_uses_existing_fallback
Validation: five zero-weight-holder assertions failed before the fix. The 19 focused tests now pass, covering all three formulas, corporate incidence and household tax, positive weighted totals, zero-valued inputs and actual dataset-free Core controls. Another 16 existing corporate-land, employer-NI and excise regressions pass.
make format, Ruff andgit diff --checkpass.Tests use synthetic data and literal arithmetic expectations. Local validation used Python3.13 / Core3.32.27 in an existing offline environment; the full suite, locked Core3.33.2 and private population calculations were not run locally.
axiom: n/a: numerical dataset-normalisation guard; statutory provisions and existing incidence-allocation assumptions are unchanged.