Skip to content

Consolidate economic impact analysis into shared compute functions #263

Closed

Description

@anth-volk

Problem

The economic impact analysis logic (decile impacts, budget summary, program statistics, poverty, inequality) is currently duplicated between the US and UK analysis.py files, and depends on country-specific string checks scattered throughout the code. This makes it hard to maintain, test, and extend to new countries.

Solution

Introduce shared, country-agnostic compute functions and a CountryConfig frozen dataclass that encapsulates all country-specific parameters:

  • CountryConfig (outputs/country_config.py): Frozen dataclass with US_CONFIG and UK_CONFIG singletons holding income variables, program definitions, budget variables, poverty variables, and inequality settings.
  • BudgetSummaryItem + compute_budget_summary() (outputs/budget_summary.py): Computes baseline/reform/change totals for budget variables using Aggregate.
  • compute_program_statistics() (outputs/program_statistics.py): Computes per-program statistics (totals, counts, winners, losers) using ProgramStatistics/ProgrammeStatistics.
  • compute_decile_impacts() (outputs/decile_impact.py): Computes decile-by-decile impacts from already-run simulations.
  • PolicyReformAnalysis (outputs/policy_reform_analysis.py): Unified result container assembling all analysis outputs.

Each country's analysis.py calls these shared functions with its config, eliminating duplication.

Additional fixes included

  • Fix DecileImpact.run() bare next() → next(..., None) + ValueError (prevents StopIteration crash)
  • Fix Aggregate and ChangeAggregate with same pattern (already done in prior commits)
  • Move inline imports to module top-level in us/analysis.py
  • Improve exception logging in compute_program_statistics with exc_info=True
  • Add model_rebuild() calls for ProgramStatistics, BudgetSummaryItem, and PolicyReformAnalysis
  • Add 11 new tests covering CountryConfig, compute_decile_impacts, DecileImpact error handling, and ChangeAggregate error handling

Activity

  1. MaxGhenis commented on Jul 7, 2026

    @MaxGhenis
    Contributor

    Re-scoping after the PR #260 review: most of the consolidation this issue asked for has happened — both countries' economic_impact_analysis are now thin orchestrators over shared convenience functions in policyengine.outputs (decile impacts, intra-decile, poverty, inequality, LSR, cliffs; see docs/impact-analysis.md "Composing manually").

    The residual duplication is narrow and concrete:

    • _validate_program_statistics_config — us/analysis.py:104 and uk/analysis.py:112, identical except the country word and the US_PROGRAMS/UK_PROGRAMS reference
    • _format_missing_program_variables and the config-error message builders — identical
    • the program-statistics build loop inside each economic_impact_analysis — identical but for the programs dict

    Plan: extract validate_program_statistics_config(programs, baseline, reform, country_label) and build_program_statistics(programs, baseline, reform) into policyengine.outputs.program_statistics, call from both country files. Explicitly NOT adopting a strategy protocol or a unified cross-country result container — the country containers deliberately diverge (UK wealth-decile outputs), which is what overtook PR #260's design.

    Fresh PR to follow shortly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions