Bump spm-calculator to >=0.2.1 for Betson equivalence scale fix#771
Merged
Bump spm-calculator to >=0.2.1 for Betson equivalence scale fix#771
Conversation
`policyengine_us_data/utils/spm.py` already consumes `spm-calculator` for base thresholds and the equivalence scale, but the dependency range was pinned at `>=0.1.0` so the lockfile resolved to `spm-calculator==0.1.0` -- which shipped a buggy linear OECD-modified equivalence scale (reference family raw = 2.1) instead of the Betson three-parameter scale with the 0.7 exponent (reference family raw = 3**0.7 approx 2.158) that BLS Garner (2021) documents and that Census uses in its published SPM thresholds. Version 0.2.0 of `spm-calculator` replaced the scale with the correct Betson form; 0.2.1 then tightened the (shadow) CE recomputation path toward BLS methodology (annualization, survey weights, mortgage principal, internet services, modern CUTENURE split). Bumping to `>=0.2.1` picks up both. Impact on computed SPM thresholds (CPS input pipeline, unchanged code, dependency bump only) - 2 adult / 2 child reference family: unchanged (normalization anchor). - 1 adult / 2 child owner-with-mortgage: $29,767 -> $32,437 (+9.0%). - 2 adult / 0 child owner-with-mortgage: $27,906 -> $25,530 (-8.5%). - Direction: single-parent-with-children units shift higher, larger childless-adult units shift lower -- matching the well-known Betson economies-of-scale properties. This changes the SPM thresholds that `cps.py` writes onto the CPS input dataset, which feeds every downstream SPM-based calibration target and poverty classification. The update is a correctness fix, not a policy change. Validation - All 714 unit tests pass (`uv run pytest tests/unit/`). - `calculate_spm_thresholds_with_geoadj` output verified by hand against Betson math for 1A2C / 2A2C / 2A0C at owner-with-mortgage. - Public API of `policyengine_us_data/utils/spm.py` unchanged across the version bump; no call-site updates required in `cps.py` or `calibration_utils.py`. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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.
Summary
policyengine_us_data/utils/spm.pyalready delegates to thespm-calculatorpackage for base thresholds and the equivalence scale, but the dependency constraint was pinned at>=0.1.0souv syncresolved tospm-calculator==0.1.0— the version that shipped a buggy linear OECD-modified equivalence scale (reference 2A2C raw = 2.1). Census SPM actually uses the Betson three-parameter scale with the 0.7 exponent (reference 2A2C raw =3**0.7≈ 2.158). This mismatch silently produced the wrong SPM threshold for every non-2A2C family on the CPS input dataset.spm-calculatorv0.2.0 (merged and published earlier today) replaced the scale with the correct Betson form; v0.2.1 tightened the shadow CE-recomputation path toward BLS methodology (annualization, survey weights, mortgage principal, internet services, modern CUTENURE split). This PR bumps the floor to>=0.2.1, refreshesuv.lock, and adds a changelog fragment. No code changes inutils/spm.py— the package-level API (SPMCalculator,spm_equivalence_scale) is backward-compatible across the bump.Impact on computed SPM thresholds
CPS input dataset, unchanged code, dependency bump only. All examples at
geoadj=1.0,owner_with_mortgage, 2024.Single-parent-with-children units shift higher, larger childless-adult units shift lower — the well-known Betson economies-of-scale properties. This changes the SPM thresholds that
cps.pywrites onto the CPS input dataset, which feeds every downstream SPM-based calibration target and poverty classification. It's a correctness fix, not a policy change.Test plan
uv run pytest tests/unit/→ 714 passed, 10 skippedcalculate_spm_thresholds_with_geoadjagainst Betson math by hand for 1A2C / 2A2C / 2A0C at owner-with-mortgagemake formaton Python passes (ruff clean)policyengine_us_data/changed)Related
PolicyEngine/spm-calculator#5(v0.2.0, Betson scale + tenure-specific GEOADJ) and#6(v0.2.1, CE-path BLS fidelity) — both merged and published to PyPI.PolicyEngine/policyengine-us#8020migratesspm_unit_spm_thresholdto a formula usingspm-calculator>=0.2.0for base thresholds + Betson scale, preserving the per-unit geographic adjustment from the stored dataset.#702(still draft) is orthogonal to this dep bump and can land independently.🤖 Generated with Claude Code