From 64b48d4f92bcec7f02b7e7a564fe47bd01902f17 Mon Sep 17 00:00:00 2001 From: Anthony Volk <14987227+anth-volk@users.noreply.github.com> Date: Thu, 22 Oct 2026 18:21:04 +0400 Subject: [PATCH 01/14] Store economy results as rows and rebuild them exactly Revision 0004 adds a table for each section of today's economy result model, SingleYearMacroOutput. A simulation's own figures belong to its simulation run (poverty_rates, inequality, cliff_impacts), so a reused current-law baseline keeps them once; the comparison belongs to the report run (budget_impacts, program_budget_impacts, decile_impacts and intra_decile_impacts for income and wealth, labor_supply_responses, labor_supply_decile_impacts, congressional_district_impacts, constituency_impacts, local_authority_impacts). Lists and maps keep their order in a position column. The report run gains result_sections (the optional sections its result holds, so null and an empty list stay distinct) and spm_provenance. write_economy_comparison writes a result's rows in the caller's transaction; with RunTransitions.complete_comparison that is the transaction marking the comparison step succeeded. check_storable first refuses a result the tables cannot hold exactly (decile maps naming different deciles, an empty share list, records of the wrong kind), and EconomyComparisonRecorder pairs it with validation against the result model for the recording loop. read_economy_comparison rebuilds the result from the rows plus labels the region catalog supplies: the model and data versions of the run's catalog version, and constituency and local-authority names and map positions by code. A round-trip test writes and reads back a fixed sample of eight results (US national, state and congressional district; UK national, nation, constituency and local authority; a budget-window year) and requires the same JSON, byte for byte. The sample is generated, sized like production results with values of varied sign and magnitude, because stored real results could not be read without starting new production calculations; an exported real result can replace any file. The persistence library now depends on the contract library for the result models. Co-Authored-By: Claude Opus 5.5 --- .../README.md | 21 + .../pyproject.toml | 6 + .../__init__.py | 16 + .../economy_results.py | 745 ++ .../result_tables.py | 290 + .../runs.py | 9 + .../schema.py | 2 +- .../economy_results/uk_constituency_2026.json | 304 + .../uk_local_authority_2026.json | 314 + .../uk_nation_scotland_2026.json | 1107 ++ .../economy_results/uk_national_2026.json | 9466 +++++++++++++++++ .../us_budget_window_year_2030.json | 243 + .../us_congressional_district_ca_12_2026.json | 301 + .../economy_results/us_national_2026.json | 4295 ++++++++ .../economy_results/us_state_ca_2026.json | 760 ++ .../tests/result_support.py | 111 + .../tests/test_economy_results.py | 163 + .../tests/test_schema.py | 3 + .../uv.lock | 666 ++ .../versions/0004_economy_result_tables.py | 383 + .../policyengine-simulation-entry/uv.lock | 2 + 21 files changed, 19206 insertions(+), 1 deletion(-) create mode 100644 libs/policyengine-simulation-persistence/src/policyengine_simulation_persistence/economy_results.py create mode 100644 libs/policyengine-simulation-persistence/src/policyengine_simulation_persistence/result_tables.py create mode 100644 libs/policyengine-simulation-persistence/tests/fixtures/economy_results/uk_constituency_2026.json create mode 100644 libs/policyengine-simulation-persistence/tests/fixtures/economy_results/uk_local_authority_2026.json create mode 100644 libs/policyengine-simulation-persistence/tests/fixtures/economy_results/uk_nation_scotland_2026.json create mode 100644 libs/policyengine-simulation-persistence/tests/fixtures/economy_results/uk_national_2026.json create mode 100644 libs/policyengine-simulation-persistence/tests/fixtures/economy_results/us_budget_window_year_2030.json create mode 100644 libs/policyengine-simulation-persistence/tests/fixtures/economy_results/us_congressional_district_ca_12_2026.json create mode 100644 libs/policyengine-simulation-persistence/tests/fixtures/economy_results/us_national_2026.json create mode 100644 libs/policyengine-simulation-persistence/tests/fixtures/economy_results/us_state_ca_2026.json create mode 100644 libs/policyengine-simulation-persistence/tests/result_support.py create mode 100644 libs/policyengine-simulation-persistence/tests/test_economy_results.py create mode 100644 migrations/versions/0004_economy_result_tables.py diff --git a/libs/policyengine-simulation-persistence/README.md b/libs/policyengine-simulation-persistence/README.md index faeff7e29..69bf2f3a6 100644 --- a/libs/policyengine-simulation-persistence/README.md +++ b/libs/policyengine-simulation-persistence/README.md @@ -63,6 +63,27 @@ steps whose simulation run failed) are failed so the work can be submitted again. A comparison step can start only once both of its simulation runs have succeeded; starting it is left to the stage 2 report path. +### Results + +Every economy result is stored as rows (`result_tables`), one table per +section of today's result model, `SingleYearMacroOutput`: + +| Belongs to | Tables | +| --- | --- | +| A simulation run (its own figures, kept once when the run is reused) | `poverty_rates`, `inequality`, `cliff_impacts` | +| A report run (the comparison) | `budget_impacts`, `program_budget_impacts`, `decile_impacts` (income and wealth), `intra_decile_impacts` (income and wealth), `labor_supply_responses`, `labor_supply_decile_impacts`, `congressional_district_impacts`, `constituency_impacts`, `local_authority_impacts` | + +Lists and maps keep their order in a `position` column. The report run also +records which optional sections its result holds (`result_sections`) and its +SPM provenance. `write_economy_comparison` checks the result can be held +exactly (`check_storable`) and writes its rows in the transaction that marks +the comparison step succeeded (`RunTransitions.complete_comparison`); +`EconomyComparisonRecorder` pairs that writer with validation against the +result model. `read_economy_comparison` rebuilds the result exactly from the +rows and from labels the region catalog supplies (`EconomyResultLabels`): the +model and data versions of the run's catalog version, and constituency and +local-authority names and map positions by code. + ## Ownership rules These rules are registered in `rules/registry.toml` and checked by diff --git a/libs/policyengine-simulation-persistence/pyproject.toml b/libs/policyengine-simulation-persistence/pyproject.toml index 28ab475b5..cf04f772f 100644 --- a/libs/policyengine-simulation-persistence/pyproject.toml +++ b/libs/policyengine-simulation-persistence/pyproject.toml @@ -8,6 +8,8 @@ authors = [ license = {file = "../../LICENSE"} requires-python = ">=3.13,<3.14" dependencies = [ + # The result models the result tables store and rebuild. + "policyengine-simulation-contract", "psycopg[binary]>=3.2,<4", "sqlalchemy>=2,<3", ] @@ -28,6 +30,10 @@ build = [ "pyright>=1.1.401", ] +[tool.uv.sources] +policyengine-simulation-contract = { path = "../policyengine-simulation-contract", editable = true } +policyengine-simulation-observability = { path = "../policyengine-simulation-observability", editable = true } + [build-system] requires = ["hatchling>=1.26"] build-backend = "hatchling.build" diff --git a/libs/policyengine-simulation-persistence/src/policyengine_simulation_persistence/__init__.py b/libs/policyengine-simulation-persistence/src/policyengine_simulation_persistence/__init__.py index be715f3e5..81f846794 100644 --- a/libs/policyengine-simulation-persistence/src/policyengine_simulation_persistence/__init__.py +++ b/libs/policyengine-simulation-persistence/src/policyengine_simulation_persistence/__init__.py @@ -4,6 +4,15 @@ the migration environment compares with the database. """ +from policyengine_simulation_persistence.economy_results import ( + OPTIONAL_SECTIONS, + EconomyComparisonRecorder, + EconomyResultLabels, + GeographyLabel, + check_storable, + read_economy_comparison, + write_economy_comparison, +) from policyengine_simulation_persistence.engine import ( create_simulation_engine, normalized_database_url, @@ -52,11 +61,15 @@ __all__ = [ "ALEMBIC_VERSION_TABLE", "HEAD_REVISION", + "OPTIONAL_SECTIONS", "RUNTIME_ROLE", "SIMULATION_SCHEMA", "SUCCEEDED_RUN_REUSE_WINDOW", "AbandonedDispatches", "DueSimulationCall", + "EconomyComparisonRecorder", + "EconomyResultLabels", + "GeographyLabel", "NewReport", "NewReportRun", "NewSimulation", @@ -76,8 +89,11 @@ "SimulationRunRecord", "SimulationStore", "StartedSimulationRun", + "check_storable", "create_simulation_engine", "normalized_database_url", + "read_economy_comparison", "read_schema_revision", "simulation_metadata", + "write_economy_comparison", ] diff --git a/libs/policyengine-simulation-persistence/src/policyengine_simulation_persistence/economy_results.py b/libs/policyengine-simulation-persistence/src/policyengine_simulation_persistence/economy_results.py new file mode 100644 index 000000000..be92198e4 --- /dev/null +++ b/libs/policyengine-simulation-persistence/src/policyengine_simulation_persistence/economy_results.py @@ -0,0 +1,745 @@ +"""Write an economy comparison's result as rows, and rebuild it from them. + +``write_economy_comparison`` runs in the transaction that marks a report run's +comparison step succeeded (``RunTransitions.complete_comparison``), so a run +never succeeds without its rows. ``read_economy_comparison`` rebuilds today's +result format, ``SingleYearMacroOutput``, from the rows and from labels the +region catalog supplies: the model and data versions of the run's catalog +version, and the names and map positions of constituencies and local +authorities by code. + +A result the tables cannot hold exactly is refused before any write by +``check_storable``: the average and relative changes of each decile map must +name the same deciles in the same order, each decile's category share list +must hold at least one value, and the constituency and local-authority lists +must hold records of their own kind. +""" + +from __future__ import annotations + +from dataclasses import dataclass, field +from typing import TYPE_CHECKING, Any + +from policyengine_simulation_contract.macro_output import ( + ConstituencyImpactRecord, + DecileOutput, + IntraDecileOutput, + LaborSupplyResponseOutput, + LocalAuthorityImpactRecord, + SingleYearMacroOutput, +) +from sqlalchemy import select, update +from sqlalchemy.dialects.postgresql import insert as postgres_insert + +from policyengine_simulation_persistence.result_tables import ( + budget_impacts, + cliff_impacts, + congressional_district_impacts, + constituency_impacts, + decile_impacts, + inequality, + intra_decile_impacts, + labor_supply_decile_impacts, + labor_supply_responses, + local_authority_impacts, + poverty_rates, + program_budget_impacts, +) +from policyengine_simulation_persistence.runs import ( + ReportRunRecord, + RunStatus, + report_runs, +) + +if TYPE_CHECKING: + from collections.abc import Mapping, Sequence + from uuid import UUID + + from sqlalchemy import Connection, RowMapping, Table + +# The sections a result may leave null. Which of them a stored result holds is +# recorded on its report run, so a reader returns null exactly where the +# writer received null, including for empty lists. +OPTIONAL_SECTIONS = ( + "poverty_by_race", + "wealth_decile", + "intra_wealth_decile", + "labor_supply_response", + "constituency_impact", + "local_authority_impact", + "congressional_district_impact", + "cliff_impact", +) +SIDES = ("baseline", "reform") + + +@dataclass(frozen=True) +class GeographyLabel: + """A constituency's or local authority's name and map position.""" + + name: str + x: int | None + y: int | None + + +@dataclass(frozen=True) +class EconomyResultLabels: + """What a stored result takes from the region catalog when it is read. + + The model and data versions belong to the run's catalog version; the + geography labels are looked up by code. + """ + + model_version: str + data_version: str + constituencies: Mapping[str, GeographyLabel] = field(default_factory=dict) + local_authorities: Mapping[str, GeographyLabel] = field(default_factory=dict) + + +# --- Checks before writing ------------------------------------------------ + + +def _check_decile_maps(name: str, decile: DecileOutput | None) -> None: + if decile is not None and list(decile.average) != list(decile.relative): + msg = f"{name}: average and relative must name the same deciles in order" + raise ValueError(msg) + + +def _check_intra_decile(name: str, intra: IntraDecileOutput | None) -> None: + if intra is not None and any(not shares for shares in intra.deciles.values()): + msg = f"{name}: every category needs at least one decile share" + raise ValueError(msg) + + +def _check_labor_supply(labor: LaborSupplyResponseOutput | None) -> None: + if labor is None: + return + metrics = labor.decile + orders = { + tuple(values) + for values in ( + metrics.average.income, + metrics.average.substitution, + metrics.relative.income, + metrics.relative.substitution, + ) + } + if len(orders) > 1: + msg = "labor_supply_response.decile: every map must name the same deciles" + raise ValueError(msg) + + +def check_storable(result: SingleYearMacroOutput) -> SingleYearMacroOutput: + """Return ``result`` if the tables can hold it exactly; else raise ValueError.""" + _check_decile_maps("decile", result.decile) + _check_decile_maps("wealth_decile", result.wealth_decile) + _check_intra_decile("intra_decile", result.intra_decile) + _check_intra_decile("intra_wealth_decile", result.intra_wealth_decile) + _check_labor_supply(result.labor_supply_response) + for section, record_type in ( + ("constituency_impact", ConstituencyImpactRecord), + ("local_authority_impact", LocalAuthorityImpactRecord), + ): + records = getattr(result, section) + if records is not None and not all( + isinstance(record, record_type) for record in records.root + ): + msg = f"{section} must hold only {record_type.__name__} records" + raise ValueError(msg) + return result + + +# --- Writing ---------------------------------------------------------------- + + +def _insert(connection: Connection, table: Table, rows: list[dict[str, Any]]) -> None: + if rows: + connection.execute(postgres_insert(table), rows) + + +def _insert_once( + connection: Connection, table: Table, rows: list[dict[str, Any]] +) -> None: + """Insert one simulation run's rows unless an earlier comparison wrote them. + + A reused simulation run, most often a current-law baseline, takes part in + many comparisons; its own figures are the same in each. + """ + if rows: + connection.execute(postgres_insert(table).on_conflict_do_nothing(), rows) + + +def _simulation_rows( + result: SingleYearMacroOutput, side: str, run_id: UUID +) -> dict[Table, list[dict[str, Any]]]: + poverty = [] + groups = [ + ("age", result.poverty.poverty, "poverty"), + ("age", result.poverty.deep_poverty, "deep_poverty"), + ("gender", result.poverty_by_gender.poverty, "poverty"), + ("gender", result.poverty_by_gender.deep_poverty, "deep_poverty"), + ] + if result.poverty_by_race is not None: + groups.append(("race", result.poverty_by_race.poverty, "poverty")) + for dimension, rates, measure in groups: + poverty.extend( + { + "simulation_run_id": run_id, + "measure": measure, + "group_dimension": dimension, + "group_value": group, + "rate": getattr(value, side), + } + for group, value in rates + ) + rows: dict[Table, list[dict[str, Any]]] = { + poverty_rates: poverty, + inequality: [ + { + "simulation_run_id": run_id, + **{name: getattr(value, side) for name, value in result.inequality}, + } + ], + } + if result.cliff_impact is not None: + cliff = getattr(result.cliff_impact, side) + rows[cliff_impacts] = [{"simulation_run_id": run_id, **cliff.model_dump()}] + return rows + + +def _decile_rows( + report_run_id: UUID, measure: str, decile: DecileOutput | None +) -> list[dict[str, Any]]: + if decile is None: + return [] + return [ + { + "report_run_id": report_run_id, + "measure": measure, + "decile": key, + "position": position, + "average_change": decile.average[key], + "relative_change": decile.relative[key], + } + for position, key in enumerate(decile.average) + ] + + +def _intra_decile_rows( + report_run_id: UUID, measure: str, intra: IntraDecileOutput | None +) -> list[dict[str, Any]]: + if intra is None: + return [] + rows = [ + { + "report_run_id": report_run_id, + "measure": measure, + "outcome": outcome, + "outcome_position": position, + "decile": index, + "share": share, + } + for position, (outcome, shares) in enumerate(intra.deciles.items()) + for index, share in enumerate(shares, start=1) + ] + rows.extend( + { + "report_run_id": report_run_id, + "measure": measure, + "outcome": outcome, + "outcome_position": position, + "decile": None, + "share": share, + } + for position, (outcome, share) in enumerate(intra.all.items()) + ) + return rows + + +def _labor_supply_rows( + report_run_id: UUID, labor: LaborSupplyResponseOutput | None +) -> dict[Table, list[dict[str, Any]]]: + if labor is None: + return {} + decile = labor.decile + return { + labor_supply_responses: [ + { + "report_run_id": report_run_id, + "substitution_lsr": labor.substitution_lsr, + "income_lsr": labor.income_lsr, + "relative_income_response": labor.relative_lsr.income, + "relative_substitution_response": labor.relative_lsr.substitution, + "total_change": labor.total_change, + "revenue_change": labor.revenue_change, + "baseline_hours": labor.hours.baseline, + "reform_hours": labor.hours.reform, + "hours_change": labor.hours.change, + "hours_income_effect": labor.hours.income_effect, + "hours_substitution_effect": labor.hours.substitution_effect, + } + ], + labor_supply_decile_impacts: [ + { + "report_run_id": report_run_id, + "decile": key, + "position": position, + "average_income_effect": decile.average.income[key], + "average_substitution_effect": decile.average.substitution[key], + "relative_income_effect": decile.relative.income[key], + "relative_substitution_effect": decile.relative.substitution[key], + } + for position, key in enumerate(decile.average.income) + ], + } + + +def _geography_rows( + report_run_id: UUID, result: SingleYearMacroOutput +) -> dict[Table, list[dict[str, Any]]]: + rows: dict[Table, list[dict[str, Any]]] = {} + if result.congressional_district_impact is not None: + rows[congressional_district_impacts] = [ + { + "report_run_id": report_run_id, + "position": position, + **record.model_dump(), + } + for position, record in enumerate( + result.congressional_district_impact.districts + ) + ] + for section, table, code_field in ( + ("constituency_impact", constituency_impacts, "constituency_code"), + ("local_authority_impact", local_authority_impacts, "local_authority_code"), + ): + records = getattr(result, section) + if records is None: + continue + rows[table] = [ + { + "report_run_id": report_run_id, + "position": position, + code_field: getattr(record, code_field), + "average_household_income_change": ( + record.average_household_income_change + ), + "relative_household_income_change": ( + record.relative_household_income_change + ), + "population": record.population, + } + for position, record in enumerate(records.root) + ] + return rows + + +def _comparison_rows( + report_run_id: UUID, result: SingleYearMacroOutput +) -> dict[Table, list[dict[str, Any]]]: + return { + budget_impacts: [ + {"report_run_id": report_run_id, **result.budget.model_dump()} + ], + program_budget_impacts: [ + { + "report_run_id": report_run_id, + "program": program, + "position": position, + **totals.model_dump(), + } + for position, (program, totals) in enumerate( + result.detailed_budget.root.items() + ) + ], + decile_impacts: [ + *_decile_rows(report_run_id, "income", result.decile), + *_decile_rows(report_run_id, "wealth", result.wealth_decile), + ], + intra_decile_impacts: [ + *_intra_decile_rows(report_run_id, "income", result.intra_decile), + *_intra_decile_rows(report_run_id, "wealth", result.intra_wealth_decile), + ], + **_labor_supply_rows(report_run_id, result.labor_supply_response), + **_geography_rows(report_run_id, result), + } + + +def write_economy_comparison( + connection: Connection, + report_run: ReportRunRecord, + result: SingleYearMacroOutput, +) -> None: + """Write an economy report run's result rows in the caller's transaction. + + The figures of each simulation go to its simulation run, the comparison to + the report run, and the SPM provenance and the optional sections the + result holds to the report run's own columns. + """ + check_storable(result) + if report_run.reform_simulation_run_id is None: + msg = "an economy comparison needs a reform simulation run" + raise ValueError(msg) + run_ids = ( + report_run.baseline_simulation_run_id, + report_run.reform_simulation_run_id, + ) + for side, run_id in zip(SIDES, run_ids, strict=True): + for table, rows in _simulation_rows(result, side, run_id).items(): + _insert_once(connection, table, rows) + for table, rows in _comparison_rows(report_run.id, result).items(): + _insert(connection, table, rows) + connection.execute( + update(report_runs) + .where(report_runs.c.id == report_run.id) + .values( + result_sections=[ + section + for section in OPTIONAL_SECTIONS + if getattr(result, section) is not None + ], + spm_provenance=( + None + if result.spm_provenance is None + else result.spm_provenance.model_dump(mode="json") + ), + ) + ) + + +@dataclass(frozen=True) +class EconomyComparisonRecorder: + """Validate a comparison's output and write it, for the recording loop.""" + + def validate(self, output: object) -> SingleYearMacroOutput: + """Return the output as a result the tables can hold; else raise ValueError.""" + return check_storable(SingleYearMacroOutput.model_validate(output)) + + def write( + self, connection: Connection, report_run: ReportRunRecord, result: object + ) -> None: + """Write the validated result's rows in the caller's transaction.""" + if not isinstance(result, SingleYearMacroOutput): + msg = "the comparison recorder writes only validated economy results" + raise TypeError(msg) + write_economy_comparison(connection, report_run, result) + + +# --- Reading ---------------------------------------------------------------- + + +def _rows( + connection: Connection, + table: Table, + key_column: str, + key: UUID, + order: Sequence[str] = (), +) -> list[RowMapping]: + statement = select(table).where(table.c[key_column] == key) + if order: + statement = statement.order_by(*(table.c[name] for name in order)) + return list(connection.execute(statement).mappings()) + + +def _one( + connection: Connection, table: Table, key_column: str, key: UUID +) -> RowMapping: + rows = _rows(connection, table, key_column, key) + if len(rows) != 1: + msg = f"{table.name} has no row for {key}" + raise LookupError(msg) + return rows[0] + + +def _poverty(rows_by_side: dict[str, list[RowMapping]]) -> dict[str, Any]: + sections: dict[tuple[str, str], dict[str, dict[str, float]]] = {} + for side, side_rows in rows_by_side.items(): + for row in side_rows: + group = sections.setdefault((row["group_dimension"], row["measure"]), {}) + group.setdefault(row["group_value"], {})[side] = row["rate"] + return { + "poverty": { + "poverty": sections[("age", "poverty")], + "deep_poverty": sections[("age", "deep_poverty")], + }, + "poverty_by_gender": { + "poverty": sections[("gender", "poverty")], + "deep_poverty": sections[("gender", "deep_poverty")], + }, + "poverty_by_race": ( + {"poverty": sections[("race", "poverty")]} + if ("race", "poverty") in sections + else None + ), + } + + +def _simulation_sections( + connection: Connection, run_ids: tuple[UUID, UUID], sections: set[str] +) -> dict[str, Any]: + by_side = { + side: _rows(connection, poverty_rates, "simulation_run_id", run_id) + for side, run_id in zip(SIDES, run_ids, strict=True) + } + payload = _poverty(by_side) + if "poverty_by_race" not in sections: + payload["poverty_by_race"] = None + inequality_rows = [ + _one(connection, inequality, "simulation_run_id", run_id) for run_id in run_ids + ] + payload["inequality"] = { + name: { + side: row[name] for side, row in zip(SIDES, inequality_rows, strict=True) + } + for name in ("gini", "top_10_pct_share", "top_1_pct_share") + } + payload["cliff_impact"] = ( + { + side: {name: row[name] for name in ("cliff_gap", "cliff_share")} + for side, row in zip( + SIDES, + ( + _one(connection, cliff_impacts, "simulation_run_id", run_id) + for run_id in run_ids + ), + strict=True, + ) + } + if "cliff_impact" in sections + else None + ) + return payload + + +def _deciles( + rows: list[RowMapping], measure: str +) -> dict[str, dict[str, float]] | None: + measured = [row for row in rows if row["measure"] == measure] + if not measured: + return None + return { + "average": {row["decile"]: row["average_change"] for row in measured}, + "relative": {row["decile"]: row["relative_change"] for row in measured}, + } + + +def _intra_deciles(rows: list[RowMapping], measure: str) -> dict[str, Any]: + measured = [row for row in rows if row["measure"] == measure] + deciles: dict[str, list[float]] = {} + for row in sorted( + (row for row in measured if row["decile"] is not None), + key=lambda row: (row["outcome_position"], row["decile"]), + ): + deciles.setdefault(row["outcome"], []).append(row["share"]) + return { + "deciles": deciles, + "all": { + row["outcome"]: row["share"] + for row in sorted( + (row for row in measured if row["decile"] is None), + key=lambda row: row["outcome_position"], + ) + }, + } + + +def _labor_supply(connection: Connection, report_run_id: UUID) -> dict[str, Any]: + response = _one(connection, labor_supply_responses, "report_run_id", report_run_id) + deciles = _rows( + connection, + labor_supply_decile_impacts, + "report_run_id", + report_run_id, + order=("position",), + ) + return { + "substitution_lsr": response["substitution_lsr"], + "income_lsr": response["income_lsr"], + "relative_lsr": { + "income": response["relative_income_response"], + "substitution": response["relative_substitution_response"], + }, + "total_change": response["total_change"], + "revenue_change": response["revenue_change"], + "decile": { + statistic: { + effect: { + row["decile"]: row[f"{statistic}_{effect}_effect"] + for row in deciles + } + for effect in ("income", "substitution") + } + for statistic in ("average", "relative") + }, + "hours": { + "baseline": response["baseline_hours"], + "reform": response["reform_hours"], + "change": response["hours_change"], + "income_effect": response["hours_income_effect"], + "substitution_effect": response["hours_substitution_effect"], + }, + } + + +def _labelled_geographies( + rows: list[RowMapping], code_field: str, name_field: str, labels: Mapping +) -> list[dict[str, Any]]: + records = [] + for row in rows: + code = row[code_field] + label = labels.get(code) + if label is None: + msg = f"the region catalog has no label for {code}" + raise LookupError(msg) + records.append( + { + code_field: code, + name_field: label.name, + "x": label.x, + "y": label.y, + "average_household_income_change": row[ + "average_household_income_change" + ], + "relative_household_income_change": row[ + "relative_household_income_change" + ], + "population": row["population"], + } + ) + return records + + +def _geography_sections( + connection: Connection, + report_run_id: UUID, + sections: set[str], + labels: EconomyResultLabels, +) -> dict[str, Any]: + def ordered(table: Table) -> list[RowMapping]: + return _rows( + connection, table, "report_run_id", report_run_id, order=("position",) + ) + + payload: dict[str, Any] = { + "congressional_district_impact": None, + "constituency_impact": None, + "local_authority_impact": None, + } + if "congressional_district_impact" in sections: + payload["congressional_district_impact"] = { + "districts": [ + { + name: row[name] + for name in row.keys() # noqa: SIM118 # RowMapping keys + if name not in {"report_run_id", "position"} + } + for row in ordered(congressional_district_impacts) + ] + } + if "constituency_impact" in sections: + payload["constituency_impact"] = _labelled_geographies( + ordered(constituency_impacts), + "constituency_code", + "constituency_name", + labels.constituencies, + ) + if "local_authority_impact" in sections: + payload["local_authority_impact"] = _labelled_geographies( + ordered(local_authority_impacts), + "local_authority_code", + "local_authority_name", + labels.local_authorities, + ) + return payload + + +def _comparison_sections( + connection: Connection, + report_run_id: UUID, + sections: set[str], + labels: EconomyResultLabels, +) -> dict[str, Any]: + budget = _one(connection, budget_impacts, "report_run_id", report_run_id) + deciles = _rows( + connection, + decile_impacts, + "report_run_id", + report_run_id, + order=("measure", "position"), + ) + intra = _rows(connection, intra_decile_impacts, "report_run_id", report_run_id) + programs = _rows( + connection, + program_budget_impacts, + "report_run_id", + report_run_id, + order=("position",), + ) + return { + "budget": { + name: value for name, value in budget.items() if name != "report_run_id" + }, + "detailed_budget": { + row["program"]: { + "baseline": row["baseline"], + "reform": row["reform"], + "difference": row["difference"], + } + for row in programs + }, + "decile": _deciles(deciles, "income"), + "wealth_decile": ( + _deciles(deciles, "wealth") if "wealth_decile" in sections else None + ), + "intra_decile": _intra_deciles(intra, "income"), + "intra_wealth_decile": ( + _intra_deciles(intra, "wealth") + if "intra_wealth_decile" in sections + else None + ), + "labor_supply_response": ( + _labor_supply(connection, report_run_id) + if "labor_supply_response" in sections + else None + ), + **_geography_sections(connection, report_run_id, sections, labels), + } + + +def read_economy_comparison( + connection: Connection, report_run_id: UUID, labels: EconomyResultLabels +) -> SingleYearMacroOutput: + """Rebuild a succeeded economy report run's result from its rows. + + Raise LookupError when the report run has no succeeded comparison, or + when the labels lack a constituency or local authority the result names. + """ + report_run_row = ( + connection.execute(select(report_runs).where(report_runs.c.id == report_run_id)) + .mappings() + .first() + ) + if report_run_row is None: + msg = f"no report run {report_run_id}" + raise LookupError(msg) + report_run = ReportRunRecord.from_row(report_run_row) + if ( + report_run.comparison_status is not RunStatus.SUCCEEDED + or report_run.reform_simulation_run_id is None + ): + msg = f"report run {report_run_id} has no succeeded economy comparison" + raise LookupError(msg) + sections: set[str] = set(report_run_row["result_sections"] or ()) + run_ids = ( + report_run.baseline_simulation_run_id, + report_run.reform_simulation_run_id, + ) + return SingleYearMacroOutput.model_validate( + { + "spm_provenance": report_run_row["spm_provenance"], + "model_version": labels.model_version, + "data_version": labels.data_version, + **_comparison_sections(connection, report_run_id, sections, labels), + **_simulation_sections(connection, run_ids, sections), + } + ) diff --git a/libs/policyengine-simulation-persistence/src/policyengine_simulation_persistence/result_tables.py b/libs/policyengine-simulation-persistence/src/policyengine_simulation_persistence/result_tables.py new file mode 100644 index 000000000..51385752e --- /dev/null +++ b/libs/policyengine-simulation-persistence/src/policyengine_simulation_persistence/result_tables.py @@ -0,0 +1,290 @@ +"""The result tables: every economy result stored as rows, attached to its run. + +Each section of today's economy result model (``SingleYearMacroOutput``) maps +to one table. Numbers that describe one simulation (a baseline's or a reform's +own poverty rates, inequality and cliff exposure) belong to that simulation +run, so a reused current-law baseline keeps them once; comparisons (the change +between baseline and reform) belong to the report run. Lists and maps keep +their order in a ``position`` column, so a reader rebuilds the result exactly. + +Constituency and local-authority names and map positions are not stored: they +come from the region catalog by code. The model and data versions are pinned +by the run's catalog version. The SPM provenance and the list of optional +sections a result holds are columns on the report run. +""" + +from __future__ import annotations + +from typing import TYPE_CHECKING + +from sqlalchemy import ( + CheckConstraint, + Column, + Double, + ForeignKeyConstraint, + Integer, + PrimaryKeyConstraint, + SmallInteger, + Table, + Text, + UniqueConstraint, + Uuid, +) + +from policyengine_simulation_persistence.runs import report_runs, simulation_runs +from policyengine_simulation_persistence.schema import simulation_metadata + +if TYPE_CHECKING: + from sqlalchemy.schema import SchemaItem + +POVERTY_MEASURES = ("poverty", "deep_poverty") +POVERTY_GROUPS = { + "age": ("child", "adult", "senior", "all"), + "gender": ("male", "female"), + "race": ("white", "black", "hispanic", "other"), +} +DECILE_MEASURES = ("income", "wealth") + + +def _values(values: tuple[str, ...]) -> str: + return ", ".join(f"'{value}'" for value in values) + + +def _simulation_run_key(table_name: str) -> list[SchemaItem]: + return [ + Column("simulation_run_id", Uuid(as_uuid=True), nullable=False), + ForeignKeyConstraint( + ["simulation_run_id"], + [simulation_runs.c.id], + name=f"fk_{table_name}_simulation_run", + ondelete="RESTRICT", + ), + ] + + +def _report_run_key(table_name: str) -> list[SchemaItem]: + return [ + Column("report_run_id", Uuid(as_uuid=True), nullable=False), + ForeignKeyConstraint( + ["report_run_id"], + [report_runs.c.id], + name=f"fk_{table_name}_report_run", + ondelete="RESTRICT", + ), + ] + + +def _numbers(*names: str) -> list[Column[float]]: + return [Column(name, Double, nullable=False) for name in names] + + +def _position() -> list[SchemaItem]: + return [ + Column("position", Integer, nullable=False), + CheckConstraint("position >= 0", name="position"), + ] + + +# --- Per simulation run ----------------------------------------------------- + +poverty_rates = Table( + "poverty_rates", + simulation_metadata, + *_simulation_run_key("poverty_rates"), + Column("measure", Text, nullable=False), + Column("group_dimension", Text, nullable=False), + Column("group_value", Text, nullable=False), + *_numbers("rate"), + PrimaryKeyConstraint( + "simulation_run_id", "measure", "group_dimension", "group_value" + ), + CheckConstraint(f"measure IN ({_values(POVERTY_MEASURES)})", name="measure"), + CheckConstraint( + " OR ".join( + f"(group_dimension = '{dimension}' " + f"AND group_value IN ({_values(group_values)}))" + for dimension, group_values in POVERTY_GROUPS.items() + ), + name="group", + ), +) + +inequality = Table( + "inequality", + simulation_metadata, + *_simulation_run_key("inequality"), + *_numbers("gini", "top_10_pct_share", "top_1_pct_share"), + PrimaryKeyConstraint("simulation_run_id"), +) + +cliff_impacts = Table( + "cliff_impacts", + simulation_metadata, + *_simulation_run_key("cliff_impacts"), + *_numbers("cliff_gap", "cliff_share"), + PrimaryKeyConstraint("simulation_run_id"), +) + +# --- Per report run --------------------------------------------------------- + +budget_impacts = Table( + "budget_impacts", + simulation_metadata, + *_report_run_key("budget_impacts"), + *_numbers( + "budgetary_impact", + "tax_revenue_impact", + "state_tax_revenue_impact", + "benefit_spending_impact", + "households", + "baseline_net_income", + ), + PrimaryKeyConstraint("report_run_id"), +) + +program_budget_impacts = Table( + "program_budget_impacts", + simulation_metadata, + *_report_run_key("program_budget_impacts"), + Column("program", Text, nullable=False), + *_position(), + *_numbers("baseline", "reform", "difference"), + PrimaryKeyConstraint("report_run_id", "program"), + UniqueConstraint("report_run_id", "position"), +) + +decile_impacts = Table( + "decile_impacts", + simulation_metadata, + *_report_run_key("decile_impacts"), + Column("measure", Text, nullable=False), + # The decile's key as the result names it ("1" to "10"). + Column("decile", Text, nullable=False), + *_position(), + *_numbers("average_change", "relative_change"), + PrimaryKeyConstraint("report_run_id", "measure", "decile"), + UniqueConstraint("report_run_id", "measure", "position"), + CheckConstraint(f"measure IN ({_values(DECILE_MEASURES)})", name="measure"), +) + +intra_decile_impacts = Table( + "intra_decile_impacts", + simulation_metadata, + *_report_run_key("intra_decile_impacts"), + Column("measure", Text, nullable=False), + # The size-of-change category, for example "Gain more than 5%". + Column("outcome", Text, nullable=False), + Column("outcome_position", Integer, nullable=False), + # 1 to 10 for a decile's share; null for the average across deciles. + Column("decile", SmallInteger, nullable=True), + *_numbers("share"), + UniqueConstraint( + "report_run_id", + "measure", + "outcome", + "decile", + postgresql_nulls_not_distinct=True, + ), + CheckConstraint(f"measure IN ({_values(DECILE_MEASURES)})", name="measure"), + CheckConstraint("decile IS NULL OR decile >= 1", name="decile"), + CheckConstraint("outcome_position >= 0", name="outcome_position"), +) + +labor_supply_responses = Table( + "labor_supply_responses", + simulation_metadata, + *_report_run_key("labor_supply_responses"), + *_numbers( + "substitution_lsr", + "income_lsr", + "relative_income_response", + "relative_substitution_response", + "total_change", + "revenue_change", + "baseline_hours", + "reform_hours", + "hours_change", + "hours_income_effect", + "hours_substitution_effect", + ), + PrimaryKeyConstraint("report_run_id"), +) + +labor_supply_decile_impacts = Table( + "labor_supply_decile_impacts", + simulation_metadata, + *_report_run_key("labor_supply_decile_impacts"), + Column("decile", Integer, nullable=False), + *_position(), + *_numbers( + "average_income_effect", + "average_substitution_effect", + "relative_income_effect", + "relative_substitution_effect", + ), + PrimaryKeyConstraint("report_run_id", "decile"), + UniqueConstraint("report_run_id", "position"), +) + +congressional_district_impacts = Table( + "congressional_district_impacts", + simulation_metadata, + *_report_run_key("congressional_district_impacts"), + Column("district", Text, nullable=False), + *_position(), + *_numbers( + "average_household_income_change", + "relative_household_income_change", + "winner_percentage", + "loser_percentage", + "no_change_percentage", + "population", + ), + PrimaryKeyConstraint("report_run_id", "district"), + UniqueConstraint("report_run_id", "position"), +) + +constituency_impacts = Table( + "constituency_impacts", + simulation_metadata, + *_report_run_key("constituency_impacts"), + Column("constituency_code", Text, nullable=False), + *_position(), + *_numbers( + "average_household_income_change", + "relative_household_income_change", + "population", + ), + PrimaryKeyConstraint("report_run_id", "constituency_code"), + UniqueConstraint("report_run_id", "position"), +) + +local_authority_impacts = Table( + "local_authority_impacts", + simulation_metadata, + *_report_run_key("local_authority_impacts"), + Column("local_authority_code", Text, nullable=False), + *_position(), + *_numbers( + "average_household_income_change", + "relative_household_income_change", + "population", + ), + PrimaryKeyConstraint("report_run_id", "local_authority_code"), + UniqueConstraint("report_run_id", "position"), +) + +ECONOMY_RESULT_TABLES = ( + poverty_rates, + inequality, + cliff_impacts, + budget_impacts, + program_budget_impacts, + decile_impacts, + intra_decile_impacts, + labor_supply_responses, + labor_supply_decile_impacts, + congressional_district_impacts, + constituency_impacts, + local_authority_impacts, +) diff --git a/libs/policyengine-simulation-persistence/src/policyengine_simulation_persistence/runs.py b/libs/policyengine-simulation-persistence/src/policyengine_simulation_persistence/runs.py index 3ad05ea99..59e6eb926 100644 --- a/libs/policyengine-simulation-persistence/src/policyengine_simulation_persistence/runs.py +++ b/libs/policyengine-simulation-persistence/src/policyengine_simulation_persistence/runs.py @@ -42,6 +42,7 @@ Uuid, text, ) +from sqlalchemy.dialects.postgresql import ARRAY, JSONB from policyengine_simulation_persistence import public_api from policyengine_simulation_persistence.reports import ( @@ -280,8 +281,16 @@ def _execution_columns(prefix: str, *, required: bool) -> list[Column[Any]]: *_execution_columns("comparison_", required=False), Column("created_at", DateTime(timezone=True), nullable=False), Column("updated_at", DateTime(timezone=True), nullable=False), + # Set with an economy comparison's result rows (item 1.07): the optional + # sections the result holds, and its SPM provenance, if any. + Column("result_sections", ARRAY(Text), nullable=True), + Column("spm_provenance", JSONB(none_as_null=True), nullable=True), CheckConstraint(f"year BETWEEN {FIRST_YEAR} AND {LAST_YEAR}", name="year"), CheckConstraint(f"trigger IN ({_values(RunTrigger)})", name="trigger"), + CheckConstraint( + "spm_provenance IS NULL OR jsonb_typeof(spm_provenance) = 'object'", + name="spm_provenance", + ), # An economy report run compares two simulation runs in its own comparison # step; a household report run has no comparison step. CheckConstraint( diff --git a/libs/policyengine-simulation-persistence/src/policyengine_simulation_persistence/schema.py b/libs/policyengine-simulation-persistence/src/policyengine_simulation_persistence/schema.py index 7ef7081c6..00ec22e10 100644 --- a/libs/policyengine-simulation-persistence/src/policyengine_simulation_persistence/schema.py +++ b/libs/policyengine-simulation-persistence/src/policyengine_simulation_persistence/schema.py @@ -17,7 +17,7 @@ # The newest revision in migrations/versions. Each migration PR updates it, and # tests/test_schema.py fails when it differs from the chain's head. The # readiness check reports it next to the database's revision. -HEAD_REVISION = "0003" +HEAD_REVISION = "0004" NAMING_CONVENTION = { "ix": "ix_%(table_name)s_%(column_0_N_name)s", diff --git a/libs/policyengine-simulation-persistence/tests/fixtures/economy_results/uk_constituency_2026.json b/libs/policyengine-simulation-persistence/tests/fixtures/economy_results/uk_constituency_2026.json new file mode 100644 index 000000000..ea769f839 --- /dev/null +++ b/libs/policyengine-simulation-persistence/tests/fixtures/economy_results/uk_constituency_2026.json @@ -0,0 +1,304 @@ +{ + "spm_provenance": null, + "model_version": "2.62.1", + "data_version": "1.30.2", + "budget": { + "tax_revenue_impact": -69830165215.09961, + "state_tax_revenue_impact": 0.0, + "benefit_spending_impact": 30186894607.97075, + "budgetary_impact": -35233447033.36752, + "households": 121448725.73335086, + "baseline_net_income": 12071764008613.379 + }, + "detailed_budget": { + "income_tax": { + "baseline": -268622166.17482895, + "reform": -884002150.4505864, + "difference": 14871466.378840514 + }, + "national_insurance": { + "baseline": -925008683.1160302, + "reform": -132708632.67522825, + "difference": -860289152.8507621 + }, + "universal_credit": { + "baseline": -818573973.3122699, + "reform": -150961621.71497208, + "difference": 653704249.3440762 + } + }, + "decile": { + "average": { + "1": -2257.1882331021266, + "2": -1660.5662123579127, + "3": 764.5993344335358, + "4": 2686.253654742034, + "5": 462.617691704992, + "6": -619.917152095319, + "7": 2857.5306335575206, + "8": -2720.503916293462, + "9": 2150.810754292077, + "10": -1262.3442820099424 + }, + "relative": { + "1": 0.0, + "2": 0.5709136896467344, + "3": -0.0, + "4": 0.10305571244359135, + "5": 1e-12, + "6": 0.0, + "7": 0.5643682931333867, + "8": 0.20595871281932654, + "9": 1e-12, + "10": -3.5e-9 + } + }, + "inequality": { + "gini": { + "baseline": 0.36158235594456634, + "reform": 0.24842658485754932 + }, + "top_10_pct_share": { + "baseline": 0.1797667495831432, + "reform": 0.7798296305842437 + }, + "top_1_pct_share": { + "baseline": 0.08185501079576984, + "reform": 0.3002491185456253 + } + }, + "poverty": { + "poverty": { + "child": { + "baseline": 0.49511635955525557, + "reform": 0.3434756899583733 + }, + "adult": { + "baseline": 0.44883419042779327, + "reform": 0.6089590190364036 + }, + "senior": { + "baseline": 0.07320086745966803, + "reform": 0.5119328306475491 + }, + "all": { + "baseline": 0.16496210364357322, + "reform": 0.34205580615985787 + } + }, + "deep_poverty": { + "child": { + "baseline": 0.9332702121806375, + "reform": 0.4216983544767443 + }, + "adult": { + "baseline": 0.9620190834121097, + "reform": 0.07762048218079554 + }, + "senior": { + "baseline": 0.5580757526533747, + "reform": 0.7890941714903549 + }, + "all": { + "baseline": 0.8183533423673176, + "reform": 0.3401223621911955 + } + } + }, + "poverty_by_gender": { + "poverty": { + "male": { + "baseline": 0.3501783877191683, + "reform": 0.4966747952989876 + }, + "female": { + "baseline": 0.7968919758215943, + "reform": 0.06876294940686056 + } + }, + "deep_poverty": { + "male": { + "baseline": 0.09359599608690361, + "reform": 0.2699392771281177 + }, + "female": { + "baseline": 0.6970420678269282, + "reform": 0.06499997571609484 + } + } + }, + "poverty_by_race": null, + "intra_decile": { + "deciles": { + "Gain more than 5%": [ + 0.7311593346408904, + 0.30960737650937475, + 0.5779462307177181, + 0.6812371747339128, + 0.4456407672509217, + 0.7166277943983036, + 0.8870402922380918, + 0.34700525568845064, + 0.9406485666460938, + 0.355464109540346 + ], + "Gain less than 5%": [ + 0.6109195434830769, + 0.49369299455698146, + 0.21820777481967946, + 0.28743192649886173, + 0.7383633795947941, + 0.3978976785462327, + 0.9168162261800614, + 0.4965066990299619, + 0.16636628247192053, + 0.4016442563343041 + ], + "No change": [ + 0.27783913078445066, + 0.13692614301502581, + 0.4305216510890757, + 0.5502195528031965, + 0.7063967094965019, + 0.9864670810011861, + 0.6827230593874516, + 0.38044130025603773, + 0.23075150810868217, + 0.08298469466133207 + ], + "Lose less than 5%": [ + 0.15129838311640065, + 0.6585166769723302, + 0.012063059843798851, + 0.8310935615682863, + 0.1823428739811973, + 0.28193072232673766, + 0.14567639245798059, + 0.5345909623001036, + 0.6098124352569969, + 0.31861168111188654 + ], + "Lose more than 5%": [ + 0.125491512495977, + 0.8592019492051857, + 0.9502239496826584, + 0.6549664637163287, + 0.7397847477644152, + 0.45664372220287475, + 0.8709795011577717, + 0.9518862208315222, + 0.68057510106171, + 0.5592717408566095 + ] + }, + "all": { + "Gain more than 5%": 0.3980696305556508, + "Gain less than 5%": 0.39412001597536417, + "No change": 0.4815228181651947, + "Lose less than 5%": 0.4004426305163489, + "Lose more than 5%": 0.19060953756680787 + } + }, + "wealth_decile": { + "average": { + "1": 2908.005604539656, + "2": -356.23879005149695, + "3": -2340.430169997201, + "4": 604.3635630268873, + "5": -2385.7224136486675, + "6": 400.7016487985069, + "7": 219.71212781061357, + "8": 2693.692551416602, + "9": 682.4235778525865, + "10": -2578.106543079062 + }, + "relative": { + "1": -3.5e-9, + "2": 1e-12, + "3": 0.9554680239214713, + "4": 0.0, + "5": -3.5e-9, + "6": -3.5e-9, + "7": 1e-12, + "8": 0.0, + "9": 1e-12, + "10": -0.0 + } + }, + "intra_wealth_decile": { + "deciles": { + "Gain more than 5%": [ + 0.5163345189623215, + 0.2052150067015407, + 0.9520209471006497, + 0.36175245900901054, + 0.6900675858793588, + 0.9141457827913946, + 0.7581429595359372, + 0.29808969034627997, + 0.6429170806953686, + 0.09101055336145147 + ], + "Gain less than 5%": [ + 0.8454475943827271, + 0.5183968571327611, + 0.90825854366304, + 0.3556961698229455, + 0.22279275605523874, + 0.5415671227801955, + 0.5026970232253148, + 0.6364419253397112, + 0.613228222813541, + 0.7883992641041133 + ], + "No change": [ + 0.758322424088633, + 0.19514603023289578, + 0.2393876747662793, + 0.4006843696525172, + 0.8033260645474455, + 0.19991798339514966, + 0.49278184291394456, + 0.7310039924754212, + 0.98960358670307, + 0.7901141366319249 + ], + "Lose less than 5%": [ + 0.4722400624988553, + 0.19364494601280935, + 0.6051390316822758, + 0.344280924254862, + 0.8085657427983075, + 0.723127961069629, + 0.34951966222376096, + 0.974514978860586, + 0.08053812548862638, + 0.10215714742873472 + ], + "Lose more than 5%": [ + 0.4700799822561902, + 0.3377374798385304, + 0.48265330213357793, + 0.9852489970647419, + 0.6102621468934083, + 0.0019083133300648036, + 0.9091991979850682, + 0.34400690197679207, + 0.6431330970285719, + 0.834648807798219 + ] + }, + "all": { + "Gain more than 5%": 0.11990363083613764, + "Gain less than 5%": 0.3885357438199436, + "No change": 0.7114929836253856, + "Lose less than 5%": 0.1993194034549053, + "Lose more than 5%": 0.8890110044071206 + } + }, + "labor_supply_response": null, + "constituency_impact": [], + "local_authority_impact": null, + "congressional_district_impact": null, + "cliff_impact": null +} diff --git a/libs/policyengine-simulation-persistence/tests/fixtures/economy_results/uk_local_authority_2026.json b/libs/policyengine-simulation-persistence/tests/fixtures/economy_results/uk_local_authority_2026.json new file mode 100644 index 000000000..3d309bacd --- /dev/null +++ b/libs/policyengine-simulation-persistence/tests/fixtures/economy_results/uk_local_authority_2026.json @@ -0,0 +1,314 @@ +{ + "spm_provenance": null, + "model_version": "2.62.1", + "data_version": "1.30.2", + "budget": { + "tax_revenue_impact": 92459007166.87656, + "state_tax_revenue_impact": 0.0, + "benefit_spending_impact": -74733820269.8281, + "budgetary_impact": -54658828123.79024, + "households": 134096338.45743215, + "baseline_net_income": 11170370536101.506 + }, + "detailed_budget": { + "income_tax": { + "baseline": -505118030.14182985, + "reform": 998257078.3251581, + "difference": -581204736.2221744 + }, + "national_insurance": { + "baseline": 283736870.144214, + "reform": -81732474.45520659, + "difference": -93735137.72371434 + }, + "universal_credit": { + "baseline": -10034612.22164459, + "reform": -615538315.5146357, + "difference": 661042547.2659434 + } + }, + "decile": { + "average": { + "1": -2462.6062593564625, + "2": -1594.9022430617679, + "3": -2880.0521626549153, + "4": -1399.3952339808131, + "5": -554.0168222342572, + "6": 2412.38580246977, + "7": -725.5474749504656, + "8": -2317.6144363152007, + "9": -1449.8597638085234, + "10": 2949.6143824264072 + }, + "relative": { + "1": 0.06308868070221851, + "2": 0.0, + "3": 1e-12, + "4": 0.0, + "5": 0.49758053499007204, + "6": 0.9013749600046599, + "7": 0.808392704592183, + "8": 0.0, + "9": -0.0, + "10": 0.14820779074761503 + } + }, + "inequality": { + "gini": { + "baseline": 0.4562631750773002, + "reform": 0.5843663579297041 + }, + "top_10_pct_share": { + "baseline": 0.4451369217459352, + "reform": 0.5573200610033924 + }, + "top_1_pct_share": { + "baseline": 0.8550395732974745, + "reform": 0.4261199543995837 + } + }, + "poverty": { + "poverty": { + "child": { + "baseline": 0.1582997572742052, + "reform": 0.6013118855477607 + }, + "adult": { + "baseline": 0.5318079940243159, + "reform": 0.31378663109351257 + }, + "senior": { + "baseline": 0.35703051052987367, + "reform": 0.643906472947396 + }, + "all": { + "baseline": 0.4946319125862524, + "reform": 0.6239857166830313 + } + }, + "deep_poverty": { + "child": { + "baseline": 0.3087913032633056, + "reform": 0.35573908335507054 + }, + "adult": { + "baseline": 0.28435448936962193, + "reform": 0.6570561831550361 + }, + "senior": { + "baseline": 0.8081220455707656, + "reform": 0.8567220084921808 + }, + "all": { + "baseline": 0.9130649320877698, + "reform": 0.5449358911808955 + } + } + }, + "poverty_by_gender": { + "poverty": { + "male": { + "baseline": 0.34420243087326197, + "reform": 0.9079041928940726 + }, + "female": { + "baseline": 0.29570667701386866, + "reform": 0.21979131003351726 + } + }, + "deep_poverty": { + "male": { + "baseline": 0.03365358280689901, + "reform": 0.2547728298375461 + }, + "female": { + "baseline": 0.29835312690076377, + "reform": 0.7053958616515078 + } + } + }, + "poverty_by_race": null, + "intra_decile": { + "deciles": { + "Gain more than 5%": [ + 0.4169195903483851, + 0.6574407249410744, + 0.11626222108439832, + 0.9325438414750353, + 0.8521088806900794, + 0.02563335151827517, + 0.9730740172153319, + 0.16067546829614598, + 0.11648309240652333, + 0.7964178976736825 + ], + "Gain less than 5%": [ + 0.38045272485774695, + 0.8363966880005376, + 0.5691257747680492, + 0.9051326083519999, + 0.13903840191737538, + 0.5639972943518561, + 0.4071549580839391, + 0.08013950726768904, + 0.06997546768743013, + 0.7168440229826548 + ], + "No change": [ + 0.03403311286312238, + 0.6632128365823879, + 0.7642800250719824, + 0.5272840362799457, + 0.1536563844062374, + 0.9364619441697246, + 0.4882392787052493, + 0.1485330386465159, + 0.6044432525558315, + 0.18967984629379342 + ], + "Lose less than 5%": [ + 0.9126148979394935, + 0.34079267372439015, + 0.6582072941487361, + 0.12074892031961626, + 0.29941097908798053, + 0.3254344684255279, + 0.3660441115717603, + 0.6458464848673228, + 0.4990195871150638, + 0.060665971600854185 + ], + "Lose more than 5%": [ + 0.6172602477157224, + 0.8829050359514565, + 0.8689035084797285, + 0.8085087313537289, + 0.8164383663237682, + 0.1719727529421302, + 0.3375224245329854, + 0.4310317668432285, + 0.1209512582671255, + 0.200459469895078 + ] + }, + "all": { + "Gain more than 5%": 0.22398320210880074, + "Gain less than 5%": 0.8113783037154952, + "No change": 0.7902104717084726, + "Lose less than 5%": 0.381087766006753, + "Lose more than 5%": 0.10845992401790983 + } + }, + "wealth_decile": { + "average": { + "1": 1325.7679247568183, + "2": 887.4898162388139, + "3": 1316.0780864723158, + "4": 86.8957367028691, + "5": -2457.4312396873806, + "6": 2571.1630793496124, + "7": 383.1595656463318, + "8": 1898.7683219078772, + "9": -267.98244302632025, + "10": -2694.442740194193 + }, + "relative": { + "1": 0.0, + "2": 0.0, + "3": 0.7083211213398463, + "4": 1e-12, + "5": 0.8292649495036908, + "6": 0.09333568050454522, + "7": 0.5025826008563596, + "8": -0.0, + "9": -3.5e-9, + "10": -0.0 + } + }, + "intra_wealth_decile": { + "deciles": { + "Gain more than 5%": [ + 0.006685229313061147, + 0.6131688080465992, + 0.9088512441506565, + 0.7432899871545285, + 0.9275799908266388, + 0.9817309707617923, + 0.22366815531507644, + 0.2964193603368207, + 0.547338593151295, + 0.9768034722225887 + ], + "Gain less than 5%": [ + 0.3692537531761815, + 0.9414230267760518, + 0.850482533282252, + 0.5162741638881791, + 0.6251121523324751, + 0.9570521142845508, + 0.7832734055464811, + 0.29582701363700126, + 0.8457166262663784, + 0.19574106846162365 + ], + "No change": [ + 0.36997222437408805, + 0.9585835530234085, + 0.8470554196734388, + 0.3119911119732981, + 0.2904953017609012, + 0.6130334390958693, + 0.8426376873177785, + 0.6843389982257562, + 0.936048982222627, + 0.7280329045339358 + ], + "Lose less than 5%": [ + 0.8209221636952363, + 0.604937118181085, + 0.3621831362924902, + 0.4275014936616992, + 0.4899422662160552, + 0.5289337598332745, + 0.8381929329185143, + 0.26884568604415127, + 0.06862739844800403, + 0.7331289564550246 + ], + "Lose more than 5%": [ + 0.2708834110852245, + 0.41973538532900223, + 0.11704248655255234, + 0.8293333189559117, + 0.27394366999516195, + 0.2916462441839135, + 0.80422434080631, + 0.5042365287885517, + 0.27732911702446716, + 0.8883975195301577 + ] + }, + "all": { + "Gain more than 5%": 0.41180290463967284, + "Gain less than 5%": 0.3613604996038956, + "No change": 0.9654456097484817, + "Lose less than 5%": 0.7901626415902006, + "Lose more than 5%": 0.7473865409041579 + } + }, + "labor_supply_response": null, + "constituency_impact": null, + "local_authority_impact": [ + { + "local_authority_code": "E06000000001", + "local_authority_name": "Local Authority 1", + "x": null, + "y": null, + "average_household_income_change": 23.761655080990707, + "relative_household_income_change": 0.45328471316462604, + "population": 103153.12548296218 + } + ], + "congressional_district_impact": null, + "cliff_impact": null +} diff --git a/libs/policyengine-simulation-persistence/tests/fixtures/economy_results/uk_nation_scotland_2026.json b/libs/policyengine-simulation-persistence/tests/fixtures/economy_results/uk_nation_scotland_2026.json new file mode 100644 index 000000000..f7212bfcd --- /dev/null +++ b/libs/policyengine-simulation-persistence/tests/fixtures/economy_results/uk_nation_scotland_2026.json @@ -0,0 +1,1107 @@ +{ + "spm_provenance": null, + "model_version": "2.62.1", + "data_version": "1.30.2", + "budget": { + "tax_revenue_impact": 64390808463.94536, + "state_tax_revenue_impact": 0.0, + "benefit_spending_impact": -2993074413.8109365, + "budgetary_impact": 58668016752.332596, + "households": 125232429.65889315, + "baseline_net_income": 11000903429770.143 + }, + "detailed_budget": { + "income_tax": { + "baseline": 325637125.7675352, + "reform": -59491485.87110997, + "difference": 519461270.1957861 + }, + "national_insurance": { + "baseline": -253679255.8523169, + "reform": 540279671.8759804, + "difference": -454603828.65605855 + }, + "universal_credit": { + "baseline": 603830966.3252072, + "reform": 459649665.2440321, + "difference": -171987117.66939324 + } + }, + "decile": { + "average": { + "1": 229.8313173316613, + "2": 1092.3104477320703, + "3": -1842.0907454154756, + "4": 321.6909929897056, + "5": 1830.7442990938393, + "6": -1406.8736733689877, + "7": 1820.1918576678795, + "8": 1114.1392926026454, + "9": 2065.6939487769896, + "10": -986.5078930451141 + }, + "relative": { + "1": -3.5e-9, + "2": -3.5e-9, + "3": -0.0, + "4": 1e-12, + "5": 0.0, + "6": -0.0, + "7": 1e-12, + "8": -0.0, + "9": 0.514651161252579, + "10": 0.0 + } + }, + "inequality": { + "gini": { + "baseline": 0.6334784504873784, + "reform": 0.24489570857396148 + }, + "top_10_pct_share": { + "baseline": 0.42968860495332184, + "reform": 0.35737961969641396 + }, + "top_1_pct_share": { + "baseline": 0.11958467282121965, + "reform": 0.5001571542030486 + } + }, + "poverty": { + "poverty": { + "child": { + "baseline": 0.6786164084469019, + "reform": 0.19912544724959425 + }, + "adult": { + "baseline": 0.6082083930279402, + "reform": 0.26788463676184904 + }, + "senior": { + "baseline": 0.7190033361034402, + "reform": 0.37980670097279756 + }, + "all": { + "baseline": 0.22273872895617441, + "reform": 0.5973431930682456 + } + }, + "deep_poverty": { + "child": { + "baseline": 0.8340038125629663, + "reform": 0.8759846739338617 + }, + "adult": { + "baseline": 0.5221405328253113, + "reform": 0.1887466667447798 + }, + "senior": { + "baseline": 0.16914279771639962, + "reform": 0.6479872117408518 + }, + "all": { + "baseline": 0.5577457838091093, + "reform": 0.6713560120781157 + } + } + }, + "poverty_by_gender": { + "poverty": { + "male": { + "baseline": 0.6186183415809611, + "reform": 0.3746321527466535 + }, + "female": { + "baseline": 0.5273738308933793, + "reform": 0.2891491959008181 + } + }, + "deep_poverty": { + "male": { + "baseline": 0.6787295490494265, + "reform": 0.48875780443714656 + }, + "female": { + "baseline": 0.1853489385760475, + "reform": 0.5939299668842034 + } + } + }, + "poverty_by_race": null, + "intra_decile": { + "deciles": { + "Gain more than 5%": [ + 0.9983275487852417, + 0.09598156795630997, + 0.4412533584632802, + 0.805664919162214, + 0.0890571094472482, + 0.6031814416514121, + 0.8704750455134551, + 0.44611240511532246, + 0.7839082541410588, + 0.38001855310871324 + ], + "Gain less than 5%": [ + 0.07647079614316421, + 0.426420781544818, + 0.3034617506390286, + 0.8165324211795908, + 0.9407251558149671, + 0.192145382959514, + 0.6801797096864858, + 0.4513581729506253, + 0.7226273326875959, + 0.9650738699147708 + ], + "No change": [ + 0.018540926440606675, + 0.5379422837756225, + 0.2511375515864458, + 0.8017780733186686, + 0.18755907011264716, + 0.5027365420127902, + 0.3294401386946224, + 0.5168725569156065, + 0.9815612316919237, + 0.9269299125618775 + ], + "Lose less than 5%": [ + 0.42174289086593053, + 0.4854045828278176, + 0.6024852653943666, + 0.6562875544916017, + 0.4920221130712703, + 0.7212748928180196, + 0.49665032554919664, + 0.6344686285014524, + 0.46726121994398717, + 0.3664770249966022 + ], + "Lose more than 5%": [ + 0.16303107865725508, + 0.9130982750883577, + 0.6194427711966841, + 0.6944523200618581, + 0.2658040323861912, + 0.6460990041366336, + 0.9750146231651212, + 0.7293056383240148, + 0.1581871877358284, + 0.8276901266782712 + ] + }, + "all": { + "Gain more than 5%": 0.5598594695791028, + "Gain less than 5%": 0.623783986638168, + "No change": 0.9646560032450038, + "Lose less than 5%": 0.18257821373725425, + "Lose more than 5%": 0.6099615676222211 + } + }, + "wealth_decile": { + "average": { + "1": 418.61987615264894, + "2": 1092.5765507745975, + "3": -774.5793001944729, + "4": 2895.625186194798, + "5": -15.355742566662167, + "6": 538.4961543504079, + "7": 2515.641832022293, + "8": -2073.6700617943084, + "9": -1384.4805830672783, + "10": -2911.058153713721 + }, + "relative": { + "1": 0.806214673685218, + "2": -3.5e-9, + "3": 1e-12, + "4": -0.0, + "5": -0.0, + "6": -0.0, + "7": 0.0, + "8": 0.0, + "9": -3.5e-9, + "10": 0.0 + } + }, + "intra_wealth_decile": { + "deciles": { + "Gain more than 5%": [ + 0.6291973816666468, + 0.7013704668836823, + 0.12700661731226226, + 0.8326633343412233, + 0.08354357750012409, + 0.6181217255531115, + 0.9113983457176773, + 0.907729408431122, + 0.8932946373096041, + 0.45198385044703215 + ], + "Gain less than 5%": [ + 0.6938003899178132, + 0.7913324805904123, + 0.13707201047427242, + 0.9434018223642858, + 0.9087743307211948, + 0.44088664262863775, + 0.7784980195721916, + 0.44707866429232035, + 0.276407066564499, + 0.7124788208255114 + ], + "No change": [ + 0.06367014967968354, + 0.8001987583321369, + 0.9780769226211543, + 0.2860706698905068, + 0.9396713676591827, + 0.0836817585111066, + 0.8580787872954002, + 0.27980791981603825, + 0.9662205612145367, + 0.43069671425396816 + ], + "Lose less than 5%": [ + 0.9221630049605285, + 0.031913121892390484, + 0.0856434274433241, + 0.8163716167559534, + 0.6385726424936319, + 0.5355011205782659, + 0.03271274819258396, + 0.17329315346763263, + 0.37048865878554826, + 0.052065871297530264 + ], + "Lose more than 5%": [ + 0.9930401276040598, + 0.7651977371516221, + 0.9497969464151493, + 0.700686107822012, + 0.3434781125570455, + 0.07759481040860672, + 0.7315198754952839, + 0.11403501331547539, + 0.5471255342341411, + 0.4640510361121649 + ] + }, + "all": { + "Gain more than 5%": 0.49453074216398074, + "Gain less than 5%": 0.07518152242937215, + "No change": 0.0739710655093323, + "Lose less than 5%": 0.5202668233103811, + "Lose more than 5%": 0.030475714696043932 + } + }, + "labor_supply_response": null, + "constituency_impact": [ + { + "constituency_code": "S14000000001", + "constituency_name": "Constituency 1", + "x": null, + "y": null, + "average_household_income_change": -22.0502560822613, + "relative_household_income_change": 1e-12, + "population": 79332.57320595343 + }, + { + "constituency_code": "S14000000002", + "constituency_name": "Constituency 2", + "x": 1, + "y": 0, + "average_household_income_change": 1215.908995067085, + "relative_household_income_change": 1e-12, + "population": 85934.48703372813 + }, + { + "constituency_code": "S14000000003", + "constituency_name": "Constituency 3", + "x": 2, + "y": 0, + "average_household_income_change": -377.999828418476, + "relative_household_income_change": -0.0, + "population": 83465.39782866623 + }, + { + "constituency_code": "S14000000004", + "constituency_name": "Constituency 4", + "x": 3, + "y": 0, + "average_household_income_change": -1974.7197361654237, + "relative_household_income_change": 0.0, + "population": 113477.96855441103 + }, + { + "constituency_code": "S14000000005", + "constituency_name": "Constituency 5", + "x": 4, + "y": 0, + "average_household_income_change": -649.8105518108947, + "relative_household_income_change": -0.0, + "population": 62789.23357183145 + }, + { + "constituency_code": "S14000000006", + "constituency_name": "Constituency 6", + "x": 5, + "y": 0, + "average_household_income_change": -387.339732156089, + "relative_household_income_change": 1e-12, + "population": 94065.14389717858 + }, + { + "constituency_code": "S14000000007", + "constituency_name": "Constituency 7", + "x": 6, + "y": 0, + "average_household_income_change": -726.0333413494302, + "relative_household_income_change": -0.0, + "population": 128189.16865653818 + }, + { + "constituency_code": "S14000000008", + "constituency_name": "Constituency 8", + "x": null, + "y": null, + "average_household_income_change": 459.8825949063641, + "relative_household_income_change": -0.0, + "population": 63046.60303942481 + }, + { + "constituency_code": "S14000000009", + "constituency_name": "Constituency 9", + "x": 8, + "y": 0, + "average_household_income_change": -1766.27589639709, + "relative_household_income_change": 0.0, + "population": 103944.30710763739 + }, + { + "constituency_code": "S14000000010", + "constituency_name": "Constituency 10", + "x": 9, + "y": 0, + "average_household_income_change": -1656.9844230967562, + "relative_household_income_change": 0.0, + "population": 92293.1508555326 + }, + { + "constituency_code": "S14000000011", + "constituency_name": "Constituency 11", + "x": 10, + "y": 0, + "average_household_income_change": -1568.4105912709422, + "relative_household_income_change": 0.0, + "population": 89367.41666308911 + }, + { + "constituency_code": "S14000000012", + "constituency_name": "Constituency 12", + "x": 11, + "y": 0, + "average_household_income_change": -1540.3301530676376, + "relative_household_income_change": 1e-12, + "population": 53137.15027763359 + }, + { + "constituency_code": "S14000000013", + "constituency_name": "Constituency 13", + "x": 12, + "y": 0, + "average_household_income_change": -49.71783554546061, + "relative_household_income_change": -3.5e-9, + "population": 69494.2870251734 + }, + { + "constituency_code": "S14000000014", + "constituency_name": "Constituency 14", + "x": 13, + "y": 0, + "average_household_income_change": -1713.485408027081, + "relative_household_income_change": 1e-12, + "population": 114944.10521441708 + }, + { + "constituency_code": "S14000000015", + "constituency_name": "Constituency 15", + "x": null, + "y": null, + "average_household_income_change": 515.040158455704, + "relative_household_income_change": 1e-12, + "population": 123680.0940363324 + }, + { + "constituency_code": "S14000000016", + "constituency_name": "Constituency 16", + "x": 15, + "y": 0, + "average_household_income_change": 886.6824618994942, + "relative_household_income_change": -0.0, + "population": 133563.797744863 + }, + { + "constituency_code": "S14000000017", + "constituency_name": "Constituency 17", + "x": 16, + "y": 0, + "average_household_income_change": 1847.8852194008336, + "relative_household_income_change": 0.970116107552746, + "population": 96561.24036341548 + }, + { + "constituency_code": "S14000000018", + "constituency_name": "Constituency 18", + "x": 17, + "y": 0, + "average_household_income_change": -199.63383446378157, + "relative_household_income_change": -0.0, + "population": 130680.98864876162 + }, + { + "constituency_code": "S14000000019", + "constituency_name": "Constituency 19", + "x": 18, + "y": 0, + "average_household_income_change": -1286.6748534572503, + "relative_household_income_change": -3.5e-9, + "population": 73823.59031650981 + }, + { + "constituency_code": "S14000000020", + "constituency_name": "Constituency 20", + "x": 19, + "y": 0, + "average_household_income_change": -1170.758388551763, + "relative_household_income_change": 0.8412079197691499, + "population": 95406.04234472507 + }, + { + "constituency_code": "S14000000021", + "constituency_name": "Constituency 21", + "x": 20, + "y": 0, + "average_household_income_change": -721.0569534926518, + "relative_household_income_change": -0.0, + "population": 68215.09086082038 + }, + { + "constituency_code": "S14000000022", + "constituency_name": "Constituency 22", + "x": null, + "y": null, + "average_household_income_change": -1327.8413593194002, + "relative_household_income_change": 1e-12, + "population": 139680.9189915626 + }, + { + "constituency_code": "S14000000023", + "constituency_name": "Constituency 23", + "x": 22, + "y": 0, + "average_household_income_change": 1823.701833262151, + "relative_household_income_change": 0.0, + "population": 135075.91381560973 + }, + { + "constituency_code": "S14000000024", + "constituency_name": "Constituency 24", + "x": 23, + "y": 0, + "average_household_income_change": 585.4829596118924, + "relative_household_income_change": 0.0, + "population": 62805.9120249973 + }, + { + "constituency_code": "S14000000025", + "constituency_name": "Constituency 25", + "x": 24, + "y": 0, + "average_household_income_change": -10.380093653008071, + "relative_household_income_change": 1e-12, + "population": 93527.3783158783 + }, + { + "constituency_code": "S14000000026", + "constituency_name": "Constituency 26", + "x": 25, + "y": 0, + "average_household_income_change": -256.4312080701563, + "relative_household_income_change": 0.6432241717762336, + "population": 88101.31906153599 + }, + { + "constituency_code": "S14000000027", + "constituency_name": "Constituency 27", + "x": 26, + "y": 0, + "average_household_income_change": 1702.7522243659537, + "relative_household_income_change": 0.0, + "population": 125414.43486372594 + }, + { + "constituency_code": "S14000000028", + "constituency_name": "Constituency 28", + "x": 27, + "y": 0, + "average_household_income_change": 1224.4288663412387, + "relative_household_income_change": 1e-12, + "population": 125936.64670777883 + }, + { + "constituency_code": "S14000000029", + "constituency_name": "Constituency 29", + "x": null, + "y": null, + "average_household_income_change": -50.36433936503304, + "relative_household_income_change": 0.5045905570059873, + "population": 110678.73316985903 + }, + { + "constituency_code": "S14000000030", + "constituency_name": "Constituency 30", + "x": 29, + "y": 0, + "average_household_income_change": -1787.784293656903, + "relative_household_income_change": -3.5e-9, + "population": 137815.36506324858 + }, + { + "constituency_code": "S14000000031", + "constituency_name": "Constituency 31", + "x": 30, + "y": 0, + "average_household_income_change": -712.4863332789974, + "relative_household_income_change": 0.8140841787567573, + "population": 77978.11324744608 + }, + { + "constituency_code": "S14000000032", + "constituency_name": "Constituency 32", + "x": 0, + "y": 1, + "average_household_income_change": 1623.627170035723, + "relative_household_income_change": -0.0, + "population": 106220.79881424447 + }, + { + "constituency_code": "S14000000033", + "constituency_name": "Constituency 33", + "x": 1, + "y": 1, + "average_household_income_change": -879.6243473802599, + "relative_household_income_change": -0.0, + "population": 113212.96419666243 + }, + { + "constituency_code": "S14000000034", + "constituency_name": "Constituency 34", + "x": 2, + "y": 1, + "average_household_income_change": -759.2250650364525, + "relative_household_income_change": -0.0, + "population": 75244.09885972543 + }, + { + "constituency_code": "S14000000035", + "constituency_name": "Constituency 35", + "x": 3, + "y": 1, + "average_household_income_change": 328.0589704575538, + "relative_household_income_change": -0.0, + "population": 100810.42044062808 + }, + { + "constituency_code": "S14000000036", + "constituency_name": "Constituency 36", + "x": null, + "y": null, + "average_household_income_change": 1123.594288313716, + "relative_household_income_change": 1e-12, + "population": 124050.46952325002 + }, + { + "constituency_code": "S14000000037", + "constituency_name": "Constituency 37", + "x": 5, + "y": 1, + "average_household_income_change": -207.40824634245314, + "relative_household_income_change": 0.566121478909492, + "population": 86172.31704600062 + }, + { + "constituency_code": "S14000000038", + "constituency_name": "Constituency 38", + "x": 6, + "y": 1, + "average_household_income_change": 450.9534054524922, + "relative_household_income_change": 1e-12, + "population": 71202.13598416587 + }, + { + "constituency_code": "S14000000039", + "constituency_name": "Constituency 39", + "x": 7, + "y": 1, + "average_household_income_change": -505.1320248700919, + "relative_household_income_change": -0.0, + "population": 78380.02565944156 + }, + { + "constituency_code": "S14000000040", + "constituency_name": "Constituency 40", + "x": 8, + "y": 1, + "average_household_income_change": 369.07046484015103, + "relative_household_income_change": 0.0, + "population": 96559.91677812286 + }, + { + "constituency_code": "S14000000041", + "constituency_name": "Constituency 41", + "x": 9, + "y": 1, + "average_household_income_change": 1725.916837222794, + "relative_household_income_change": 0.6377702114609652, + "population": 54537.937931824395 + }, + { + "constituency_code": "S14000000042", + "constituency_name": "Constituency 42", + "x": 10, + "y": 1, + "average_household_income_change": 1330.2517858463264, + "relative_household_income_change": 0.5598026330340823, + "population": 52934.12546599741 + }, + { + "constituency_code": "S14000000043", + "constituency_name": "Constituency 43", + "x": null, + "y": null, + "average_household_income_change": 1766.9186377099031, + "relative_household_income_change": 1e-12, + "population": 67014.41931048906 + }, + { + "constituency_code": "S14000000044", + "constituency_name": "Constituency 44", + "x": 12, + "y": 1, + "average_household_income_change": -573.5210003270792, + "relative_household_income_change": 0.5958518145639365, + "population": 143726.2105377167 + }, + { + "constituency_code": "S14000000045", + "constituency_name": "Constituency 45", + "x": 13, + "y": 1, + "average_household_income_change": -1142.3319096547716, + "relative_household_income_change": 1e-12, + "population": 127568.64904169193 + }, + { + "constituency_code": "S14000000046", + "constituency_name": "Constituency 46", + "x": 14, + "y": 1, + "average_household_income_change": -1987.0210639986383, + "relative_household_income_change": -0.0, + "population": 79684.65150836893 + }, + { + "constituency_code": "S14000000047", + "constituency_name": "Constituency 47", + "x": 15, + "y": 1, + "average_household_income_change": -899.9641960071924, + "relative_household_income_change": 0.33535050184635984, + "population": 110975.7867195766 + }, + { + "constituency_code": "S14000000048", + "constituency_name": "Constituency 48", + "x": 16, + "y": 1, + "average_household_income_change": 43.803712052223446, + "relative_household_income_change": -0.0, + "population": 55638.22656504041 + }, + { + "constituency_code": "S14000000049", + "constituency_name": "Constituency 49", + "x": 17, + "y": 1, + "average_household_income_change": -1858.2148152893594, + "relative_household_income_change": -0.0, + "population": 61494.55783779679 + }, + { + "constituency_code": "S14000000050", + "constituency_name": "Constituency 50", + "x": null, + "y": null, + "average_household_income_change": 1793.552834263271, + "relative_household_income_change": 1e-12, + "population": 71150.5956498904 + }, + { + "constituency_code": "S14000000051", + "constituency_name": "Constituency 51", + "x": 19, + "y": 1, + "average_household_income_change": 395.1686018800302, + "relative_household_income_change": -3.5e-9, + "population": 57577.16533695534 + }, + { + "constituency_code": "S14000000052", + "constituency_name": "Constituency 52", + "x": 20, + "y": 1, + "average_household_income_change": 1734.0747439322786, + "relative_household_income_change": 1e-12, + "population": 65718.41606608071 + }, + { + "constituency_code": "S14000000053", + "constituency_name": "Constituency 53", + "x": 21, + "y": 1, + "average_household_income_change": -1021.0283577089085, + "relative_household_income_change": 1e-12, + "population": 52738.38868454951 + }, + { + "constituency_code": "S14000000054", + "constituency_name": "Constituency 54", + "x": 22, + "y": 1, + "average_household_income_change": 1195.60033690023, + "relative_household_income_change": 0.0, + "population": 58687.69580485995 + }, + { + "constituency_code": "S14000000055", + "constituency_name": "Constituency 55", + "x": 23, + "y": 1, + "average_household_income_change": 1258.2528562824318, + "relative_household_income_change": 1e-12, + "population": 52638.640102357116 + }, + { + "constituency_code": "S14000000056", + "constituency_name": "Constituency 56", + "x": 24, + "y": 1, + "average_household_income_change": -1190.9949809860163, + "relative_household_income_change": -3.5e-9, + "population": 95505.81052752634 + }, + { + "constituency_code": "S14000000057", + "constituency_name": "Constituency 57", + "x": null, + "y": null, + "average_household_income_change": -1580.6126310753368, + "relative_household_income_change": 0.8216310930495441, + "population": 64646.038428561056 + } + ], + "local_authority_impact": [ + { + "local_authority_code": "S12000000001", + "local_authority_name": "Local Authority 1", + "x": null, + "y": null, + "average_household_income_change": 1711.9662635106972, + "relative_household_income_change": -0.0, + "population": 139245.28916534188 + }, + { + "local_authority_code": "S12000000002", + "local_authority_name": "Local Authority 2", + "x": 1, + "y": 0, + "average_household_income_change": -760.4907483529573, + "relative_household_income_change": -0.0, + "population": 100805.127015022 + }, + { + "local_authority_code": "S12000000003", + "local_authority_name": "Local Authority 3", + "x": 2, + "y": 0, + "average_household_income_change": -1353.896856076334, + "relative_household_income_change": -0.0, + "population": 136496.49703708116 + }, + { + "local_authority_code": "S12000000004", + "local_authority_name": "Local Authority 4", + "x": 3, + "y": 0, + "average_household_income_change": -1879.016683323623, + "relative_household_income_change": 0.0, + "population": 127529.863915214 + }, + { + "local_authority_code": "S12000000005", + "local_authority_name": "Local Authority 5", + "x": 4, + "y": 0, + "average_household_income_change": -629.0130927662503, + "relative_household_income_change": -0.0, + "population": 119156.76386104178 + }, + { + "local_authority_code": "S12000000006", + "local_authority_name": "Local Authority 6", + "x": 5, + "y": 0, + "average_household_income_change": 874.6099793547413, + "relative_household_income_change": -3.5e-9, + "population": 106277.9233003826 + }, + { + "local_authority_code": "S12000000007", + "local_authority_name": "Local Authority 7", + "x": 6, + "y": 0, + "average_household_income_change": 467.98635714846614, + "relative_household_income_change": 1e-12, + "population": 139741.54468077584 + }, + { + "local_authority_code": "S12000000008", + "local_authority_name": "Local Authority 8", + "x": null, + "y": null, + "average_household_income_change": -550.7700901310177, + "relative_household_income_change": 0.0, + "population": 80739.55317161283 + }, + { + "local_authority_code": "S12000000009", + "local_authority_name": "Local Authority 9", + "x": 8, + "y": 0, + "average_household_income_change": -838.1639537967227, + "relative_household_income_change": 0.42674518552708585, + "population": 77962.94927239053 + }, + { + "local_authority_code": "S12000000010", + "local_authority_name": "Local Authority 10", + "x": 9, + "y": 0, + "average_household_income_change": -1308.258634844165, + "relative_household_income_change": 0.7317258270864375, + "population": 106985.32281751494 + }, + { + "local_authority_code": "S12000000011", + "local_authority_name": "Local Authority 11", + "x": 10, + "y": 0, + "average_household_income_change": -1200.3987427447091, + "relative_household_income_change": -0.0, + "population": 60169.16904360067 + }, + { + "local_authority_code": "S12000000012", + "local_authority_name": "Local Authority 12", + "x": 11, + "y": 0, + "average_household_income_change": -538.9775499790547, + "relative_household_income_change": 1e-12, + "population": 134657.14469719745 + }, + { + "local_authority_code": "S12000000013", + "local_authority_name": "Local Authority 13", + "x": 12, + "y": 0, + "average_household_income_change": -521.6966583670524, + "relative_household_income_change": -0.0, + "population": 84326.3910283849 + }, + { + "local_authority_code": "S12000000014", + "local_authority_name": "Local Authority 14", + "x": 13, + "y": 0, + "average_household_income_change": -403.72167393983773, + "relative_household_income_change": 1e-12, + "population": 90121.64285325728 + }, + { + "local_authority_code": "S12000000015", + "local_authority_name": "Local Authority 15", + "x": null, + "y": null, + "average_household_income_change": -1992.3987578717731, + "relative_household_income_change": 0.5390980006995861, + "population": 57146.25648990415 + }, + { + "local_authority_code": "S12000000016", + "local_authority_name": "Local Authority 16", + "x": 15, + "y": 0, + "average_household_income_change": 1912.9330818653293, + "relative_household_income_change": -3.5e-9, + "population": 61630.540132526454 + }, + { + "local_authority_code": "S12000000017", + "local_authority_name": "Local Authority 17", + "x": 16, + "y": 0, + "average_household_income_change": 676.9488735769369, + "relative_household_income_change": 0.22230810403099188, + "population": 83264.51133432586 + }, + { + "local_authority_code": "S12000000018", + "local_authority_name": "Local Authority 18", + "x": 17, + "y": 0, + "average_household_income_change": 736.3951699342284, + "relative_household_income_change": -3.5e-9, + "population": 60421.1365110476 + }, + { + "local_authority_code": "S12000000019", + "local_authority_name": "Local Authority 19", + "x": 18, + "y": 0, + "average_household_income_change": -892.5830346459045, + "relative_household_income_change": -3.5e-9, + "population": 149136.34982537729 + }, + { + "local_authority_code": "S12000000020", + "local_authority_name": "Local Authority 20", + "x": 19, + "y": 0, + "average_household_income_change": 1871.832185732079, + "relative_household_income_change": 0.9315108544036715, + "population": 82551.14096226152 + }, + { + "local_authority_code": "S12000000021", + "local_authority_name": "Local Authority 21", + "x": 20, + "y": 0, + "average_household_income_change": -1775.413352074153, + "relative_household_income_change": -3.5e-9, + "population": 142543.40081999943 + }, + { + "local_authority_code": "S12000000022", + "local_authority_name": "Local Authority 22", + "x": null, + "y": null, + "average_household_income_change": 1677.2264729092446, + "relative_household_income_change": -3.5e-9, + "population": 119213.98806155729 + }, + { + "local_authority_code": "S12000000023", + "local_authority_name": "Local Authority 23", + "x": 22, + "y": 0, + "average_household_income_change": 253.80086043629467, + "relative_household_income_change": 0.16846215105615936, + "population": 131349.02471522414 + }, + { + "local_authority_code": "S12000000024", + "local_authority_name": "Local Authority 24", + "x": 23, + "y": 0, + "average_household_income_change": -1851.6056943936076, + "relative_household_income_change": -3.5e-9, + "population": 98606.58597465903 + }, + { + "local_authority_code": "S12000000025", + "local_authority_name": "Local Authority 25", + "x": 24, + "y": 0, + "average_household_income_change": -1449.2733170436777, + "relative_household_income_change": 1e-12, + "population": 57564.83061204634 + }, + { + "local_authority_code": "S12000000026", + "local_authority_name": "Local Authority 26", + "x": 25, + "y": 0, + "average_household_income_change": -872.6789126607173, + "relative_household_income_change": 1e-12, + "population": 125783.43975305068 + }, + { + "local_authority_code": "S12000000027", + "local_authority_name": "Local Authority 27", + "x": 26, + "y": 0, + "average_household_income_change": -1311.9645179858242, + "relative_household_income_change": 0.9912178495741759, + "population": 81237.5561149096 + }, + { + "local_authority_code": "S12000000028", + "local_authority_name": "Local Authority 28", + "x": 27, + "y": 0, + "average_household_income_change": 576.031133075289, + "relative_household_income_change": 0.7038678747725524, + "population": 141107.730757162 + }, + { + "local_authority_code": "S12000000029", + "local_authority_name": "Local Authority 29", + "x": null, + "y": null, + "average_household_income_change": 958.8442127965027, + "relative_household_income_change": 1e-12, + "population": 102312.94874371101 + }, + { + "local_authority_code": "S12000000030", + "local_authority_name": "Local Authority 30", + "x": 29, + "y": 0, + "average_household_income_change": -1343.8459777407186, + "relative_household_income_change": -3.5e-9, + "population": 103091.15965651689 + }, + { + "local_authority_code": "S12000000031", + "local_authority_name": "Local Authority 31", + "x": 30, + "y": 0, + "average_household_income_change": -26.106472316017815, + "relative_household_income_change": -3.5e-9, + "population": 139125.5993482639 + }, + { + "local_authority_code": "S12000000032", + "local_authority_name": "Local Authority 32", + "x": 0, + "y": 1, + "average_household_income_change": 1875.5073255172429, + "relative_household_income_change": 1e-12, + "population": 52821.895044486846 + } + ], + "congressional_district_impact": null, + "cliff_impact": null +} diff --git a/libs/policyengine-simulation-persistence/tests/fixtures/economy_results/uk_national_2026.json b/libs/policyengine-simulation-persistence/tests/fixtures/economy_results/uk_national_2026.json new file mode 100644 index 000000000..726c2d974 --- /dev/null +++ b/libs/policyengine-simulation-persistence/tests/fixtures/economy_results/uk_national_2026.json @@ -0,0 +1,9466 @@ +{ + "spm_provenance": null, + "model_version": "2.62.1", + "data_version": "1.30.2", + "budget": { + "tax_revenue_impact": 48357397852.14588, + "state_tax_revenue_impact": 0.0, + "benefit_spending_impact": 59038713113.13933, + "budgetary_impact": 24580338977.940384, + "households": 138849005.675541, + "baseline_net_income": 12479797149479.861 + }, + "detailed_budget": { + "income_tax": { + "baseline": 844649993.330834, + "reform": -941989543.4327705, + "difference": -68754691.2437893 + }, + "national_insurance": { + "baseline": 886713433.9966273, + "reform": 297949106.2738484, + "difference": 801800983.5012454 + }, + "universal_credit": { + "baseline": -773588070.6937113, + "reform": -61861904.43567252, + "difference": -506854334.7603394 + } + }, + "decile": { + "average": { + "1": 262.5651554155826, + "2": 443.6471275686047, + "3": -2921.314862466587, + "4": -1699.621197216911, + "5": -1323.1058039333382, + "6": 2498.0722308513114, + "7": 1594.3527097748504, + "8": -2042.3747258517706, + "9": 1782.8819485872268, + "10": -2167.395489606581 + }, + "relative": { + "1": -0.0, + "2": 0.0, + "3": -0.0, + "4": -0.0, + "5": 1e-12, + "6": -0.0, + "7": -0.0, + "8": -0.0, + "9": -3.5e-9, + "10": 1e-12 + } + }, + "inequality": { + "gini": { + "baseline": 0.4149067116227452, + "reform": 0.9357926558382951 + }, + "top_10_pct_share": { + "baseline": 0.26381193894997024, + "reform": 0.33185448722063815 + }, + "top_1_pct_share": { + "baseline": 0.8174003109567611, + "reform": 0.5861412585033708 + } + }, + "poverty": { + "poverty": { + "child": { + "baseline": 0.5959789505447018, + "reform": 0.7076761524222557 + }, + "adult": { + "baseline": 0.06602245055107714, + "reform": 0.35535135729996914 + }, + "senior": { + "baseline": 0.3060642591174333, + "reform": 0.6964198076411567 + }, + "all": { + "baseline": 0.18477324009849416, + "reform": 0.47253834981224785 + } + }, + "deep_poverty": { + "child": { + "baseline": 0.17612008047849625, + "reform": 0.25618183594271204 + }, + "adult": { + "baseline": 0.939011804929864, + "reform": 0.9492204766705261 + }, + "senior": { + "baseline": 0.35764406505883395, + "reform": 0.4042940811668897 + }, + "all": { + "baseline": 0.5490659459511809, + "reform": 0.4188272384269869 + } + } + }, + "poverty_by_gender": { + "poverty": { + "male": { + "baseline": 0.37636541261165457, + "reform": 0.8412340954622506 + }, + "female": { + "baseline": 0.45282225345616867, + "reform": 0.7077582566508612 + } + }, + "deep_poverty": { + "male": { + "baseline": 0.6237130310772351, + "reform": 0.954394476089788 + }, + "female": { + "baseline": 0.11902055707377501, + "reform": 0.24608679063361372 + } + } + }, + "poverty_by_race": null, + "intra_decile": { + "deciles": { + "Gain more than 5%": [ + 0.8194931666705297, + 0.46220536041544236, + 0.5124960121124476, + 0.8927110919706659, + 0.25089395624103406, + 0.46284975937048245, + 0.5897633712619398, + 0.7809871494563421, + 0.3672972162045115, + 0.29586380747431196 + ], + "Gain less than 5%": [ + 0.43297668506056197, + 0.9783414907096316, + 0.20848339304879704, + 0.5128800541969205, + 0.3626254865384637, + 0.14819563433497784, + 0.27567637655286203, + 0.702606734224737, + 0.09207334602214667, + 0.6859658309578894 + ], + "No change": [ + 0.30617106838135244, + 0.7987736171349602, + 0.6268057685261074, + 0.7211350402919544, + 0.30930358169024297, + 0.4837937739605416, + 0.7201288197081697, + 0.08095823218449283, + 0.6006492118055428, + 0.9236068159780504 + ], + "Lose less than 5%": [ + 0.03182648299140178, + 0.7405584945824758, + 0.34383290131610267, + 0.2502088580702625, + 0.6509664388131893, + 0.14562901896020186, + 0.9790506207650106, + 0.6383243727141709, + 0.8016644306001379, + 0.3341852936031615 + ], + "Lose more than 5%": [ + 0.2070598910046504, + 0.9813004861151011, + 0.5640476118758213, + 0.13277698777913516, + 0.896496018678021, + 0.41382241328530467, + 0.16882086123939744, + 0.37299762777421874, + 0.05877061817596774, + 0.4206458203108081 + ] + }, + "all": { + "Gain more than 5%": 0.14120240847136756, + "Gain less than 5%": 0.9220033436961468, + "No change": 0.620401984842514, + "Lose less than 5%": 0.16928990912443076, + "Lose more than 5%": 0.5221943516547977 + } + }, + "wealth_decile": { + "average": { + "1": 2760.7880601954007, + "2": 1133.034276791141, + "3": -1093.786486430059, + "4": -1355.7868171771192, + "5": -179.51504571187195, + "6": 2411.162815086828, + "7": -2324.637902811137, + "8": 1932.3300267035227, + "9": 190.5111354507152, + "10": -1923.6226099596192 + }, + "relative": { + "1": 1e-12, + "2": -3.5e-9, + "3": 0.2723101341365193, + "4": 1e-12, + "5": 1e-12, + "6": 0.0, + "7": 1e-12, + "8": 1e-12, + "9": 1e-12, + "10": 1e-12 + } + }, + "intra_wealth_decile": { + "deciles": { + "Gain more than 5%": [ + 0.9568854268308546, + 0.3400733891851615, + 0.17864939257994905, + 0.8518219963578928, + 0.47430384566628103, + 0.7737170178494772, + 0.3259049331519225, + 0.27368510859414175, + 0.28882651639491064, + 0.5003491241293917 + ], + "Gain less than 5%": [ + 0.6736381411375548, + 0.3565706338575818, + 0.2738756510918071, + 0.3455818350451242, + 0.9375151830031623, + 0.4084690239283826, + 0.9223332318878142, + 0.1724730198823753, + 0.8669714680935215, + 0.4497840700754686 + ], + "No change": [ + 0.3642746877410745, + 0.3343392574648516, + 0.14185820914313252, + 0.980204821871017, + 0.19865319756135547, + 0.36202891869382325, + 0.8538547938856402, + 0.2828581980722068, + 0.07883672952418375, + 0.6708582992133008 + ], + "Lose less than 5%": [ + 0.4166333688186612, + 0.6167804507938893, + 0.9362248151067294, + 0.5164551859017925, + 0.9364310981392266, + 0.3026660950760326, + 0.553207820465451, + 0.8671281385188301, + 0.27070607036660954, + 0.9960168155105562 + ], + "Lose more than 5%": [ + 0.1955988568069269, + 0.5864482182343931, + 0.6240718189635653, + 0.18074274971364557, + 0.7589971548762711, + 0.18053314559806255, + 0.7184623333950467, + 0.9864683931439034, + 0.9797599556017115, + 0.1657454822521135 + ] + }, + "all": { + "Gain more than 5%": 0.891809859376601, + "Gain less than 5%": 0.11082883415632572, + "No change": 0.9679805128391624, + "Lose less than 5%": 0.48266186709225245, + "Lose more than 5%": 0.5483207407270189 + } + }, + "labor_supply_response": { + "substitution_lsr": -512964474.581326, + "income_lsr": 4417979.006311912, + "relative_lsr": { + "income": -0.0, + "substitution": 1e-12 + }, + "total_change": 852714849.5207293, + "revenue_change": -205242491.53897566, + "decile": { + "average": { + "income": { + "1": 935.7357839289454, + "2": 462.94383251575465, + "3": 96.23021667461119, + "4": 257.8467628719523, + "5": 172.12874681714885, + "6": -279.55778856918556, + "7": 993.4358936204936, + "8": -192.21213911130343, + "9": 967.6904232442824, + "10": 705.1466422363058 + }, + "substitution": { + "1": -943.3107891837828, + "2": -483.5956687839016, + "3": -44.47179025453374, + "4": 629.1927835860174, + "5": -644.736925553173, + "6": 231.68117254507402, + "7": -265.58121369712893, + "8": 571.3578431812651, + "9": 852.8503903153766, + "10": 524.2353774411259 + } + }, + "relative": { + "income": { + "1": -613.4186720210399, + "2": 520.5759410481696, + "3": -123.67540662945076, + "4": 674.444469332411, + "5": -59.755876469413934, + "6": 813.2868269175722, + "7": 972.3328516817755, + "8": 648.4356491100871, + "9": 652.161311150754, + "10": 638.0759148741213 + }, + "substitution": { + "1": 184.25451379479486, + "2": -650.2800501994182, + "3": 972.4071166773432, + "4": -71.64740663837277, + "5": -967.6036583871357, + "6": -131.08238678931406, + "7": -170.0468523564045, + "8": -598.2616845096542, + "9": 920.7243378432994, + "10": -775.9508418317278 + } + } + }, + "hours": { + "baseline": 8082872177.716915, + "reform": 995217975.6411117, + "change": -6427763.165620004, + "income_effect": -2834583.8204234396, + "substitution_effect": -993619.1893709556 + } + }, + "constituency_impact": [ + { + "constituency_code": "E14000000001", + "constituency_name": "Constituency 1", + "x": null, + "y": null, + "average_household_income_change": 1913.4194334839867, + "relative_household_income_change": 0.05452265501045739, + "population": 98386.17433244424 + }, + { + "constituency_code": "E14000000002", + "constituency_name": "Constituency 2", + "x": 1, + "y": 0, + "average_household_income_change": 1766.892980665629, + "relative_household_income_change": -0.0, + "population": 65914.779888391 + }, + { + "constituency_code": "E14000000003", + "constituency_name": "Constituency 3", + "x": 2, + "y": 0, + "average_household_income_change": 1979.1207253554358, + "relative_household_income_change": -0.0, + "population": 146525.5307749652 + }, + { + "constituency_code": "E14000000004", + "constituency_name": "Constituency 4", + "x": 3, + "y": 0, + "average_household_income_change": -241.7288234592716, + "relative_household_income_change": 0.0011309834882184955, + "population": 88718.4004768281 + }, + { + "constituency_code": "E14000000005", + "constituency_name": "Constituency 5", + "x": 4, + "y": 0, + "average_household_income_change": -1955.5874396191487, + "relative_household_income_change": -0.0, + "population": 98185.74579851818 + }, + { + "constituency_code": "E14000000006", + "constituency_name": "Constituency 6", + "x": 5, + "y": 0, + "average_household_income_change": 500.32029373535636, + "relative_household_income_change": -3.5e-9, + "population": 91600.07992596942 + }, + { + "constituency_code": "E14000000007", + "constituency_name": "Constituency 7", + "x": 6, + "y": 0, + "average_household_income_change": 1429.7516356012716, + "relative_household_income_change": -3.5e-9, + "population": 144767.61377682418 + }, + { + "constituency_code": "E14000000008", + "constituency_name": "Constituency 8", + "x": null, + "y": null, + "average_household_income_change": 303.4651099150256, + "relative_household_income_change": 1e-12, + "population": 104370.43989569198 + }, + { + "constituency_code": "E14000000009", + "constituency_name": "Constituency 9", + "x": 8, + "y": 0, + "average_household_income_change": -1430.855530589559, + "relative_household_income_change": 0.5204399501519741, + "population": 120355.88560972406 + }, + { + "constituency_code": "E14000000010", + "constituency_name": "Constituency 10", + "x": 9, + "y": 0, + "average_household_income_change": -879.9490006950084, + "relative_household_income_change": -3.5e-9, + "population": 131238.10258698944 + }, + { + "constituency_code": "E14000000011", + "constituency_name": "Constituency 11", + "x": 10, + "y": 0, + "average_household_income_change": 626.256099809495, + "relative_household_income_change": 0.0, + "population": 70186.41755304152 + }, + { + "constituency_code": "E14000000012", + "constituency_name": "Constituency 12", + "x": 11, + "y": 0, + "average_household_income_change": -1182.6118333676216, + "relative_household_income_change": -3.5e-9, + "population": 95668.57228708114 + }, + { + "constituency_code": "E14000000013", + "constituency_name": "Constituency 13", + "x": 12, + "y": 0, + "average_household_income_change": -1313.786038062641, + "relative_household_income_change": -0.0, + "population": 58717.759794404556 + }, + { + "constituency_code": "E14000000014", + "constituency_name": "Constituency 14", + "x": 13, + "y": 0, + "average_household_income_change": 522.77933357376, + "relative_household_income_change": -0.0, + "population": 105485.06719596757 + }, + { + "constituency_code": "E14000000015", + "constituency_name": "Constituency 15", + "x": null, + "y": null, + "average_household_income_change": -283.01292441674696, + "relative_household_income_change": -0.0, + "population": 64972.126858879885 + }, + { + "constituency_code": "E14000000016", + "constituency_name": "Constituency 16", + "x": 15, + "y": 0, + "average_household_income_change": 1838.9633545881009, + "relative_household_income_change": 0.8530915769275014, + "population": 95302.11433575382 + }, + { + "constituency_code": "E14000000017", + "constituency_name": "Constituency 17", + "x": 16, + "y": 0, + "average_household_income_change": 1807.801459835364, + "relative_household_income_change": -0.0, + "population": 102662.03335442903 + }, + { + "constituency_code": "E14000000018", + "constituency_name": "Constituency 18", + "x": 17, + "y": 0, + "average_household_income_change": 1302.60169056573, + "relative_household_income_change": -3.5e-9, + "population": 102906.71208383882 + }, + { + "constituency_code": "E14000000019", + "constituency_name": "Constituency 19", + "x": 18, + "y": 0, + "average_household_income_change": 684.7633481422735, + "relative_household_income_change": -0.0, + "population": 54222.044888242985 + }, + { + "constituency_code": "E14000000020", + "constituency_name": "Constituency 20", + "x": 19, + "y": 0, + "average_household_income_change": 488.326844642812, + "relative_household_income_change": 1e-12, + "population": 57009.64734391624 + }, + { + "constituency_code": "E14000000021", + "constituency_name": "Constituency 21", + "x": 20, + "y": 0, + "average_household_income_change": -1826.7030677545897, + "relative_household_income_change": -0.0, + "population": 60607.39438166653 + }, + { + "constituency_code": "E14000000022", + "constituency_name": "Constituency 22", + "x": null, + "y": null, + "average_household_income_change": 941.3762870336742, + "relative_household_income_change": 0.0, + "population": 65082.17476365694 + }, + { + "constituency_code": "E14000000023", + "constituency_name": "Constituency 23", + "x": 22, + "y": 0, + "average_household_income_change": -166.75177258327656, + "relative_household_income_change": 0.046193690494361284, + "population": 65296.52386416295 + }, + { + "constituency_code": "E14000000024", + "constituency_name": "Constituency 24", + "x": 23, + "y": 0, + "average_household_income_change": -1397.6894273125588, + "relative_household_income_change": -0.0, + "population": 82358.07690579105 + }, + { + "constituency_code": "E14000000025", + "constituency_name": "Constituency 25", + "x": 24, + "y": 0, + "average_household_income_change": -1166.7618642594055, + "relative_household_income_change": -0.0, + "population": 58056.9265454936 + }, + { + "constituency_code": "E14000000026", + "constituency_name": "Constituency 26", + "x": 25, + "y": 0, + "average_household_income_change": 1103.7650090255484, + "relative_household_income_change": 0.0, + "population": 138706.63023281284 + }, + { + "constituency_code": "E14000000027", + "constituency_name": "Constituency 27", + "x": 26, + "y": 0, + "average_household_income_change": 1390.0054628643597, + "relative_household_income_change": 0.19212060592154867, + "population": 82600.12292622661 + }, + { + "constituency_code": "E14000000028", + "constituency_name": "Constituency 28", + "x": 27, + "y": 0, + "average_household_income_change": -550.2630807394695, + "relative_household_income_change": 0.0, + "population": 66882.2129669484 + }, + { + "constituency_code": "E14000000029", + "constituency_name": "Constituency 29", + "x": null, + "y": null, + "average_household_income_change": -376.0757965327994, + "relative_household_income_change": -0.0, + "population": 131755.4233245176 + }, + { + "constituency_code": "E14000000030", + "constituency_name": "Constituency 30", + "x": 29, + "y": 0, + "average_household_income_change": -1807.9185090422197, + "relative_household_income_change": 1e-12, + "population": 76098.68374829671 + }, + { + "constituency_code": "E14000000031", + "constituency_name": "Constituency 31", + "x": 30, + "y": 0, + "average_household_income_change": 1181.9497773458966, + "relative_household_income_change": 0.6841082101901497, + "population": 97597.70307584907 + }, + { + "constituency_code": "E14000000032", + "constituency_name": "Constituency 32", + "x": 0, + "y": 1, + "average_household_income_change": -1978.4430390331474, + "relative_household_income_change": 0.9698872181871829, + "population": 119385.14894333272 + }, + { + "constituency_code": "E14000000033", + "constituency_name": "Constituency 33", + "x": 1, + "y": 1, + "average_household_income_change": -927.783221433379, + "relative_household_income_change": 0.6556433745742408, + "population": 56063.824089337824 + }, + { + "constituency_code": "E14000000034", + "constituency_name": "Constituency 34", + "x": 2, + "y": 1, + "average_household_income_change": 768.3322762327842, + "relative_household_income_change": -0.0, + "population": 146677.93429020338 + }, + { + "constituency_code": "E14000000035", + "constituency_name": "Constituency 35", + "x": 3, + "y": 1, + "average_household_income_change": -1729.540058696729, + "relative_household_income_change": 0.7274163682705892, + "population": 141793.29131328876 + }, + { + "constituency_code": "E14000000036", + "constituency_name": "Constituency 36", + "x": null, + "y": null, + "average_household_income_change": -846.208132023205, + "relative_household_income_change": 0.8483280186604456, + "population": 67143.97059156044 + }, + { + "constituency_code": "E14000000037", + "constituency_name": "Constituency 37", + "x": 5, + "y": 1, + "average_household_income_change": -1936.6401638583116, + "relative_household_income_change": -0.0, + "population": 61672.55464881558 + }, + { + "constituency_code": "E14000000038", + "constituency_name": "Constituency 38", + "x": 6, + "y": 1, + "average_household_income_change": -628.8145345899005, + "relative_household_income_change": 1e-12, + "population": 132985.11142986448 + }, + { + "constituency_code": "E14000000039", + "constituency_name": "Constituency 39", + "x": 7, + "y": 1, + "average_household_income_change": -1777.3930705516138, + "relative_household_income_change": 0.5276137376872608, + "population": 127787.70788799871 + }, + { + "constituency_code": "E14000000040", + "constituency_name": "Constituency 40", + "x": 8, + "y": 1, + "average_household_income_change": -939.8753120050504, + "relative_household_income_change": 1e-12, + "population": 102035.60610842177 + }, + { + "constituency_code": "E14000000041", + "constituency_name": "Constituency 41", + "x": 9, + "y": 1, + "average_household_income_change": 1996.581447976601, + "relative_household_income_change": -3.5e-9, + "population": 62516.54815850142 + }, + { + "constituency_code": "E14000000042", + "constituency_name": "Constituency 42", + "x": 10, + "y": 1, + "average_household_income_change": -1900.8595839448872, + "relative_household_income_change": 0.5897475984561965, + "population": 68761.98222160083 + }, + { + "constituency_code": "E14000000043", + "constituency_name": "Constituency 43", + "x": null, + "y": null, + "average_household_income_change": -653.4834431595642, + "relative_household_income_change": -0.0, + "population": 51348.43227638599 + }, + { + "constituency_code": "E14000000044", + "constituency_name": "Constituency 44", + "x": 12, + "y": 1, + "average_household_income_change": -1508.6955230422716, + "relative_household_income_change": -3.5e-9, + "population": 120576.53453498721 + }, + { + "constituency_code": "E14000000045", + "constituency_name": "Constituency 45", + "x": 13, + "y": 1, + "average_household_income_change": -1361.5842774754205, + "relative_household_income_change": -0.0, + "population": 57742.78406589189 + }, + { + "constituency_code": "E14000000046", + "constituency_name": "Constituency 46", + "x": 14, + "y": 1, + "average_household_income_change": -353.29379038553776, + "relative_household_income_change": -3.5e-9, + "population": 126551.15106107993 + }, + { + "constituency_code": "E14000000047", + "constituency_name": "Constituency 47", + "x": 15, + "y": 1, + "average_household_income_change": -1672.7900598157826, + "relative_household_income_change": -3.5e-9, + "population": 144378.29471218237 + }, + { + "constituency_code": "E14000000048", + "constituency_name": "Constituency 48", + "x": 16, + "y": 1, + "average_household_income_change": 758.8777810416283, + "relative_household_income_change": -0.0, + "population": 115096.92998669462 + }, + { + "constituency_code": "E14000000049", + "constituency_name": "Constituency 49", + "x": 17, + "y": 1, + "average_household_income_change": -1559.0227122087886, + "relative_household_income_change": 1e-12, + "population": 106776.20642347747 + }, + { + "constituency_code": "E14000000050", + "constituency_name": "Constituency 50", + "x": null, + "y": null, + "average_household_income_change": 789.7011489873229, + "relative_household_income_change": 0.0, + "population": 127076.9781852224 + }, + { + "constituency_code": "E14000000051", + "constituency_name": "Constituency 51", + "x": 19, + "y": 1, + "average_household_income_change": 158.31787373201277, + "relative_household_income_change": -3.5e-9, + "population": 77473.57871872757 + }, + { + "constituency_code": "E14000000052", + "constituency_name": "Constituency 52", + "x": 20, + "y": 1, + "average_household_income_change": 545.7397560998354, + "relative_household_income_change": 1e-12, + "population": 123149.70477872998 + }, + { + "constituency_code": "E14000000053", + "constituency_name": "Constituency 53", + "x": 21, + "y": 1, + "average_household_income_change": -1989.6254923025228, + "relative_household_income_change": -3.5e-9, + "population": 138656.01900310494 + }, + { + "constituency_code": "E14000000054", + "constituency_name": "Constituency 54", + "x": 22, + "y": 1, + "average_household_income_change": -1309.1057736433424, + "relative_household_income_change": -3.5e-9, + "population": 105353.90714704938 + }, + { + "constituency_code": "E14000000055", + "constituency_name": "Constituency 55", + "x": 23, + "y": 1, + "average_household_income_change": -910.2455237869887, + "relative_household_income_change": 1e-12, + "population": 92014.34882548383 + }, + { + "constituency_code": "E14000000056", + "constituency_name": "Constituency 56", + "x": 24, + "y": 1, + "average_household_income_change": -1893.3912344738899, + "relative_household_income_change": 1e-12, + "population": 62745.988954386 + }, + { + "constituency_code": "E14000000057", + "constituency_name": "Constituency 57", + "x": null, + "y": null, + "average_household_income_change": -233.6121744507622, + "relative_household_income_change": 0.0, + "population": 80531.25807633463 + }, + { + "constituency_code": "E14000000058", + "constituency_name": "Constituency 58", + "x": 26, + "y": 1, + "average_household_income_change": 1723.235202484926, + "relative_household_income_change": 0.0, + "population": 62353.128351459265 + }, + { + "constituency_code": "E14000000059", + "constituency_name": "Constituency 59", + "x": 27, + "y": 1, + "average_household_income_change": -989.7236409560759, + "relative_household_income_change": 0.0, + "population": 82844.38317215677 + }, + { + "constituency_code": "E14000000060", + "constituency_name": "Constituency 60", + "x": 28, + "y": 1, + "average_household_income_change": 1854.5416655237204, + "relative_household_income_change": 0.9442223354304049, + "population": 118156.82723049479 + }, + { + "constituency_code": "E14000000061", + "constituency_name": "Constituency 61", + "x": 29, + "y": 1, + "average_household_income_change": -1245.781306574102, + "relative_household_income_change": 0.10992560517344074, + "population": 121532.76585539519 + }, + { + "constituency_code": "E14000000062", + "constituency_name": "Constituency 62", + "x": 30, + "y": 1, + "average_household_income_change": 447.36217162511946, + "relative_household_income_change": -0.0, + "population": 90921.07222144597 + }, + { + "constituency_code": "E14000000063", + "constituency_name": "Constituency 63", + "x": 0, + "y": 2, + "average_household_income_change": 1977.7483196114183, + "relative_household_income_change": -0.0, + "population": 145071.50512103183 + }, + { + "constituency_code": "E14000000064", + "constituency_name": "Constituency 64", + "x": null, + "y": null, + "average_household_income_change": 836.8416626768695, + "relative_household_income_change": 0.3827069272720205, + "population": 80491.97355110932 + }, + { + "constituency_code": "E14000000065", + "constituency_name": "Constituency 65", + "x": 2, + "y": 2, + "average_household_income_change": -646.4321678071556, + "relative_household_income_change": 0.6461356256019504, + "population": 82414.78499033627 + }, + { + "constituency_code": "E14000000066", + "constituency_name": "Constituency 66", + "x": 3, + "y": 2, + "average_household_income_change": -269.67895991541104, + "relative_household_income_change": 0.0, + "population": 107324.65179222659 + }, + { + "constituency_code": "E14000000067", + "constituency_name": "Constituency 67", + "x": 4, + "y": 2, + "average_household_income_change": -766.5123752502452, + "relative_household_income_change": 0.5355509950976918, + "population": 121437.09706568257 + }, + { + "constituency_code": "E14000000068", + "constituency_name": "Constituency 68", + "x": 5, + "y": 2, + "average_household_income_change": 1137.686580720843, + "relative_household_income_change": 1e-12, + "population": 105524.95460769659 + }, + { + "constituency_code": "E14000000069", + "constituency_name": "Constituency 69", + "x": 6, + "y": 2, + "average_household_income_change": -1706.7509137766676, + "relative_household_income_change": 1e-12, + "population": 89192.43391252482 + }, + { + "constituency_code": "E14000000070", + "constituency_name": "Constituency 70", + "x": 7, + "y": 2, + "average_household_income_change": 290.0010881146389, + "relative_household_income_change": 0.0, + "population": 105626.728450015 + }, + { + "constituency_code": "E14000000071", + "constituency_name": "Constituency 71", + "x": null, + "y": null, + "average_household_income_change": -1040.696959610678, + "relative_household_income_change": -0.0, + "population": 113268.62178290357 + }, + { + "constituency_code": "E14000000072", + "constituency_name": "Constituency 72", + "x": 9, + "y": 2, + "average_household_income_change": -635.9903698714575, + "relative_household_income_change": 0.0, + "population": 56501.415493660155 + }, + { + "constituency_code": "E14000000073", + "constituency_name": "Constituency 73", + "x": 10, + "y": 2, + "average_household_income_change": -1854.3994611686637, + "relative_household_income_change": -3.5e-9, + "population": 102254.43848842036 + }, + { + "constituency_code": "E14000000074", + "constituency_name": "Constituency 74", + "x": 11, + "y": 2, + "average_household_income_change": -90.81831049588996, + "relative_household_income_change": -0.0, + "population": 80954.3654644868 + }, + { + "constituency_code": "E14000000075", + "constituency_name": "Constituency 75", + "x": 12, + "y": 2, + "average_household_income_change": -427.27767032936634, + "relative_household_income_change": -0.0, + "population": 108071.93041754297 + }, + { + "constituency_code": "E14000000076", + "constituency_name": "Constituency 76", + "x": 13, + "y": 2, + "average_household_income_change": -127.30625312048672, + "relative_household_income_change": 1e-12, + "population": 117467.31956453231 + }, + { + "constituency_code": "E14000000077", + "constituency_name": "Constituency 77", + "x": 14, + "y": 2, + "average_household_income_change": 1230.791969781145, + "relative_household_income_change": -3.5e-9, + "population": 148070.92092286033 + }, + { + "constituency_code": "E14000000078", + "constituency_name": "Constituency 78", + "x": null, + "y": null, + "average_household_income_change": 961.4866644663272, + "relative_household_income_change": 0.0, + "population": 102372.13679715489 + }, + { + "constituency_code": "E14000000079", + "constituency_name": "Constituency 79", + "x": 16, + "y": 2, + "average_household_income_change": 558.5324418439463, + "relative_household_income_change": 0.0, + "population": 80215.38631281923 + }, + { + "constituency_code": "E14000000080", + "constituency_name": "Constituency 80", + "x": 17, + "y": 2, + "average_household_income_change": 1454.8518394753298, + "relative_household_income_change": -3.5e-9, + "population": 96129.88324153051 + }, + { + "constituency_code": "E14000000081", + "constituency_name": "Constituency 81", + "x": 18, + "y": 2, + "average_household_income_change": -1995.8700108929918, + "relative_household_income_change": -0.0, + "population": 117530.89833643334 + }, + { + "constituency_code": "E14000000082", + "constituency_name": "Constituency 82", + "x": 19, + "y": 2, + "average_household_income_change": -658.2352550207946, + "relative_household_income_change": 0.0, + "population": 91829.77214309663 + }, + { + "constituency_code": "E14000000083", + "constituency_name": "Constituency 83", + "x": 20, + "y": 2, + "average_household_income_change": 188.26514420342198, + "relative_household_income_change": 1e-12, + "population": 66881.29106756164 + }, + { + "constituency_code": "E14000000084", + "constituency_name": "Constituency 84", + "x": 21, + "y": 2, + "average_household_income_change": 345.8706592634417, + "relative_household_income_change": 1e-12, + "population": 56080.595832210536 + }, + { + "constituency_code": "E14000000085", + "constituency_name": "Constituency 85", + "x": null, + "y": null, + "average_household_income_change": -1673.2370069478045, + "relative_household_income_change": -3.5e-9, + "population": 132596.5586019211 + }, + { + "constituency_code": "E14000000086", + "constituency_name": "Constituency 86", + "x": 23, + "y": 2, + "average_household_income_change": -127.34504781316191, + "relative_household_income_change": -0.0, + "population": 108141.83862604474 + }, + { + "constituency_code": "E14000000087", + "constituency_name": "Constituency 87", + "x": 24, + "y": 2, + "average_household_income_change": -1334.0686487199855, + "relative_household_income_change": -0.0, + "population": 64208.1603564976 + }, + { + "constituency_code": "E14000000088", + "constituency_name": "Constituency 88", + "x": 25, + "y": 2, + "average_household_income_change": 902.6394274385958, + "relative_household_income_change": 0.0, + "population": 96826.50596375517 + }, + { + "constituency_code": "E14000000089", + "constituency_name": "Constituency 89", + "x": 26, + "y": 2, + "average_household_income_change": -599.3606996628422, + "relative_household_income_change": 1e-12, + "population": 73495.08876254177 + }, + { + "constituency_code": "E14000000090", + "constituency_name": "Constituency 90", + "x": 27, + "y": 2, + "average_household_income_change": 1736.004403868296, + "relative_household_income_change": 0.0, + "population": 72671.92918410263 + }, + { + "constituency_code": "E14000000091", + "constituency_name": "Constituency 91", + "x": 28, + "y": 2, + "average_household_income_change": -183.77106589635696, + "relative_household_income_change": 0.43806674434402326, + "population": 114528.8279064073 + }, + { + "constituency_code": "E14000000092", + "constituency_name": "Constituency 92", + "x": null, + "y": null, + "average_household_income_change": 748.6525324379664, + "relative_household_income_change": -0.0, + "population": 115796.32346101322 + }, + { + "constituency_code": "E14000000093", + "constituency_name": "Constituency 93", + "x": 30, + "y": 2, + "average_household_income_change": 879.2492998869496, + "relative_household_income_change": 0.9812499439637178, + "population": 72504.37458082387 + }, + { + "constituency_code": "E14000000094", + "constituency_name": "Constituency 94", + "x": 0, + "y": 3, + "average_household_income_change": 88.85783739759168, + "relative_household_income_change": -0.0, + "population": 98878.56897288407 + }, + { + "constituency_code": "E14000000095", + "constituency_name": "Constituency 95", + "x": 1, + "y": 3, + "average_household_income_change": 1647.1065576113149, + "relative_household_income_change": 1e-12, + "population": 143872.09389896045 + }, + { + "constituency_code": "E14000000096", + "constituency_name": "Constituency 96", + "x": 2, + "y": 3, + "average_household_income_change": 1000.4981954112053, + "relative_household_income_change": 0.2974922761899098, + "population": 95587.75122445801 + }, + { + "constituency_code": "E14000000097", + "constituency_name": "Constituency 97", + "x": 3, + "y": 3, + "average_household_income_change": 662.0195760611831, + "relative_household_income_change": 0.24624440427242644, + "population": 74596.90118944892 + }, + { + "constituency_code": "E14000000098", + "constituency_name": "Constituency 98", + "x": 4, + "y": 3, + "average_household_income_change": -969.5701848891072, + "relative_household_income_change": -3.5e-9, + "population": 119650.20784516653 + }, + { + "constituency_code": "E14000000099", + "constituency_name": "Constituency 99", + "x": null, + "y": null, + "average_household_income_change": 1640.698557999197, + "relative_household_income_change": 1e-12, + "population": 65758.83878464595 + }, + { + "constituency_code": "E14000000100", + "constituency_name": "Constituency 100", + "x": 6, + "y": 3, + "average_household_income_change": -1807.137308302433, + "relative_household_income_change": 0.20830978548035517, + "population": 130632.53138420294 + }, + { + "constituency_code": "E14000000101", + "constituency_name": "Constituency 101", + "x": 7, + "y": 3, + "average_household_income_change": 249.5946512422913, + "relative_household_income_change": 0.0, + "population": 117617.37454965772 + }, + { + "constituency_code": "E14000000102", + "constituency_name": "Constituency 102", + "x": 8, + "y": 3, + "average_household_income_change": 1704.7622150184222, + "relative_household_income_change": 0.040006378333672155, + "population": 91743.07750685193 + }, + { + "constituency_code": "E14000000103", + "constituency_name": "Constituency 103", + "x": 9, + "y": 3, + "average_household_income_change": 1323.0082082453052, + "relative_household_income_change": -0.0, + "population": 82625.82863494732 + }, + { + "constituency_code": "E14000000104", + "constituency_name": "Constituency 104", + "x": 10, + "y": 3, + "average_household_income_change": -548.9345688529448, + "relative_household_income_change": 0.0, + "population": 106252.55590308961 + }, + { + "constituency_code": "E14000000105", + "constituency_name": "Constituency 105", + "x": 11, + "y": 3, + "average_household_income_change": 1490.3340145481927, + "relative_household_income_change": -0.0, + "population": 52780.212642555765 + }, + { + "constituency_code": "E14000000106", + "constituency_name": "Constituency 106", + "x": null, + "y": null, + "average_household_income_change": -110.74050107692868, + "relative_household_income_change": -0.0, + "population": 132857.81166528582 + }, + { + "constituency_code": "E14000000107", + "constituency_name": "Constituency 107", + "x": 13, + "y": 3, + "average_household_income_change": 535.7247779833637, + "relative_household_income_change": 1e-12, + "population": 70233.9136272132 + }, + { + "constituency_code": "E14000000108", + "constituency_name": "Constituency 108", + "x": 14, + "y": 3, + "average_household_income_change": -1562.196706775103, + "relative_household_income_change": 1e-12, + "population": 57613.888020112136 + }, + { + "constituency_code": "E14000000109", + "constituency_name": "Constituency 109", + "x": 15, + "y": 3, + "average_household_income_change": -807.5046810198771, + "relative_household_income_change": 0.0, + "population": 59873.63482115029 + }, + { + "constituency_code": "E14000000110", + "constituency_name": "Constituency 110", + "x": 16, + "y": 3, + "average_household_income_change": 831.9248746300553, + "relative_household_income_change": 0.7884886691726886, + "population": 118598.10011798801 + }, + { + "constituency_code": "E14000000111", + "constituency_name": "Constituency 111", + "x": 17, + "y": 3, + "average_household_income_change": -1626.7832810843204, + "relative_household_income_change": 1e-12, + "population": 119305.13175442934 + }, + { + "constituency_code": "E14000000112", + "constituency_name": "Constituency 112", + "x": 18, + "y": 3, + "average_household_income_change": 1429.6328025898952, + "relative_household_income_change": 1e-12, + "population": 102121.6917442946 + }, + { + "constituency_code": "E14000000113", + "constituency_name": "Constituency 113", + "x": null, + "y": null, + "average_household_income_change": -1344.590914850559, + "relative_household_income_change": 0.0, + "population": 62858.80426314438 + }, + { + "constituency_code": "E14000000114", + "constituency_name": "Constituency 114", + "x": 20, + "y": 3, + "average_household_income_change": -1146.3259480815013, + "relative_household_income_change": 0.5837592442382298, + "population": 122906.79170362945 + }, + { + "constituency_code": "E14000000115", + "constituency_name": "Constituency 115", + "x": 21, + "y": 3, + "average_household_income_change": 898.8663515055783, + "relative_household_income_change": 0.0, + "population": 99534.98962730182 + }, + { + "constituency_code": "E14000000116", + "constituency_name": "Constituency 116", + "x": 22, + "y": 3, + "average_household_income_change": 1719.4014329329482, + "relative_household_income_change": -3.5e-9, + "population": 69591.52802599104 + }, + { + "constituency_code": "E14000000117", + "constituency_name": "Constituency 117", + "x": 23, + "y": 3, + "average_household_income_change": 562.4608552702921, + "relative_household_income_change": 0.0, + "population": 55842.24291191352 + }, + { + "constituency_code": "E14000000118", + "constituency_name": "Constituency 118", + "x": 24, + "y": 3, + "average_household_income_change": -1800.665380166868, + "relative_household_income_change": 0.0, + "population": 58657.962368604676 + }, + { + "constituency_code": "E14000000119", + "constituency_name": "Constituency 119", + "x": 25, + "y": 3, + "average_household_income_change": -1818.6883148220843, + "relative_household_income_change": -0.0, + "population": 137813.88099731703 + }, + { + "constituency_code": "E14000000120", + "constituency_name": "Constituency 120", + "x": null, + "y": null, + "average_household_income_change": 455.83119363301086, + "relative_household_income_change": 1e-12, + "population": 57970.009217312014 + }, + { + "constituency_code": "E14000000121", + "constituency_name": "Constituency 121", + "x": 27, + "y": 3, + "average_household_income_change": 1782.7850710537834, + "relative_household_income_change": 0.0, + "population": 143164.58131962447 + }, + { + "constituency_code": "E14000000122", + "constituency_name": "Constituency 122", + "x": 28, + "y": 3, + "average_household_income_change": -1321.9039327565874, + "relative_household_income_change": 0.541962411948292, + "population": 50457.04856292268 + }, + { + "constituency_code": "E14000000123", + "constituency_name": "Constituency 123", + "x": 29, + "y": 3, + "average_household_income_change": -1609.0297193715548, + "relative_household_income_change": 1e-12, + "population": 135630.50062274272 + }, + { + "constituency_code": "E14000000124", + "constituency_name": "Constituency 124", + "x": 30, + "y": 3, + "average_household_income_change": 1494.6489038444706, + "relative_household_income_change": -0.0, + "population": 86499.87244664696 + }, + { + "constituency_code": "E14000000125", + "constituency_name": "Constituency 125", + "x": 0, + "y": 4, + "average_household_income_change": -203.1025816503482, + "relative_household_income_change": -3.5e-9, + "population": 131450.3581071367 + }, + { + "constituency_code": "E14000000126", + "constituency_name": "Constituency 126", + "x": 1, + "y": 4, + "average_household_income_change": -1736.00876747027, + "relative_household_income_change": 1e-12, + "population": 77714.90708517047 + }, + { + "constituency_code": "E14000000127", + "constituency_name": "Constituency 127", + "x": null, + "y": null, + "average_household_income_change": 732.7271206158956, + "relative_household_income_change": 0.0, + "population": 62311.51182123555 + }, + { + "constituency_code": "E14000000128", + "constituency_name": "Constituency 128", + "x": 3, + "y": 4, + "average_household_income_change": 759.0741072953095, + "relative_household_income_change": 1e-12, + "population": 148750.0421308927 + }, + { + "constituency_code": "E14000000129", + "constituency_name": "Constituency 129", + "x": 4, + "y": 4, + "average_household_income_change": -112.66921174672939, + "relative_household_income_change": -0.0, + "population": 143434.03244226988 + }, + { + "constituency_code": "E14000000130", + "constituency_name": "Constituency 130", + "x": 5, + "y": 4, + "average_household_income_change": 691.029924028856, + "relative_household_income_change": 1e-12, + "population": 99922.79421022549 + }, + { + "constituency_code": "E14000000131", + "constituency_name": "Constituency 131", + "x": 6, + "y": 4, + "average_household_income_change": 1441.9814618812738, + "relative_household_income_change": -3.5e-9, + "population": 131523.50923887704 + }, + { + "constituency_code": "E14000000132", + "constituency_name": "Constituency 132", + "x": 7, + "y": 4, + "average_household_income_change": -1430.5752926829505, + "relative_household_income_change": -3.5e-9, + "population": 137924.9037228661 + }, + { + "constituency_code": "E14000000133", + "constituency_name": "Constituency 133", + "x": 8, + "y": 4, + "average_household_income_change": -534.625803263033, + "relative_household_income_change": 0.7529910574305773, + "population": 148437.97322438212 + }, + { + "constituency_code": "E14000000134", + "constituency_name": "Constituency 134", + "x": null, + "y": null, + "average_household_income_change": 61.61400773596615, + "relative_household_income_change": -0.0, + "population": 111496.92620513316 + }, + { + "constituency_code": "E14000000135", + "constituency_name": "Constituency 135", + "x": 10, + "y": 4, + "average_household_income_change": 1905.6857330111927, + "relative_household_income_change": -3.5e-9, + "population": 138584.5575915625 + }, + { + "constituency_code": "E14000000136", + "constituency_name": "Constituency 136", + "x": 11, + "y": 4, + "average_household_income_change": -1144.1054423786206, + "relative_household_income_change": 0.2928856424926053, + "population": 53197.31312326364 + }, + { + "constituency_code": "E14000000137", + "constituency_name": "Constituency 137", + "x": 12, + "y": 4, + "average_household_income_change": -1265.1713617127114, + "relative_household_income_change": -3.5e-9, + "population": 86572.81347329413 + }, + { + "constituency_code": "E14000000138", + "constituency_name": "Constituency 138", + "x": 13, + "y": 4, + "average_household_income_change": -519.7588256792973, + "relative_household_income_change": 1e-12, + "population": 71191.46671555749 + }, + { + "constituency_code": "E14000000139", + "constituency_name": "Constituency 139", + "x": 14, + "y": 4, + "average_household_income_change": 162.22254008254345, + "relative_household_income_change": 0.8858936695673891, + "population": 96442.4130437495 + }, + { + "constituency_code": "E14000000140", + "constituency_name": "Constituency 140", + "x": 15, + "y": 4, + "average_household_income_change": -242.46320601773473, + "relative_household_income_change": 0.0, + "population": 80110.23234374468 + }, + { + "constituency_code": "E14000000141", + "constituency_name": "Constituency 141", + "x": null, + "y": null, + "average_household_income_change": 816.202709092623, + "relative_household_income_change": 1e-12, + "population": 73590.60951765552 + }, + { + "constituency_code": "E14000000142", + "constituency_name": "Constituency 142", + "x": 17, + "y": 4, + "average_household_income_change": -833.1977474989549, + "relative_household_income_change": 0.0, + "population": 61505.33961873027 + }, + { + "constituency_code": "E14000000143", + "constituency_name": "Constituency 143", + "x": 18, + "y": 4, + "average_household_income_change": 1160.9421061865896, + "relative_household_income_change": 0.0, + "population": 115466.82296615103 + }, + { + "constituency_code": "E14000000144", + "constituency_name": "Constituency 144", + "x": 19, + "y": 4, + "average_household_income_change": -907.0148122290055, + "relative_household_income_change": -0.0, + "population": 146736.6126186456 + }, + { + "constituency_code": "E14000000145", + "constituency_name": "Constituency 145", + "x": 20, + "y": 4, + "average_household_income_change": 35.53462916544747, + "relative_household_income_change": 0.0, + "population": 64441.56694242156 + }, + { + "constituency_code": "E14000000146", + "constituency_name": "Constituency 146", + "x": 21, + "y": 4, + "average_household_income_change": -124.46281500682232, + "relative_household_income_change": -0.0, + "population": 120349.10959497117 + }, + { + "constituency_code": "E14000000147", + "constituency_name": "Constituency 147", + "x": 22, + "y": 4, + "average_household_income_change": -862.1979283911992, + "relative_household_income_change": 1e-12, + "population": 75978.88726544433 + }, + { + "constituency_code": "E14000000148", + "constituency_name": "Constituency 148", + "x": null, + "y": null, + "average_household_income_change": 1140.4649528680948, + "relative_household_income_change": 0.0, + "population": 54047.383882475355 + }, + { + "constituency_code": "E14000000149", + "constituency_name": "Constituency 149", + "x": 24, + "y": 4, + "average_household_income_change": 678.6107114798727, + "relative_household_income_change": -3.5e-9, + "population": 117413.54107700937 + }, + { + "constituency_code": "E14000000150", + "constituency_name": "Constituency 150", + "x": 25, + "y": 4, + "average_household_income_change": -968.559432686301, + "relative_household_income_change": 0.37852725111076435, + "population": 115903.15108720168 + }, + { + "constituency_code": "E14000000151", + "constituency_name": "Constituency 151", + "x": 26, + "y": 4, + "average_household_income_change": -1129.3003769282795, + "relative_household_income_change": -3.5e-9, + "population": 144612.66162939422 + }, + { + "constituency_code": "E14000000152", + "constituency_name": "Constituency 152", + "x": 27, + "y": 4, + "average_household_income_change": 1269.0375684969467, + "relative_household_income_change": -3.5e-9, + "population": 103290.76445801418 + }, + { + "constituency_code": "E14000000153", + "constituency_name": "Constituency 153", + "x": 28, + "y": 4, + "average_household_income_change": -484.59589825511887, + "relative_household_income_change": 0.0, + "population": 78314.43303172 + }, + { + "constituency_code": "E14000000154", + "constituency_name": "Constituency 154", + "x": 29, + "y": 4, + "average_household_income_change": -1495.7935523863468, + "relative_household_income_change": -0.0, + "population": 64071.97759800385 + }, + { + "constituency_code": "E14000000155", + "constituency_name": "Constituency 155", + "x": null, + "y": null, + "average_household_income_change": -389.87763296794054, + "relative_household_income_change": 0.0, + "population": 54102.4304805369 + }, + { + "constituency_code": "E14000000156", + "constituency_name": "Constituency 156", + "x": 0, + "y": 5, + "average_household_income_change": 1643.525970306858, + "relative_household_income_change": 0.0, + "population": 114985.93268203211 + }, + { + "constituency_code": "E14000000157", + "constituency_name": "Constituency 157", + "x": 1, + "y": 5, + "average_household_income_change": 504.13911589940864, + "relative_household_income_change": 1e-12, + "population": 96530.2084560394 + }, + { + "constituency_code": "E14000000158", + "constituency_name": "Constituency 158", + "x": 2, + "y": 5, + "average_household_income_change": 1753.9239358191967, + "relative_household_income_change": 0.17275558712005012, + "population": 63841.377140504985 + }, + { + "constituency_code": "E14000000159", + "constituency_name": "Constituency 159", + "x": 3, + "y": 5, + "average_household_income_change": -1655.610381708632, + "relative_household_income_change": 1e-12, + "population": 59182.04001348608 + }, + { + "constituency_code": "E14000000160", + "constituency_name": "Constituency 160", + "x": 4, + "y": 5, + "average_household_income_change": 1493.1892934146344, + "relative_household_income_change": 0.05167241091737229, + "population": 134883.8787827266 + }, + { + "constituency_code": "E14000000161", + "constituency_name": "Constituency 161", + "x": 5, + "y": 5, + "average_household_income_change": -1009.785320605499, + "relative_household_income_change": -0.0, + "population": 105313.0376348572 + }, + { + "constituency_code": "E14000000162", + "constituency_name": "Constituency 162", + "x": null, + "y": null, + "average_household_income_change": 1985.790511051385, + "relative_household_income_change": 0.0, + "population": 59046.08239782301 + }, + { + "constituency_code": "E14000000163", + "constituency_name": "Constituency 163", + "x": 7, + "y": 5, + "average_household_income_change": -624.0407357817598, + "relative_household_income_change": -3.5e-9, + "population": 133938.68480033753 + }, + { + "constituency_code": "E14000000164", + "constituency_name": "Constituency 164", + "x": 8, + "y": 5, + "average_household_income_change": -1219.380899954297, + "relative_household_income_change": -3.5e-9, + "population": 140688.8228403655 + }, + { + "constituency_code": "E14000000165", + "constituency_name": "Constituency 165", + "x": 9, + "y": 5, + "average_household_income_change": 1082.0360022946556, + "relative_household_income_change": -0.0, + "population": 119206.25377648813 + }, + { + "constituency_code": "E14000000166", + "constituency_name": "Constituency 166", + "x": 10, + "y": 5, + "average_household_income_change": 1270.7265069357318, + "relative_household_income_change": 0.0, + "population": 60177.53130640996 + }, + { + "constituency_code": "E14000000167", + "constituency_name": "Constituency 167", + "x": 11, + "y": 5, + "average_household_income_change": -173.76753307330173, + "relative_household_income_change": -3.5e-9, + "population": 92609.98355546329 + }, + { + "constituency_code": "E14000000168", + "constituency_name": "Constituency 168", + "x": 12, + "y": 5, + "average_household_income_change": 84.60524462623465, + "relative_household_income_change": 0.0, + "population": 109246.06859637471 + }, + { + "constituency_code": "E14000000169", + "constituency_name": "Constituency 169", + "x": null, + "y": null, + "average_household_income_change": 1226.4575806689, + "relative_household_income_change": -3.5e-9, + "population": 85779.77623277435 + }, + { + "constituency_code": "E14000000170", + "constituency_name": "Constituency 170", + "x": 14, + "y": 5, + "average_household_income_change": 1897.8839697841004, + "relative_household_income_change": 0.3673733728077122, + "population": 134526.85600579536 + }, + { + "constituency_code": "E14000000171", + "constituency_name": "Constituency 171", + "x": 15, + "y": 5, + "average_household_income_change": -96.71162396045486, + "relative_household_income_change": -0.0, + "population": 135267.77830307873 + }, + { + "constituency_code": "E14000000172", + "constituency_name": "Constituency 172", + "x": 16, + "y": 5, + "average_household_income_change": 1734.8446483630125, + "relative_household_income_change": 0.7508561605283052, + "population": 121288.32325809612 + }, + { + "constituency_code": "E14000000173", + "constituency_name": "Constituency 173", + "x": 17, + "y": 5, + "average_household_income_change": 1116.8285362297524, + "relative_household_income_change": 0.0, + "population": 143666.5638784498 + }, + { + "constituency_code": "E14000000174", + "constituency_name": "Constituency 174", + "x": 18, + "y": 5, + "average_household_income_change": 1731.2154456492808, + "relative_household_income_change": -3.5e-9, + "population": 124824.5757648796 + }, + { + "constituency_code": "E14000000175", + "constituency_name": "Constituency 175", + "x": 19, + "y": 5, + "average_household_income_change": 1948.654638465101, + "relative_household_income_change": 0.4978536471952415, + "population": 131100.4905236806 + }, + { + "constituency_code": "E14000000176", + "constituency_name": "Constituency 176", + "x": null, + "y": null, + "average_household_income_change": -511.27124006434775, + "relative_household_income_change": 0.13061907743062717, + "population": 116551.31582614966 + }, + { + "constituency_code": "E14000000177", + "constituency_name": "Constituency 177", + "x": 21, + "y": 5, + "average_household_income_change": -1935.029384051584, + "relative_household_income_change": 1e-12, + "population": 137063.16851170457 + }, + { + "constituency_code": "E14000000178", + "constituency_name": "Constituency 178", + "x": 22, + "y": 5, + "average_household_income_change": -911.186276780501, + "relative_household_income_change": -0.0, + "population": 61965.39400983384 + }, + { + "constituency_code": "E14000000179", + "constituency_name": "Constituency 179", + "x": 23, + "y": 5, + "average_household_income_change": 1733.1720235382163, + "relative_household_income_change": 0.0, + "population": 142246.5510827012 + }, + { + "constituency_code": "E14000000180", + "constituency_name": "Constituency 180", + "x": 24, + "y": 5, + "average_household_income_change": 1661.238755153409, + "relative_household_income_change": 0.0, + "population": 90367.91791250638 + }, + { + "constituency_code": "E14000000181", + "constituency_name": "Constituency 181", + "x": 25, + "y": 5, + "average_household_income_change": 345.2949680294841, + "relative_household_income_change": -3.5e-9, + "population": 149980.7029767488 + }, + { + "constituency_code": "E14000000182", + "constituency_name": "Constituency 182", + "x": 26, + "y": 5, + "average_household_income_change": -988.0666839819572, + "relative_household_income_change": -0.0, + "population": 128097.92539036271 + }, + { + "constituency_code": "E14000000183", + "constituency_name": "Constituency 183", + "x": null, + "y": null, + "average_household_income_change": 902.1430784366627, + "relative_household_income_change": 0.09220506661790073, + "population": 85359.46880565214 + }, + { + "constituency_code": "E14000000184", + "constituency_name": "Constituency 184", + "x": 28, + "y": 5, + "average_household_income_change": -957.5128615802955, + "relative_household_income_change": 0.0, + "population": 57657.65475740139 + }, + { + "constituency_code": "E14000000185", + "constituency_name": "Constituency 185", + "x": 29, + "y": 5, + "average_household_income_change": -753.5040279733156, + "relative_household_income_change": 1e-12, + "population": 98478.87085938707 + }, + { + "constituency_code": "E14000000186", + "constituency_name": "Constituency 186", + "x": 30, + "y": 5, + "average_household_income_change": 1655.0348378318804, + "relative_household_income_change": -0.0, + "population": 140589.08503782647 + }, + { + "constituency_code": "E14000000187", + "constituency_name": "Constituency 187", + "x": 0, + "y": 6, + "average_household_income_change": -457.6924571642285, + "relative_household_income_change": -3.5e-9, + "population": 60506.32404568623 + }, + { + "constituency_code": "E14000000188", + "constituency_name": "Constituency 188", + "x": 1, + "y": 6, + "average_household_income_change": 955.5435083380046, + "relative_household_income_change": 0.0, + "population": 148637.46753157367 + }, + { + "constituency_code": "E14000000189", + "constituency_name": "Constituency 189", + "x": 2, + "y": 6, + "average_household_income_change": -824.5635557117255, + "relative_household_income_change": 0.0, + "population": 99782.64274656228 + }, + { + "constituency_code": "E14000000190", + "constituency_name": "Constituency 190", + "x": null, + "y": null, + "average_household_income_change": -534.8346178311823, + "relative_household_income_change": 1e-12, + "population": 55067.263103974285 + }, + { + "constituency_code": "E14000000191", + "constituency_name": "Constituency 191", + "x": 4, + "y": 6, + "average_household_income_change": 1124.6850271956769, + "relative_household_income_change": -0.0, + "population": 135639.43667060742 + }, + { + "constituency_code": "E14000000192", + "constituency_name": "Constituency 192", + "x": 5, + "y": 6, + "average_household_income_change": 1915.0183852603498, + "relative_household_income_change": -0.0, + "population": 72513.67422403721 + }, + { + "constituency_code": "E14000000193", + "constituency_name": "Constituency 193", + "x": 6, + "y": 6, + "average_household_income_change": 468.543806087232, + "relative_household_income_change": 1e-12, + "population": 51295.48380385167 + }, + { + "constituency_code": "E14000000194", + "constituency_name": "Constituency 194", + "x": 7, + "y": 6, + "average_household_income_change": -1970.722745123179, + "relative_household_income_change": -3.5e-9, + "population": 90662.16267914974 + }, + { + "constituency_code": "E14000000195", + "constituency_name": "Constituency 195", + "x": 8, + "y": 6, + "average_household_income_change": 1541.7517077241403, + "relative_household_income_change": 0.0, + "population": 51287.49142035601 + }, + { + "constituency_code": "E14000000196", + "constituency_name": "Constituency 196", + "x": 9, + "y": 6, + "average_household_income_change": -561.0043898564228, + "relative_household_income_change": -0.0, + "population": 148348.3321363182 + }, + { + "constituency_code": "E14000000197", + "constituency_name": "Constituency 197", + "x": null, + "y": null, + "average_household_income_change": 847.9949757046952, + "relative_household_income_change": 0.12100126791021937, + "population": 146252.67973033 + }, + { + "constituency_code": "E14000000198", + "constituency_name": "Constituency 198", + "x": 11, + "y": 6, + "average_household_income_change": -122.91164421650168, + "relative_household_income_change": 0.0, + "population": 108822.50841263078 + }, + { + "constituency_code": "E14000000199", + "constituency_name": "Constituency 199", + "x": 12, + "y": 6, + "average_household_income_change": 210.35075187056896, + "relative_household_income_change": 1e-12, + "population": 73060.15474275278 + }, + { + "constituency_code": "E14000000200", + "constituency_name": "Constituency 200", + "x": 13, + "y": 6, + "average_household_income_change": 1373.2772747493455, + "relative_household_income_change": -3.5e-9, + "population": 54562.39026607954 + }, + { + "constituency_code": "E14000000201", + "constituency_name": "Constituency 201", + "x": 14, + "y": 6, + "average_household_income_change": 1775.7579273582728, + "relative_household_income_change": -0.0, + "population": 68571.93485422268 + }, + { + "constituency_code": "E14000000202", + "constituency_name": "Constituency 202", + "x": 15, + "y": 6, + "average_household_income_change": 487.9521355800094, + "relative_household_income_change": 1e-12, + "population": 52440.31636393422 + }, + { + "constituency_code": "E14000000203", + "constituency_name": "Constituency 203", + "x": 16, + "y": 6, + "average_household_income_change": -1322.0472054070465, + "relative_household_income_change": 0.7971877766379147, + "population": 135070.588467467 + }, + { + "constituency_code": "E14000000204", + "constituency_name": "Constituency 204", + "x": null, + "y": null, + "average_household_income_change": 1509.8157970664406, + "relative_household_income_change": 1e-12, + "population": 144410.89387433697 + }, + { + "constituency_code": "E14000000205", + "constituency_name": "Constituency 205", + "x": 18, + "y": 6, + "average_household_income_change": 817.8577390299471, + "relative_household_income_change": -0.0, + "population": 110217.0617559504 + }, + { + "constituency_code": "E14000000206", + "constituency_name": "Constituency 206", + "x": 19, + "y": 6, + "average_household_income_change": -519.2624488298457, + "relative_household_income_change": 0.13511138675068546, + "population": 76651.5628612962 + }, + { + "constituency_code": "E14000000207", + "constituency_name": "Constituency 207", + "x": 20, + "y": 6, + "average_household_income_change": -1085.0536783564949, + "relative_household_income_change": -0.0, + "population": 60836.20787139632 + }, + { + "constituency_code": "E14000000208", + "constituency_name": "Constituency 208", + "x": 21, + "y": 6, + "average_household_income_change": 301.6568478061923, + "relative_household_income_change": 0.0, + "population": 87157.94506624367 + }, + { + "constituency_code": "E14000000209", + "constituency_name": "Constituency 209", + "x": 22, + "y": 6, + "average_household_income_change": -1673.3597854652503, + "relative_household_income_change": 0.4169266309393279, + "population": 68426.82588844819 + }, + { + "constituency_code": "E14000000210", + "constituency_name": "Constituency 210", + "x": 23, + "y": 6, + "average_household_income_change": -83.09691011490594, + "relative_household_income_change": -0.0, + "population": 126920.19674232941 + }, + { + "constituency_code": "E14000000211", + "constituency_name": "Constituency 211", + "x": null, + "y": null, + "average_household_income_change": 237.6712620893251, + "relative_household_income_change": 1e-12, + "population": 60236.095478765325 + }, + { + "constituency_code": "E14000000212", + "constituency_name": "Constituency 212", + "x": 25, + "y": 6, + "average_household_income_change": -1585.4887263147605, + "relative_household_income_change": -0.0, + "population": 116481.5354173281 + }, + { + "constituency_code": "E14000000213", + "constituency_name": "Constituency 213", + "x": 26, + "y": 6, + "average_household_income_change": 52.57033563292879, + "relative_household_income_change": 0.0, + "population": 79714.87039267518 + }, + { + "constituency_code": "E14000000214", + "constituency_name": "Constituency 214", + "x": 27, + "y": 6, + "average_household_income_change": 140.7077209407901, + "relative_household_income_change": 1e-12, + "population": 132320.27403479567 + }, + { + "constituency_code": "E14000000215", + "constituency_name": "Constituency 215", + "x": 28, + "y": 6, + "average_household_income_change": -1284.1135147208838, + "relative_household_income_change": -3.5e-9, + "population": 106469.78321771967 + }, + { + "constituency_code": "E14000000216", + "constituency_name": "Constituency 216", + "x": 29, + "y": 6, + "average_household_income_change": -1792.2895026530314, + "relative_household_income_change": -0.0, + "population": 99990.59878057335 + }, + { + "constituency_code": "E14000000217", + "constituency_name": "Constituency 217", + "x": 30, + "y": 6, + "average_household_income_change": -783.8278631034128, + "relative_household_income_change": 0.28888357094563333, + "population": 110733.83910680971 + }, + { + "constituency_code": "E14000000218", + "constituency_name": "Constituency 218", + "x": null, + "y": null, + "average_household_income_change": 642.037289695729, + "relative_household_income_change": -0.0, + "population": 90348.9414403198 + }, + { + "constituency_code": "E14000000219", + "constituency_name": "Constituency 219", + "x": 1, + "y": 7, + "average_household_income_change": -1806.0966714650708, + "relative_household_income_change": 0.08357134950427492, + "population": 141405.8939185595 + }, + { + "constituency_code": "E14000000220", + "constituency_name": "Constituency 220", + "x": 2, + "y": 7, + "average_household_income_change": -528.2119277643891, + "relative_household_income_change": 0.4861389513239871, + "population": 71685.69023793048 + }, + { + "constituency_code": "E14000000221", + "constituency_name": "Constituency 221", + "x": 3, + "y": 7, + "average_household_income_change": 951.5333154614805, + "relative_household_income_change": -0.0, + "population": 79177.23029313763 + }, + { + "constituency_code": "E14000000222", + "constituency_name": "Constituency 222", + "x": 4, + "y": 7, + "average_household_income_change": 834.3379193338874, + "relative_household_income_change": 1e-12, + "population": 110931.01259918352 + }, + { + "constituency_code": "E14000000223", + "constituency_name": "Constituency 223", + "x": 5, + "y": 7, + "average_household_income_change": 1654.9743225435302, + "relative_household_income_change": -0.0, + "population": 144906.40272194232 + }, + { + "constituency_code": "E14000000224", + "constituency_name": "Constituency 224", + "x": 6, + "y": 7, + "average_household_income_change": 1855.1096996562494, + "relative_household_income_change": -3.5e-9, + "population": 66984.07968401432 + }, + { + "constituency_code": "E14000000225", + "constituency_name": "Constituency 225", + "x": null, + "y": null, + "average_household_income_change": 1113.0857713770702, + "relative_household_income_change": -3.5e-9, + "population": 60678.66657872668 + }, + { + "constituency_code": "E14000000226", + "constituency_name": "Constituency 226", + "x": 8, + "y": 7, + "average_household_income_change": -317.2806673045674, + "relative_household_income_change": 1e-12, + "population": 85565.2841368982 + }, + { + "constituency_code": "E14000000227", + "constituency_name": "Constituency 227", + "x": 9, + "y": 7, + "average_household_income_change": 146.19610700532658, + "relative_household_income_change": 0.0, + "population": 54058.96768105369 + }, + { + "constituency_code": "E14000000228", + "constituency_name": "Constituency 228", + "x": 10, + "y": 7, + "average_household_income_change": 1221.1828572635995, + "relative_household_income_change": -0.0, + "population": 72968.59443746644 + }, + { + "constituency_code": "E14000000229", + "constituency_name": "Constituency 229", + "x": 11, + "y": 7, + "average_household_income_change": -474.6414251653745, + "relative_household_income_change": 0.44878570088574854, + "population": 90285.80408850596 + }, + { + "constituency_code": "E14000000230", + "constituency_name": "Constituency 230", + "x": 12, + "y": 7, + "average_household_income_change": -71.76530955441463, + "relative_household_income_change": 0.5436024592612985, + "population": 141221.01934312264 + }, + { + "constituency_code": "E14000000231", + "constituency_name": "Constituency 231", + "x": 13, + "y": 7, + "average_household_income_change": -378.30934127288975, + "relative_household_income_change": -3.5e-9, + "population": 116505.42531287429 + }, + { + "constituency_code": "E14000000232", + "constituency_name": "Constituency 232", + "x": null, + "y": null, + "average_household_income_change": 1005.3928185121252, + "relative_household_income_change": -0.0, + "population": 75058.25944668779 + }, + { + "constituency_code": "E14000000233", + "constituency_name": "Constituency 233", + "x": 15, + "y": 7, + "average_household_income_change": 1586.7343046544327, + "relative_household_income_change": 1e-12, + "population": 67712.64242455097 + }, + { + "constituency_code": "E14000000234", + "constituency_name": "Constituency 234", + "x": 16, + "y": 7, + "average_household_income_change": -1174.252830775441, + "relative_household_income_change": -3.5e-9, + "population": 63789.03547513046 + }, + { + "constituency_code": "E14000000235", + "constituency_name": "Constituency 235", + "x": 17, + "y": 7, + "average_household_income_change": 645.6604038115912, + "relative_household_income_change": 0.0, + "population": 122263.69384295912 + }, + { + "constituency_code": "E14000000236", + "constituency_name": "Constituency 236", + "x": 18, + "y": 7, + "average_household_income_change": -597.6576548607908, + "relative_household_income_change": -3.5e-9, + "population": 98804.04918650471 + }, + { + "constituency_code": "E14000000237", + "constituency_name": "Constituency 237", + "x": 19, + "y": 7, + "average_household_income_change": 415.38377283407124, + "relative_household_income_change": 1e-12, + "population": 72462.68658428223 + }, + { + "constituency_code": "E14000000238", + "constituency_name": "Constituency 238", + "x": 20, + "y": 7, + "average_household_income_change": -502.30148175641, + "relative_household_income_change": 0.39825500487354804, + "population": 75577.16208619578 + }, + { + "constituency_code": "E14000000239", + "constituency_name": "Constituency 239", + "x": null, + "y": null, + "average_household_income_change": 1982.22971422196, + "relative_household_income_change": 0.0, + "population": 100039.3452447531 + }, + { + "constituency_code": "E14000000240", + "constituency_name": "Constituency 240", + "x": 22, + "y": 7, + "average_household_income_change": 68.96842129588521, + "relative_household_income_change": 0.0, + "population": 78623.37294752918 + }, + { + "constituency_code": "E14000000241", + "constituency_name": "Constituency 241", + "x": 23, + "y": 7, + "average_household_income_change": -469.3900179759347, + "relative_household_income_change": -3.5e-9, + "population": 71536.75669369439 + }, + { + "constituency_code": "E14000000242", + "constituency_name": "Constituency 242", + "x": 24, + "y": 7, + "average_household_income_change": 1230.3207047092353, + "relative_household_income_change": -3.5e-9, + "population": 63353.07779126578 + }, + { + "constituency_code": "E14000000243", + "constituency_name": "Constituency 243", + "x": 25, + "y": 7, + "average_household_income_change": -1928.9219199088845, + "relative_household_income_change": -3.5e-9, + "population": 62849.86261697499 + }, + { + "constituency_code": "E14000000244", + "constituency_name": "Constituency 244", + "x": 26, + "y": 7, + "average_household_income_change": 1110.3372470128168, + "relative_household_income_change": -0.0, + "population": 76727.3810569975 + }, + { + "constituency_code": "E14000000245", + "constituency_name": "Constituency 245", + "x": 27, + "y": 7, + "average_household_income_change": 1362.7103896145973, + "relative_household_income_change": -0.0, + "population": 124325.70785994509 + }, + { + "constituency_code": "E14000000246", + "constituency_name": "Constituency 246", + "x": null, + "y": null, + "average_household_income_change": -271.49022713741465, + "relative_household_income_change": 1e-12, + "population": 99799.46872015242 + }, + { + "constituency_code": "E14000000247", + "constituency_name": "Constituency 247", + "x": 29, + "y": 7, + "average_household_income_change": 1537.7903349770033, + "relative_household_income_change": -3.5e-9, + "population": 123746.60837519364 + }, + { + "constituency_code": "E14000000248", + "constituency_name": "Constituency 248", + "x": 30, + "y": 7, + "average_household_income_change": -1087.8785006624473, + "relative_household_income_change": 1e-12, + "population": 97600.39659601363 + }, + { + "constituency_code": "E14000000249", + "constituency_name": "Constituency 249", + "x": 0, + "y": 8, + "average_household_income_change": -1345.7662153813862, + "relative_household_income_change": 0.0, + "population": 114313.09710587711 + }, + { + "constituency_code": "E14000000250", + "constituency_name": "Constituency 250", + "x": 1, + "y": 8, + "average_household_income_change": 1658.6777073773708, + "relative_household_income_change": -0.0, + "population": 94609.60109811788 + }, + { + "constituency_code": "E14000000251", + "constituency_name": "Constituency 251", + "x": 2, + "y": 8, + "average_household_income_change": -519.6173843357359, + "relative_household_income_change": 0.05288350383949525, + "population": 101879.58740965034 + }, + { + "constituency_code": "E14000000252", + "constituency_name": "Constituency 252", + "x": 3, + "y": 8, + "average_household_income_change": 61.39724136454517, + "relative_household_income_change": 0.0, + "population": 122016.25936999946 + }, + { + "constituency_code": "E14000000253", + "constituency_name": "Constituency 253", + "x": null, + "y": null, + "average_household_income_change": 200.79508742853758, + "relative_household_income_change": 1e-12, + "population": 112382.16718067882 + }, + { + "constituency_code": "E14000000254", + "constituency_name": "Constituency 254", + "x": 5, + "y": 8, + "average_household_income_change": 68.46081134368464, + "relative_household_income_change": 1e-12, + "population": 79034.69952823792 + }, + { + "constituency_code": "E14000000255", + "constituency_name": "Constituency 255", + "x": 6, + "y": 8, + "average_household_income_change": -1049.8419544678975, + "relative_household_income_change": 0.0685689670992683, + "population": 84627.21548030981 + }, + { + "constituency_code": "E14000000256", + "constituency_name": "Constituency 256", + "x": 7, + "y": 8, + "average_household_income_change": 1881.2593648861452, + "relative_household_income_change": -3.5e-9, + "population": 135723.15777362182 + }, + { + "constituency_code": "E14000000257", + "constituency_name": "Constituency 257", + "x": 8, + "y": 8, + "average_household_income_change": -300.59480412605757, + "relative_household_income_change": 0.38686768114256065, + "population": 140550.79135966688 + }, + { + "constituency_code": "E14000000258", + "constituency_name": "Constituency 258", + "x": 9, + "y": 8, + "average_household_income_change": -299.27228807240124, + "relative_household_income_change": -3.5e-9, + "population": 136940.02453417546 + }, + { + "constituency_code": "E14000000259", + "constituency_name": "Constituency 259", + "x": 10, + "y": 8, + "average_household_income_change": -1968.8831338393782, + "relative_household_income_change": 1e-12, + "population": 116862.35781095125 + }, + { + "constituency_code": "E14000000260", + "constituency_name": "Constituency 260", + "x": null, + "y": null, + "average_household_income_change": -1937.396708083625, + "relative_household_income_change": -0.0, + "population": 53050.95960456516 + }, + { + "constituency_code": "E14000000261", + "constituency_name": "Constituency 261", + "x": 12, + "y": 8, + "average_household_income_change": 278.54418344988784, + "relative_household_income_change": 0.8182049447786189, + "population": 145996.30964651122 + }, + { + "constituency_code": "E14000000262", + "constituency_name": "Constituency 262", + "x": 13, + "y": 8, + "average_household_income_change": -1743.60096454641, + "relative_household_income_change": -3.5e-9, + "population": 137665.3909221181 + }, + { + "constituency_code": "E14000000263", + "constituency_name": "Constituency 263", + "x": 14, + "y": 8, + "average_household_income_change": 410.3648552033592, + "relative_household_income_change": 0.0, + "population": 130733.25893769521 + }, + { + "constituency_code": "E14000000264", + "constituency_name": "Constituency 264", + "x": 15, + "y": 8, + "average_household_income_change": -870.6543863626357, + "relative_household_income_change": 0.0, + "population": 130659.0095046039 + }, + { + "constituency_code": "E14000000265", + "constituency_name": "Constituency 265", + "x": 16, + "y": 8, + "average_household_income_change": 1143.162831284736, + "relative_household_income_change": 0.0, + "population": 107575.18022024026 + }, + { + "constituency_code": "E14000000266", + "constituency_name": "Constituency 266", + "x": 17, + "y": 8, + "average_household_income_change": -1057.9486970304836, + "relative_household_income_change": -0.0, + "population": 91442.6613340457 + }, + { + "constituency_code": "E14000000267", + "constituency_name": "Constituency 267", + "x": null, + "y": null, + "average_household_income_change": 1814.0649747416485, + "relative_household_income_change": 1e-12, + "population": 65130.079693553234 + }, + { + "constituency_code": "E14000000268", + "constituency_name": "Constituency 268", + "x": 19, + "y": 8, + "average_household_income_change": -1516.7977290124063, + "relative_household_income_change": -0.0, + "population": 55364.656447213056 + }, + { + "constituency_code": "E14000000269", + "constituency_name": "Constituency 269", + "x": 20, + "y": 8, + "average_household_income_change": -294.20877227662066, + "relative_household_income_change": -0.0, + "population": 61555.40574473531 + }, + { + "constituency_code": "E14000000270", + "constituency_name": "Constituency 270", + "x": 21, + "y": 8, + "average_household_income_change": 695.5018348863717, + "relative_household_income_change": -0.0, + "population": 68812.25148927994 + }, + { + "constituency_code": "E14000000271", + "constituency_name": "Constituency 271", + "x": 22, + "y": 8, + "average_household_income_change": -351.1802166259006, + "relative_household_income_change": -0.0, + "population": 54027.65899145163 + }, + { + "constituency_code": "E14000000272", + "constituency_name": "Constituency 272", + "x": 23, + "y": 8, + "average_household_income_change": -1642.2915725524824, + "relative_household_income_change": 0.8379817398377877, + "population": 88079.14001836749 + }, + { + "constituency_code": "E14000000273", + "constituency_name": "Constituency 273", + "x": 24, + "y": 8, + "average_household_income_change": -196.16611907612392, + "relative_household_income_change": 0.6191859545022685, + "population": 143901.09379379006 + }, + { + "constituency_code": "E14000000274", + "constituency_name": "Constituency 274", + "x": null, + "y": null, + "average_household_income_change": 1592.5511593747626, + "relative_household_income_change": 1e-12, + "population": 56538.644750654064 + }, + { + "constituency_code": "E14000000275", + "constituency_name": "Constituency 275", + "x": 26, + "y": 8, + "average_household_income_change": 1249.8308107022656, + "relative_household_income_change": 0.0, + "population": 82852.1573553915 + }, + { + "constituency_code": "E14000000276", + "constituency_name": "Constituency 276", + "x": 27, + "y": 8, + "average_household_income_change": -1679.6035271853639, + "relative_household_income_change": 1e-12, + "population": 82624.31099995461 + }, + { + "constituency_code": "E14000000277", + "constituency_name": "Constituency 277", + "x": 28, + "y": 8, + "average_household_income_change": 1081.625804541158, + "relative_household_income_change": 0.7119632280929965, + "population": 56373.70772158275 + }, + { + "constituency_code": "E14000000278", + "constituency_name": "Constituency 278", + "x": 29, + "y": 8, + "average_household_income_change": -1514.008414001978, + "relative_household_income_change": -3.5e-9, + "population": 54038.13587168238 + }, + { + "constituency_code": "E14000000279", + "constituency_name": "Constituency 279", + "x": 30, + "y": 8, + "average_household_income_change": -879.656036805668, + "relative_household_income_change": 0.0, + "population": 66920.7276918206 + }, + { + "constituency_code": "E14000000280", + "constituency_name": "Constituency 280", + "x": 0, + "y": 9, + "average_household_income_change": -1434.2729900398488, + "relative_household_income_change": -3.5e-9, + "population": 114525.67044788442 + }, + { + "constituency_code": "E14000000281", + "constituency_name": "Constituency 281", + "x": null, + "y": null, + "average_household_income_change": 78.84229063710268, + "relative_household_income_change": 0.9093867952915566, + "population": 71203.42519173468 + }, + { + "constituency_code": "E14000000282", + "constituency_name": "Constituency 282", + "x": 2, + "y": 9, + "average_household_income_change": 12.239268357744137, + "relative_household_income_change": -0.0, + "population": 57133.2670657449 + }, + { + "constituency_code": "E14000000283", + "constituency_name": "Constituency 283", + "x": 3, + "y": 9, + "average_household_income_change": -879.1966266472486, + "relative_household_income_change": -3.5e-9, + "population": 117950.37248663565 + }, + { + "constituency_code": "E14000000284", + "constituency_name": "Constituency 284", + "x": 4, + "y": 9, + "average_household_income_change": 731.6369198544824, + "relative_household_income_change": 0.0, + "population": 60677.670160915164 + }, + { + "constituency_code": "E14000000285", + "constituency_name": "Constituency 285", + "x": 5, + "y": 9, + "average_household_income_change": 538.8786664582988, + "relative_household_income_change": 0.0, + "population": 134931.71481241478 + }, + { + "constituency_code": "E14000000286", + "constituency_name": "Constituency 286", + "x": 6, + "y": 9, + "average_household_income_change": -363.61423705336284, + "relative_household_income_change": -3.5e-9, + "population": 59397.05353299759 + }, + { + "constituency_code": "E14000000287", + "constituency_name": "Constituency 287", + "x": 7, + "y": 9, + "average_household_income_change": -41.56094887664574, + "relative_household_income_change": -0.0, + "population": 101221.93183884669 + }, + { + "constituency_code": "E14000000288", + "constituency_name": "Constituency 288", + "x": null, + "y": null, + "average_household_income_change": -1640.8394237733885, + "relative_household_income_change": -0.0, + "population": 85331.20565330614 + }, + { + "constituency_code": "E14000000289", + "constituency_name": "Constituency 289", + "x": 9, + "y": 9, + "average_household_income_change": 1607.6675640232882, + "relative_household_income_change": 0.0, + "population": 54725.222443885046 + }, + { + "constituency_code": "E14000000290", + "constituency_name": "Constituency 290", + "x": 10, + "y": 9, + "average_household_income_change": -1442.7349429318213, + "relative_household_income_change": 1e-12, + "population": 119504.45090787341 + }, + { + "constituency_code": "E14000000291", + "constituency_name": "Constituency 291", + "x": 11, + "y": 9, + "average_household_income_change": -1298.611495104644, + "relative_household_income_change": -0.0, + "population": 124055.42495705158 + }, + { + "constituency_code": "E14000000292", + "constituency_name": "Constituency 292", + "x": 12, + "y": 9, + "average_household_income_change": -363.63670045492836, + "relative_household_income_change": -0.0, + "population": 80797.82277151337 + }, + { + "constituency_code": "E14000000293", + "constituency_name": "Constituency 293", + "x": 13, + "y": 9, + "average_household_income_change": 902.118169666097, + "relative_household_income_change": 0.5975509379823232, + "population": 129073.02446683323 + }, + { + "constituency_code": "E14000000294", + "constituency_name": "Constituency 294", + "x": 14, + "y": 9, + "average_household_income_change": -139.25701863002172, + "relative_household_income_change": 0.06255641858639482, + "population": 57752.53085066069 + }, + { + "constituency_code": "E14000000295", + "constituency_name": "Constituency 295", + "x": null, + "y": null, + "average_household_income_change": -1163.432231007708, + "relative_household_income_change": 0.8764210555336815, + "population": 106333.06119563997 + }, + { + "constituency_code": "E14000000296", + "constituency_name": "Constituency 296", + "x": 16, + "y": 9, + "average_household_income_change": -1679.9787950530365, + "relative_household_income_change": 1e-12, + "population": 75692.39275484561 + }, + { + "constituency_code": "E14000000297", + "constituency_name": "Constituency 297", + "x": 17, + "y": 9, + "average_household_income_change": 1582.697326893069, + "relative_household_income_change": 0.0, + "population": 117975.52461036804 + }, + { + "constituency_code": "E14000000298", + "constituency_name": "Constituency 298", + "x": 18, + "y": 9, + "average_household_income_change": -141.68662686740774, + "relative_household_income_change": 0.0, + "population": 147122.08267887653 + }, + { + "constituency_code": "E14000000299", + "constituency_name": "Constituency 299", + "x": 19, + "y": 9, + "average_household_income_change": 248.44524455147445, + "relative_household_income_change": 0.0, + "population": 57914.21355725573 + }, + { + "constituency_code": "E14000000300", + "constituency_name": "Constituency 300", + "x": 20, + "y": 9, + "average_household_income_change": -1435.1194306235277, + "relative_household_income_change": 1e-12, + "population": 89667.12520548898 + }, + { + "constituency_code": "E14000000301", + "constituency_name": "Constituency 301", + "x": 21, + "y": 9, + "average_household_income_change": 1093.4980272431533, + "relative_household_income_change": 0.0, + "population": 149640.69785386953 + }, + { + "constituency_code": "E14000000302", + "constituency_name": "Constituency 302", + "x": null, + "y": null, + "average_household_income_change": 53.08937001870451, + "relative_household_income_change": -0.0, + "population": 66230.07359490372 + }, + { + "constituency_code": "E14000000303", + "constituency_name": "Constituency 303", + "x": 23, + "y": 9, + "average_household_income_change": -471.8832314261454, + "relative_household_income_change": -3.5e-9, + "population": 57337.41263366653 + }, + { + "constituency_code": "E14000000304", + "constituency_name": "Constituency 304", + "x": 24, + "y": 9, + "average_household_income_change": -1026.020840673814, + "relative_household_income_change": 1e-12, + "population": 142490.88938975122 + }, + { + "constituency_code": "E14000000305", + "constituency_name": "Constituency 305", + "x": 25, + "y": 9, + "average_household_income_change": 608.8165690306914, + "relative_household_income_change": 0.6404988087018922, + "population": 72487.89624498294 + }, + { + "constituency_code": "E14000000306", + "constituency_name": "Constituency 306", + "x": 26, + "y": 9, + "average_household_income_change": -115.80972292330483, + "relative_household_income_change": 0.39081883301841813, + "population": 77350.48896896599 + }, + { + "constituency_code": "E14000000307", + "constituency_name": "Constituency 307", + "x": 27, + "y": 9, + "average_household_income_change": -1591.2097568655606, + "relative_household_income_change": -0.0, + "population": 130601.76627288382 + }, + { + "constituency_code": "E14000000308", + "constituency_name": "Constituency 308", + "x": 28, + "y": 9, + "average_household_income_change": -202.68597089062146, + "relative_household_income_change": -3.5e-9, + "population": 127803.58575356533 + }, + { + "constituency_code": "E14000000309", + "constituency_name": "Constituency 309", + "x": null, + "y": null, + "average_household_income_change": -1703.293029455986, + "relative_household_income_change": 0.0, + "population": 96967.75627127332 + }, + { + "constituency_code": "E14000000310", + "constituency_name": "Constituency 310", + "x": 30, + "y": 9, + "average_household_income_change": -831.6689332469039, + "relative_household_income_change": -3.5e-9, + "population": 115309.39370340896 + }, + { + "constituency_code": "E14000000311", + "constituency_name": "Constituency 311", + "x": 0, + "y": 10, + "average_household_income_change": 1870.4055118959807, + "relative_household_income_change": 0.0, + "population": 83882.90139684646 + }, + { + "constituency_code": "E14000000312", + "constituency_name": "Constituency 312", + "x": 1, + "y": 10, + "average_household_income_change": 491.49040529432983, + "relative_household_income_change": -0.0, + "population": 80790.58693080283 + }, + { + "constituency_code": "E14000000313", + "constituency_name": "Constituency 313", + "x": 2, + "y": 10, + "average_household_income_change": 375.3827408162542, + "relative_household_income_change": 1e-12, + "population": 84326.10208188766 + }, + { + "constituency_code": "E14000000314", + "constituency_name": "Constituency 314", + "x": 3, + "y": 10, + "average_household_income_change": 33.000174958145664, + "relative_household_income_change": 0.5409158451119593, + "population": 133101.32286826705 + }, + { + "constituency_code": "E14000000315", + "constituency_name": "Constituency 315", + "x": 4, + "y": 10, + "average_household_income_change": -1338.6782648550195, + "relative_household_income_change": 1e-12, + "population": 135673.8907982766 + }, + { + "constituency_code": "E14000000316", + "constituency_name": "Constituency 316", + "x": null, + "y": null, + "average_household_income_change": -645.4749752199311, + "relative_household_income_change": 0.0, + "population": 53154.68071281595 + }, + { + "constituency_code": "E14000000317", + "constituency_name": "Constituency 317", + "x": 6, + "y": 10, + "average_household_income_change": 875.2196826351822, + "relative_household_income_change": -0.0, + "population": 54663.23250214491 + }, + { + "constituency_code": "E14000000318", + "constituency_name": "Constituency 318", + "x": 7, + "y": 10, + "average_household_income_change": -1906.3685553236708, + "relative_household_income_change": -0.0, + "population": 62216.10372183205 + }, + { + "constituency_code": "E14000000319", + "constituency_name": "Constituency 319", + "x": 8, + "y": 10, + "average_household_income_change": 265.67730367256326, + "relative_household_income_change": 0.07095713112290669, + "population": 123272.98162748596 + }, + { + "constituency_code": "E14000000320", + "constituency_name": "Constituency 320", + "x": 9, + "y": 10, + "average_household_income_change": 957.6221647457519, + "relative_household_income_change": -3.5e-9, + "population": 117320.59667338144 + }, + { + "constituency_code": "E14000000321", + "constituency_name": "Constituency 321", + "x": 10, + "y": 10, + "average_household_income_change": 892.5971352867052, + "relative_household_income_change": 0.01547062226303364, + "population": 64382.017243272196 + }, + { + "constituency_code": "E14000000322", + "constituency_name": "Constituency 322", + "x": 11, + "y": 10, + "average_household_income_change": -89.5120196189252, + "relative_household_income_change": 0.6415075542058354, + "population": 125144.8692163065 + }, + { + "constituency_code": "E14000000323", + "constituency_name": "Constituency 323", + "x": null, + "y": null, + "average_household_income_change": 1811.2694791851518, + "relative_household_income_change": -3.5e-9, + "population": 65712.70150761414 + }, + { + "constituency_code": "E14000000324", + "constituency_name": "Constituency 324", + "x": 13, + "y": 10, + "average_household_income_change": -1100.7471361008027, + "relative_household_income_change": 0.4185108779894693, + "population": 114836.3220960143 + }, + { + "constituency_code": "E14000000325", + "constituency_name": "Constituency 325", + "x": 14, + "y": 10, + "average_household_income_change": -1122.6043621770434, + "relative_household_income_change": 1e-12, + "population": 55237.5686532306 + }, + { + "constituency_code": "E14000000326", + "constituency_name": "Constituency 326", + "x": 15, + "y": 10, + "average_household_income_change": -1382.4413984731443, + "relative_household_income_change": -0.0, + "population": 94786.54853619754 + }, + { + "constituency_code": "E14000000327", + "constituency_name": "Constituency 327", + "x": 16, + "y": 10, + "average_household_income_change": -624.9672122114114, + "relative_household_income_change": 0.8086293754051761, + "population": 91180.08167511584 + }, + { + "constituency_code": "E14000000328", + "constituency_name": "Constituency 328", + "x": 17, + "y": 10, + "average_household_income_change": -1532.5080712305694, + "relative_household_income_change": 1e-12, + "population": 74992.84884821136 + }, + { + "constituency_code": "E14000000329", + "constituency_name": "Constituency 329", + "x": 18, + "y": 10, + "average_household_income_change": 1256.8611941470808, + "relative_household_income_change": -0.0, + "population": 73264.68467329515 + }, + { + "constituency_code": "E14000000330", + "constituency_name": "Constituency 330", + "x": null, + "y": null, + "average_household_income_change": 1460.216582001018, + "relative_household_income_change": -0.0, + "population": 120762.21259691025 + }, + { + "constituency_code": "E14000000331", + "constituency_name": "Constituency 331", + "x": 20, + "y": 10, + "average_household_income_change": 1131.1627205329526, + "relative_household_income_change": -3.5e-9, + "population": 124414.09849910664 + }, + { + "constituency_code": "E14000000332", + "constituency_name": "Constituency 332", + "x": 21, + "y": 10, + "average_household_income_change": -950.333632645132, + "relative_household_income_change": 0.30068912666377334, + "population": 102386.62156113084 + }, + { + "constituency_code": "E14000000333", + "constituency_name": "Constituency 333", + "x": 22, + "y": 10, + "average_household_income_change": -662.1771673166976, + "relative_household_income_change": -3.5e-9, + "population": 99217.79434560373 + }, + { + "constituency_code": "E14000000334", + "constituency_name": "Constituency 334", + "x": 23, + "y": 10, + "average_household_income_change": -310.1144178009183, + "relative_household_income_change": 0.0, + "population": 82642.85198374328 + }, + { + "constituency_code": "E14000000335", + "constituency_name": "Constituency 335", + "x": 24, + "y": 10, + "average_household_income_change": -98.61823883872577, + "relative_household_income_change": 0.24680610402164405, + "population": 101928.52381666923 + }, + { + "constituency_code": "E14000000336", + "constituency_name": "Constituency 336", + "x": 25, + "y": 10, + "average_household_income_change": 1800.075825253157, + "relative_household_income_change": 0.0, + "population": 106604.47201418565 + }, + { + "constituency_code": "E14000000337", + "constituency_name": "Constituency 337", + "x": null, + "y": null, + "average_household_income_change": -1024.5596852965332, + "relative_household_income_change": 0.5282743216274547, + "population": 84831.59483429573 + }, + { + "constituency_code": "E14000000338", + "constituency_name": "Constituency 338", + "x": 27, + "y": 10, + "average_household_income_change": -1559.9200409332993, + "relative_household_income_change": 0.0, + "population": 132190.56010856107 + }, + { + "constituency_code": "E14000000339", + "constituency_name": "Constituency 339", + "x": 28, + "y": 10, + "average_household_income_change": -322.5458070710423, + "relative_household_income_change": 0.22529688748048748, + "population": 106479.0884301016 + }, + { + "constituency_code": "E14000000340", + "constituency_name": "Constituency 340", + "x": 29, + "y": 10, + "average_household_income_change": 975.9731193891134, + "relative_household_income_change": 0.9228591687698418, + "population": 147412.05136602212 + }, + { + "constituency_code": "E14000000341", + "constituency_name": "Constituency 341", + "x": 30, + "y": 10, + "average_household_income_change": 1222.6290457869818, + "relative_household_income_change": 0.0, + "population": 144225.48837876614 + }, + { + "constituency_code": "E14000000342", + "constituency_name": "Constituency 342", + "x": 0, + "y": 11, + "average_household_income_change": -314.19552200388875, + "relative_household_income_change": 1e-12, + "population": 111129.0169869452 + }, + { + "constituency_code": "E14000000343", + "constituency_name": "Constituency 343", + "x": 1, + "y": 11, + "average_household_income_change": 1337.6914447481315, + "relative_household_income_change": 0.6064418096250256, + "population": 72777.5551270252 + }, + { + "constituency_code": "E14000000344", + "constituency_name": "Constituency 344", + "x": null, + "y": null, + "average_household_income_change": -500.28648215289894, + "relative_household_income_change": 0.02539666980792299, + "population": 140300.06720143737 + }, + { + "constituency_code": "E14000000345", + "constituency_name": "Constituency 345", + "x": 3, + "y": 11, + "average_household_income_change": -899.8299632125404, + "relative_household_income_change": -3.5e-9, + "population": 118550.12291309344 + }, + { + "constituency_code": "E14000000346", + "constituency_name": "Constituency 346", + "x": 4, + "y": 11, + "average_household_income_change": -824.48101449791, + "relative_household_income_change": 0.05691560918933902, + "population": 84746.18474953297 + }, + { + "constituency_code": "E14000000347", + "constituency_name": "Constituency 347", + "x": 5, + "y": 11, + "average_household_income_change": 1360.4905042331795, + "relative_household_income_change": 1e-12, + "population": 115209.82974713409 + }, + { + "constituency_code": "E14000000348", + "constituency_name": "Constituency 348", + "x": 6, + "y": 11, + "average_household_income_change": 1775.1536699727137, + "relative_household_income_change": 0.11514487999565826, + "population": 80112.3937259131 + }, + { + "constituency_code": "E14000000349", + "constituency_name": "Constituency 349", + "x": 7, + "y": 11, + "average_household_income_change": 1707.8194320756604, + "relative_household_income_change": 1e-12, + "population": 76833.07357783025 + }, + { + "constituency_code": "E14000000350", + "constituency_name": "Constituency 350", + "x": 8, + "y": 11, + "average_household_income_change": 1499.4873663114822, + "relative_household_income_change": 1e-12, + "population": 102963.34481014374 + }, + { + "constituency_code": "E14000000351", + "constituency_name": "Constituency 351", + "x": null, + "y": null, + "average_household_income_change": -845.488142728954, + "relative_household_income_change": 0.0, + "population": 77060.88122496438 + }, + { + "constituency_code": "E14000000352", + "constituency_name": "Constituency 352", + "x": 10, + "y": 11, + "average_household_income_change": 895.7933970570076, + "relative_household_income_change": 1e-12, + "population": 121186.05852623229 + }, + { + "constituency_code": "E14000000353", + "constituency_name": "Constituency 353", + "x": 11, + "y": 11, + "average_household_income_change": 436.30185633340534, + "relative_household_income_change": -3.5e-9, + "population": 90359.39372869075 + }, + { + "constituency_code": "E14000000354", + "constituency_name": "Constituency 354", + "x": 12, + "y": 11, + "average_household_income_change": 1531.899304402959, + "relative_household_income_change": -3.5e-9, + "population": 125773.89335858136 + }, + { + "constituency_code": "E14000000355", + "constituency_name": "Constituency 355", + "x": 13, + "y": 11, + "average_household_income_change": 1900.3636110963519, + "relative_household_income_change": -3.5e-9, + "population": 86402.77703380983 + }, + { + "constituency_code": "E14000000356", + "constituency_name": "Constituency 356", + "x": 14, + "y": 11, + "average_household_income_change": 990.6809907292611, + "relative_household_income_change": 1e-12, + "population": 133926.5278974796 + }, + { + "constituency_code": "E14000000357", + "constituency_name": "Constituency 357", + "x": 15, + "y": 11, + "average_household_income_change": -102.81392002473177, + "relative_household_income_change": 1e-12, + "population": 91672.73914310064 + }, + { + "constituency_code": "E14000000358", + "constituency_name": "Constituency 358", + "x": null, + "y": null, + "average_household_income_change": 1413.2362731585495, + "relative_household_income_change": 0.11842765300769598, + "population": 131869.28448096052 + }, + { + "constituency_code": "E14000000359", + "constituency_name": "Constituency 359", + "x": 17, + "y": 11, + "average_household_income_change": -1526.3658607536765, + "relative_household_income_change": 1e-12, + "population": 76359.1774732786 + }, + { + "constituency_code": "E14000000360", + "constituency_name": "Constituency 360", + "x": 18, + "y": 11, + "average_household_income_change": -1032.2988351211718, + "relative_household_income_change": -3.5e-9, + "population": 81960.88765276896 + }, + { + "constituency_code": "E14000000361", + "constituency_name": "Constituency 361", + "x": 19, + "y": 11, + "average_household_income_change": 906.6356976421935, + "relative_household_income_change": 0.5017789670349119, + "population": 57719.93054066484 + }, + { + "constituency_code": "E14000000362", + "constituency_name": "Constituency 362", + "x": 20, + "y": 11, + "average_household_income_change": -1671.2986473147962, + "relative_household_income_change": -0.0, + "population": 113415.38429893683 + }, + { + "constituency_code": "E14000000363", + "constituency_name": "Constituency 363", + "x": 21, + "y": 11, + "average_household_income_change": 111.27087975723614, + "relative_household_income_change": 0.0, + "population": 68079.6212173605 + }, + { + "constituency_code": "E14000000364", + "constituency_name": "Constituency 364", + "x": 22, + "y": 11, + "average_household_income_change": -781.90725602331, + "relative_household_income_change": -0.0, + "population": 67864.18906912404 + }, + { + "constituency_code": "E14000000365", + "constituency_name": "Constituency 365", + "x": null, + "y": null, + "average_household_income_change": 305.0824783887256, + "relative_household_income_change": 0.4660933581476817, + "population": 61334.79792201664 + }, + { + "constituency_code": "E14000000366", + "constituency_name": "Constituency 366", + "x": 24, + "y": 11, + "average_household_income_change": 724.4525151520427, + "relative_household_income_change": 1e-12, + "population": 106024.91759136216 + }, + { + "constituency_code": "E14000000367", + "constituency_name": "Constituency 367", + "x": 25, + "y": 11, + "average_household_income_change": -1702.5549476447566, + "relative_household_income_change": 0.11056314456087024, + "population": 81926.19788223934 + }, + { + "constituency_code": "E14000000368", + "constituency_name": "Constituency 368", + "x": 26, + "y": 11, + "average_household_income_change": -1931.3909280413527, + "relative_household_income_change": 1e-12, + "population": 71770.85701884079 + }, + { + "constituency_code": "E14000000369", + "constituency_name": "Constituency 369", + "x": 27, + "y": 11, + "average_household_income_change": 792.0308313732289, + "relative_household_income_change": 1e-12, + "population": 50440.10731257584 + }, + { + "constituency_code": "E14000000370", + "constituency_name": "Constituency 370", + "x": 28, + "y": 11, + "average_household_income_change": 425.9231978760969, + "relative_household_income_change": 0.7075709754638798, + "population": 112090.1619356483 + }, + { + "constituency_code": "E14000000371", + "constituency_name": "Constituency 371", + "x": 29, + "y": 11, + "average_household_income_change": -1814.3519191458379, + "relative_household_income_change": 0.8091499706226665, + "population": 52356.510651433506 + }, + { + "constituency_code": "E14000000372", + "constituency_name": "Constituency 372", + "x": null, + "y": null, + "average_household_income_change": 1109.08621756159, + "relative_household_income_change": -0.0, + "population": 83600.63778977693 + }, + { + "constituency_code": "E14000000373", + "constituency_name": "Constituency 373", + "x": 0, + "y": 12, + "average_household_income_change": 19.22110165496216, + "relative_household_income_change": 0.5146548251212197, + "population": 66507.908891974 + }, + { + "constituency_code": "E14000000374", + "constituency_name": "Constituency 374", + "x": 1, + "y": 12, + "average_household_income_change": -749.5772000344579, + "relative_household_income_change": -3.5e-9, + "population": 146792.99486028682 + }, + { + "constituency_code": "E14000000375", + "constituency_name": "Constituency 375", + "x": 2, + "y": 12, + "average_household_income_change": -783.8395562619974, + "relative_household_income_change": 1e-12, + "population": 65422.167957346835 + }, + { + "constituency_code": "E14000000376", + "constituency_name": "Constituency 376", + "x": 3, + "y": 12, + "average_household_income_change": -1450.1221650989824, + "relative_household_income_change": 0.0, + "population": 85866.87293099564 + }, + { + "constituency_code": "E14000000377", + "constituency_name": "Constituency 377", + "x": 4, + "y": 12, + "average_household_income_change": -645.798670669981, + "relative_household_income_change": 0.4976229122040582, + "population": 122889.59326278509 + }, + { + "constituency_code": "E14000000378", + "constituency_name": "Constituency 378", + "x": 5, + "y": 12, + "average_household_income_change": 1635.1724174774276, + "relative_household_income_change": 0.0, + "population": 140388.28343393683 + }, + { + "constituency_code": "E14000000379", + "constituency_name": "Constituency 379", + "x": null, + "y": null, + "average_household_income_change": -1322.91414940455, + "relative_household_income_change": 1e-12, + "population": 130180.15071380371 + }, + { + "constituency_code": "E14000000380", + "constituency_name": "Constituency 380", + "x": 7, + "y": 12, + "average_household_income_change": 643.6955982549462, + "relative_household_income_change": 1e-12, + "population": 141937.50754987824 + }, + { + "constituency_code": "E14000000381", + "constituency_name": "Constituency 381", + "x": 8, + "y": 12, + "average_household_income_change": -1775.2096638418507, + "relative_household_income_change": 0.43429070796214286, + "population": 145004.63125557202 + }, + { + "constituency_code": "E14000000382", + "constituency_name": "Constituency 382", + "x": 9, + "y": 12, + "average_household_income_change": 1754.3529428875963, + "relative_household_income_change": 1e-12, + "population": 82461.35902260432 + }, + { + "constituency_code": "E14000000383", + "constituency_name": "Constituency 383", + "x": 10, + "y": 12, + "average_household_income_change": 1134.450520364727, + "relative_household_income_change": 1e-12, + "population": 146435.07039696595 + }, + { + "constituency_code": "E14000000384", + "constituency_name": "Constituency 384", + "x": 11, + "y": 12, + "average_household_income_change": -1935.1463493486115, + "relative_household_income_change": 0.32313335925070485, + "population": 58004.102496374035 + }, + { + "constituency_code": "E14000000385", + "constituency_name": "Constituency 385", + "x": 12, + "y": 12, + "average_household_income_change": -209.05028104926782, + "relative_household_income_change": 0.6186153260113829, + "population": 117034.62816551719 + }, + { + "constituency_code": "E14000000386", + "constituency_name": "Constituency 386", + "x": null, + "y": null, + "average_household_income_change": 1694.0160478141113, + "relative_household_income_change": -0.0, + "population": 89858.43775105188 + }, + { + "constituency_code": "E14000000387", + "constituency_name": "Constituency 387", + "x": 14, + "y": 12, + "average_household_income_change": 1203.3637271579084, + "relative_household_income_change": -3.5e-9, + "population": 147699.35190383965 + }, + { + "constituency_code": "E14000000388", + "constituency_name": "Constituency 388", + "x": 15, + "y": 12, + "average_household_income_change": -1041.2816219126073, + "relative_household_income_change": 0.7761888702877715, + "population": 140566.11583849424 + }, + { + "constituency_code": "E14000000389", + "constituency_name": "Constituency 389", + "x": 16, + "y": 12, + "average_household_income_change": 1963.4883502536732, + "relative_household_income_change": 0.15856590673397397, + "population": 99208.27114640783 + }, + { + "constituency_code": "E14000000390", + "constituency_name": "Constituency 390", + "x": 17, + "y": 12, + "average_household_income_change": -541.6746768853842, + "relative_household_income_change": -0.0, + "population": 146739.93179938247 + }, + { + "constituency_code": "E14000000391", + "constituency_name": "Constituency 391", + "x": 18, + "y": 12, + "average_household_income_change": 392.3345088407983, + "relative_household_income_change": -3.5e-9, + "population": 110310.79494795081 + }, + { + "constituency_code": "E14000000392", + "constituency_name": "Constituency 392", + "x": 19, + "y": 12, + "average_household_income_change": -1394.3824785730135, + "relative_household_income_change": 0.0, + "population": 91123.9105954635 + }, + { + "constituency_code": "E14000000393", + "constituency_name": "Constituency 393", + "x": null, + "y": null, + "average_household_income_change": 1886.147031653585, + "relative_household_income_change": 1e-12, + "population": 127053.70056596707 + }, + { + "constituency_code": "E14000000394", + "constituency_name": "Constituency 394", + "x": 21, + "y": 12, + "average_household_income_change": -764.3913703477714, + "relative_household_income_change": 0.0, + "population": 74690.3431446662 + }, + { + "constituency_code": "E14000000395", + "constituency_name": "Constituency 395", + "x": 22, + "y": 12, + "average_household_income_change": -412.86388601931725, + "relative_household_income_change": -0.0, + "population": 91152.69472270005 + }, + { + "constituency_code": "E14000000396", + "constituency_name": "Constituency 396", + "x": 23, + "y": 12, + "average_household_income_change": -523.5367854396005, + "relative_household_income_change": -0.0, + "population": 96083.32104944291 + }, + { + "constituency_code": "E14000000397", + "constituency_name": "Constituency 397", + "x": 24, + "y": 12, + "average_household_income_change": -438.4916791503861, + "relative_household_income_change": 0.36857333601514064, + "population": 65334.83510074024 + }, + { + "constituency_code": "E14000000398", + "constituency_name": "Constituency 398", + "x": 25, + "y": 12, + "average_household_income_change": -1489.3255914403437, + "relative_household_income_change": -0.0, + "population": 75879.3948917247 + }, + { + "constituency_code": "E14000000399", + "constituency_name": "Constituency 399", + "x": 26, + "y": 12, + "average_household_income_change": 1280.5129456302825, + "relative_household_income_change": 0.0, + "population": 140421.26314416766 + }, + { + "constituency_code": "E14000000400", + "constituency_name": "Constituency 400", + "x": null, + "y": null, + "average_household_income_change": 838.1710243074423, + "relative_household_income_change": 1e-12, + "population": 102164.8608901718 + }, + { + "constituency_code": "E14000000401", + "constituency_name": "Constituency 401", + "x": 28, + "y": 12, + "average_household_income_change": -1785.5002054920485, + "relative_household_income_change": -0.0, + "population": 87580.2271317752 + }, + { + "constituency_code": "E14000000402", + "constituency_name": "Constituency 402", + "x": 29, + "y": 12, + "average_household_income_change": -689.4004480676439, + "relative_household_income_change": 0.6742375088852286, + "population": 81438.53883171464 + }, + { + "constituency_code": "E14000000403", + "constituency_name": "Constituency 403", + "x": 30, + "y": 12, + "average_household_income_change": -393.4628128033797, + "relative_household_income_change": -0.0, + "population": 75039.98922314639 + }, + { + "constituency_code": "E14000000404", + "constituency_name": "Constituency 404", + "x": 0, + "y": 13, + "average_household_income_change": 1565.0837804033047, + "relative_household_income_change": 0.0, + "population": 142227.87444765354 + }, + { + "constituency_code": "E14000000405", + "constituency_name": "Constituency 405", + "x": 1, + "y": 13, + "average_household_income_change": -337.8714605234876, + "relative_household_income_change": -3.5e-9, + "population": 77203.57983346927 + }, + { + "constituency_code": "E14000000406", + "constituency_name": "Constituency 406", + "x": 2, + "y": 13, + "average_household_income_change": -1055.3789197118797, + "relative_household_income_change": 0.4078556824436944, + "population": 136422.76200474886 + }, + { + "constituency_code": "E14000000407", + "constituency_name": "Constituency 407", + "x": null, + "y": null, + "average_household_income_change": 834.0527556961325, + "relative_household_income_change": -3.5e-9, + "population": 97354.9639783863 + }, + { + "constituency_code": "E14000000408", + "constituency_name": "Constituency 408", + "x": 4, + "y": 13, + "average_household_income_change": 134.09988432838736, + "relative_household_income_change": -3.5e-9, + "population": 119310.48812370429 + }, + { + "constituency_code": "E14000000409", + "constituency_name": "Constituency 409", + "x": 5, + "y": 13, + "average_household_income_change": 710.0191188423665, + "relative_household_income_change": -3.5e-9, + "population": 104900.49608990214 + }, + { + "constituency_code": "E14000000410", + "constituency_name": "Constituency 410", + "x": 6, + "y": 13, + "average_household_income_change": -1733.3123895866431, + "relative_household_income_change": -3.5e-9, + "population": 72416.44538586303 + }, + { + "constituency_code": "E14000000411", + "constituency_name": "Constituency 411", + "x": 7, + "y": 13, + "average_household_income_change": 1328.957189349265, + "relative_household_income_change": 1e-12, + "population": 55101.62863024679 + }, + { + "constituency_code": "E14000000412", + "constituency_name": "Constituency 412", + "x": 8, + "y": 13, + "average_household_income_change": 864.9534307001913, + "relative_household_income_change": 0.25864922967497583, + "population": 82769.6707088191 + }, + { + "constituency_code": "E14000000413", + "constituency_name": "Constituency 413", + "x": 9, + "y": 13, + "average_household_income_change": -1015.563802054348, + "relative_household_income_change": 0.5566808097245476, + "population": 115698.84677273533 + }, + { + "constituency_code": "E14000000414", + "constituency_name": "Constituency 414", + "x": null, + "y": null, + "average_household_income_change": 1966.0549435935516, + "relative_household_income_change": -3.5e-9, + "population": 63072.63158724338 + }, + { + "constituency_code": "E14000000415", + "constituency_name": "Constituency 415", + "x": 11, + "y": 13, + "average_household_income_change": -1719.4482496747435, + "relative_household_income_change": 1e-12, + "population": 122400.05252854996 + }, + { + "constituency_code": "E14000000416", + "constituency_name": "Constituency 416", + "x": 12, + "y": 13, + "average_household_income_change": -637.0025407932425, + "relative_household_income_change": -0.0, + "population": 117953.03763761363 + }, + { + "constituency_code": "E14000000417", + "constituency_name": "Constituency 417", + "x": 13, + "y": 13, + "average_household_income_change": -576.1912016158312, + "relative_household_income_change": -0.0, + "population": 109259.17191042229 + }, + { + "constituency_code": "E14000000418", + "constituency_name": "Constituency 418", + "x": 14, + "y": 13, + "average_household_income_change": -1004.6878933670484, + "relative_household_income_change": -3.5e-9, + "population": 91871.97834788615 + }, + { + "constituency_code": "E14000000419", + "constituency_name": "Constituency 419", + "x": 15, + "y": 13, + "average_household_income_change": -1937.3634334742933, + "relative_household_income_change": 0.0, + "population": 115991.17237357103 + }, + { + "constituency_code": "E14000000420", + "constituency_name": "Constituency 420", + "x": 16, + "y": 13, + "average_household_income_change": -88.33450719112923, + "relative_household_income_change": 0.19477066794069864, + "population": 138651.37596406846 + }, + { + "constituency_code": "E14000000421", + "constituency_name": "Constituency 421", + "x": null, + "y": null, + "average_household_income_change": -1783.8506563658334, + "relative_household_income_change": -0.0, + "population": 119996.31865550006 + }, + { + "constituency_code": "E14000000422", + "constituency_name": "Constituency 422", + "x": 18, + "y": 13, + "average_household_income_change": -124.97928653299084, + "relative_household_income_change": -0.0, + "population": 103284.53004234466 + }, + { + "constituency_code": "E14000000423", + "constituency_name": "Constituency 423", + "x": 19, + "y": 13, + "average_household_income_change": 746.9717492722236, + "relative_household_income_change": 0.0, + "population": 64314.765602602485 + }, + { + "constituency_code": "E14000000424", + "constituency_name": "Constituency 424", + "x": 20, + "y": 13, + "average_household_income_change": -400.21091127364275, + "relative_household_income_change": -3.5e-9, + "population": 126140.46522738156 + }, + { + "constituency_code": "E14000000425", + "constituency_name": "Constituency 425", + "x": 21, + "y": 13, + "average_household_income_change": -8.615886541627926, + "relative_household_income_change": 1e-12, + "population": 120500.20874521669 + }, + { + "constituency_code": "E14000000426", + "constituency_name": "Constituency 426", + "x": 22, + "y": 13, + "average_household_income_change": -1445.5321322845048, + "relative_household_income_change": 0.9992850483781154, + "population": 78517.46219775046 + }, + { + "constituency_code": "E14000000427", + "constituency_name": "Constituency 427", + "x": 23, + "y": 13, + "average_household_income_change": 259.7025064134226, + "relative_household_income_change": -3.5e-9, + "population": 134534.28932349032 + }, + { + "constituency_code": "E14000000428", + "constituency_name": "Constituency 428", + "x": null, + "y": null, + "average_household_income_change": 1353.384121501907, + "relative_household_income_change": -3.5e-9, + "population": 65122.60724567148 + }, + { + "constituency_code": "E14000000429", + "constituency_name": "Constituency 429", + "x": 25, + "y": 13, + "average_household_income_change": -1202.1846279558727, + "relative_household_income_change": 0.4375422625855504, + "population": 106516.88841622724 + }, + { + "constituency_code": "E14000000430", + "constituency_name": "Constituency 430", + "x": 26, + "y": 13, + "average_household_income_change": -965.9386032117636, + "relative_household_income_change": -3.5e-9, + "population": 77348.31795576304 + }, + { + "constituency_code": "E14000000431", + "constituency_name": "Constituency 431", + "x": 27, + "y": 13, + "average_household_income_change": -399.31020340847834, + "relative_household_income_change": -0.0, + "population": 120119.21276118392 + }, + { + "constituency_code": "E14000000432", + "constituency_name": "Constituency 432", + "x": 28, + "y": 13, + "average_household_income_change": -1501.7510086178102, + "relative_household_income_change": -3.5e-9, + "population": 123543.00333458264 + }, + { + "constituency_code": "E14000000433", + "constituency_name": "Constituency 433", + "x": 29, + "y": 13, + "average_household_income_change": 1871.3633908875686, + "relative_household_income_change": -0.0, + "population": 114188.50689344354 + }, + { + "constituency_code": "E14000000434", + "constituency_name": "Constituency 434", + "x": 30, + "y": 13, + "average_household_income_change": -878.9359766848924, + "relative_household_income_change": 0.0, + "population": 137125.66547882586 + }, + { + "constituency_code": "E14000000435", + "constituency_name": "Constituency 435", + "x": null, + "y": null, + "average_household_income_change": 22.292631722566902, + "relative_household_income_change": -3.5e-9, + "population": 81603.38693974496 + }, + { + "constituency_code": "E14000000436", + "constituency_name": "Constituency 436", + "x": 1, + "y": 14, + "average_household_income_change": -858.5202969894166, + "relative_household_income_change": -3.5e-9, + "population": 134844.320946582 + }, + { + "constituency_code": "E14000000437", + "constituency_name": "Constituency 437", + "x": 2, + "y": 14, + "average_household_income_change": 1108.7892653049796, + "relative_household_income_change": 0.7974146129248088, + "population": 109738.3225739174 + }, + { + "constituency_code": "E14000000438", + "constituency_name": "Constituency 438", + "x": 3, + "y": 14, + "average_household_income_change": -1938.1221811323512, + "relative_household_income_change": -3.5e-9, + "population": 133395.10392182146 + }, + { + "constituency_code": "E14000000439", + "constituency_name": "Constituency 439", + "x": 4, + "y": 14, + "average_household_income_change": 519.5332360344125, + "relative_household_income_change": -0.0, + "population": 110056.89208575683 + }, + { + "constituency_code": "E14000000440", + "constituency_name": "Constituency 440", + "x": 5, + "y": 14, + "average_household_income_change": 1201.6281562769175, + "relative_household_income_change": 0.6330995821885036, + "population": 139221.9302277582 + }, + { + "constituency_code": "E14000000441", + "constituency_name": "Constituency 441", + "x": 6, + "y": 14, + "average_household_income_change": 1411.4779232097058, + "relative_household_income_change": -0.0, + "population": 98613.22805672791 + }, + { + "constituency_code": "E14000000442", + "constituency_name": "Constituency 442", + "x": null, + "y": null, + "average_household_income_change": -1849.2825797469372, + "relative_household_income_change": 1e-12, + "population": 114277.94687681618 + }, + { + "constituency_code": "E14000000443", + "constituency_name": "Constituency 443", + "x": 8, + "y": 14, + "average_household_income_change": 1479.1634504108054, + "relative_household_income_change": -0.0, + "population": 55027.6507208199 + }, + { + "constituency_code": "E14000000444", + "constituency_name": "Constituency 444", + "x": 9, + "y": 14, + "average_household_income_change": -312.3263436457391, + "relative_household_income_change": 0.5903607041796785, + "population": 134005.43950487245 + }, + { + "constituency_code": "E14000000445", + "constituency_name": "Constituency 445", + "x": 10, + "y": 14, + "average_household_income_change": -235.72010774130314, + "relative_household_income_change": -0.0, + "population": 107152.43583785828 + }, + { + "constituency_code": "E14000000446", + "constituency_name": "Constituency 446", + "x": 11, + "y": 14, + "average_household_income_change": 277.1497954833628, + "relative_household_income_change": 0.5135397749456319, + "population": 70104.98439053618 + }, + { + "constituency_code": "E14000000447", + "constituency_name": "Constituency 447", + "x": 12, + "y": 14, + "average_household_income_change": 1828.3291736397134, + "relative_household_income_change": 0.0, + "population": 105758.01403771316 + }, + { + "constituency_code": "E14000000448", + "constituency_name": "Constituency 448", + "x": 13, + "y": 14, + "average_household_income_change": -1577.4235955150164, + "relative_household_income_change": -0.0, + "population": 84769.36787383328 + }, + { + "constituency_code": "E14000000449", + "constituency_name": "Constituency 449", + "x": null, + "y": null, + "average_household_income_change": -1375.9862826114268, + "relative_household_income_change": -3.5e-9, + "population": 68155.11585838869 + }, + { + "constituency_code": "E14000000450", + "constituency_name": "Constituency 450", + "x": 15, + "y": 14, + "average_household_income_change": 1619.7588245435081, + "relative_household_income_change": 1e-12, + "population": 108529.78607189572 + }, + { + "constituency_code": "E14000000451", + "constituency_name": "Constituency 451", + "x": 16, + "y": 14, + "average_household_income_change": -130.43885920074817, + "relative_household_income_change": -3.5e-9, + "population": 102164.24550005347 + }, + { + "constituency_code": "E14000000452", + "constituency_name": "Constituency 452", + "x": 17, + "y": 14, + "average_household_income_change": 1575.9769085769442, + "relative_household_income_change": -0.0, + "population": 83074.55414942687 + }, + { + "constituency_code": "E14000000453", + "constituency_name": "Constituency 453", + "x": 18, + "y": 14, + "average_household_income_change": -1376.5227309882753, + "relative_household_income_change": 1e-12, + "population": 76954.27379439081 + }, + { + "constituency_code": "E14000000454", + "constituency_name": "Constituency 454", + "x": 19, + "y": 14, + "average_household_income_change": 27.855930561574205, + "relative_household_income_change": -3.5e-9, + "population": 67970.8621895939 + }, + { + "constituency_code": "E14000000455", + "constituency_name": "Constituency 455", + "x": 20, + "y": 14, + "average_household_income_change": 255.4598736945679, + "relative_household_income_change": -0.0, + "population": 134897.99335933474 + }, + { + "constituency_code": "E14000000456", + "constituency_name": "Constituency 456", + "x": null, + "y": null, + "average_household_income_change": -1470.9287179798966, + "relative_household_income_change": -0.0, + "population": 110214.6845204571 + }, + { + "constituency_code": "E14000000457", + "constituency_name": "Constituency 457", + "x": 22, + "y": 14, + "average_household_income_change": -1065.357672584253, + "relative_household_income_change": 0.0, + "population": 85225.7969482269 + }, + { + "constituency_code": "E14000000458", + "constituency_name": "Constituency 458", + "x": 23, + "y": 14, + "average_household_income_change": 1826.5135187399758, + "relative_household_income_change": 1e-12, + "population": 98812.90540379459 + }, + { + "constituency_code": "E14000000459", + "constituency_name": "Constituency 459", + "x": 24, + "y": 14, + "average_household_income_change": -1758.258007451244, + "relative_household_income_change": 0.0, + "population": 120834.59886771583 + }, + { + "constituency_code": "E14000000460", + "constituency_name": "Constituency 460", + "x": 25, + "y": 14, + "average_household_income_change": 1661.4752599701808, + "relative_household_income_change": -3.5e-9, + "population": 140361.971015295 + }, + { + "constituency_code": "E14000000461", + "constituency_name": "Constituency 461", + "x": 26, + "y": 14, + "average_household_income_change": 843.8123826337538, + "relative_household_income_change": -0.0, + "population": 107298.60428240836 + }, + { + "constituency_code": "E14000000462", + "constituency_name": "Constituency 462", + "x": 27, + "y": 14, + "average_household_income_change": -261.89617854069394, + "relative_household_income_change": -0.0, + "population": 64880.04282406481 + }, + { + "constituency_code": "E14000000463", + "constituency_name": "Constituency 463", + "x": null, + "y": null, + "average_household_income_change": -362.59096189355546, + "relative_household_income_change": 0.0, + "population": 50746.49871824345 + }, + { + "constituency_code": "E14000000464", + "constituency_name": "Constituency 464", + "x": 29, + "y": 14, + "average_household_income_change": -1379.3381831933407, + "relative_household_income_change": -3.5e-9, + "population": 81843.30796123961 + }, + { + "constituency_code": "E14000000465", + "constituency_name": "Constituency 465", + "x": 30, + "y": 14, + "average_household_income_change": -895.9319061295998, + "relative_household_income_change": -0.0, + "population": 86307.51948753887 + }, + { + "constituency_code": "E14000000466", + "constituency_name": "Constituency 466", + "x": 0, + "y": 15, + "average_household_income_change": -1045.5240756289488, + "relative_household_income_change": 0.0, + "population": 106630.97285104157 + }, + { + "constituency_code": "E14000000467", + "constituency_name": "Constituency 467", + "x": 1, + "y": 15, + "average_household_income_change": -131.40113141275344, + "relative_household_income_change": 0.0, + "population": 85625.67572050777 + }, + { + "constituency_code": "E14000000468", + "constituency_name": "Constituency 468", + "x": 2, + "y": 15, + "average_household_income_change": -864.2228005114356, + "relative_household_income_change": 1e-12, + "population": 110692.75990094521 + }, + { + "constituency_code": "E14000000469", + "constituency_name": "Constituency 469", + "x": 3, + "y": 15, + "average_household_income_change": -1217.396077124258, + "relative_household_income_change": 1e-12, + "population": 95791.24250102474 + }, + { + "constituency_code": "E14000000470", + "constituency_name": "Constituency 470", + "x": null, + "y": null, + "average_household_income_change": 819.4095140623756, + "relative_household_income_change": -3.5e-9, + "population": 132591.75404400696 + }, + { + "constituency_code": "E14000000471", + "constituency_name": "Constituency 471", + "x": 5, + "y": 15, + "average_household_income_change": -677.4478721217139, + "relative_household_income_change": -0.0, + "population": 93372.07825937188 + }, + { + "constituency_code": "E14000000472", + "constituency_name": "Constituency 472", + "x": 6, + "y": 15, + "average_household_income_change": 769.2812919052758, + "relative_household_income_change": 0.35070114616556214, + "population": 82749.8384185931 + }, + { + "constituency_code": "E14000000473", + "constituency_name": "Constituency 473", + "x": 7, + "y": 15, + "average_household_income_change": 1826.5823371023187, + "relative_household_income_change": -0.0, + "population": 94452.51692962078 + }, + { + "constituency_code": "E14000000474", + "constituency_name": "Constituency 474", + "x": 8, + "y": 15, + "average_household_income_change": -854.2150106850004, + "relative_household_income_change": 0.0, + "population": 73725.82272334029 + }, + { + "constituency_code": "E14000000475", + "constituency_name": "Constituency 475", + "x": 9, + "y": 15, + "average_household_income_change": 1825.4016048874723, + "relative_household_income_change": 0.0, + "population": 77291.27368977931 + }, + { + "constituency_code": "E14000000476", + "constituency_name": "Constituency 476", + "x": 10, + "y": 15, + "average_household_income_change": 216.77639129025695, + "relative_household_income_change": 0.0, + "population": 77824.36965646 + }, + { + "constituency_code": "E14000000477", + "constituency_name": "Constituency 477", + "x": null, + "y": null, + "average_household_income_change": -1593.3122775483603, + "relative_household_income_change": -3.5e-9, + "population": 111493.02905492586 + }, + { + "constituency_code": "E14000000478", + "constituency_name": "Constituency 478", + "x": 12, + "y": 15, + "average_household_income_change": -1262.0158636617136, + "relative_household_income_change": -0.0, + "population": 57389.887600907605 + }, + { + "constituency_code": "E14000000479", + "constituency_name": "Constituency 479", + "x": 13, + "y": 15, + "average_household_income_change": -1737.3547076698944, + "relative_household_income_change": 0.4758874388681912, + "population": 146184.4538265504 + }, + { + "constituency_code": "E14000000480", + "constituency_name": "Constituency 480", + "x": 14, + "y": 15, + "average_household_income_change": -1337.146372116397, + "relative_household_income_change": -0.0, + "population": 99503.02345698366 + }, + { + "constituency_code": "E14000000481", + "constituency_name": "Constituency 481", + "x": 15, + "y": 15, + "average_household_income_change": -443.31641902452026, + "relative_household_income_change": 1e-12, + "population": 95722.83718255228 + }, + { + "constituency_code": "E14000000482", + "constituency_name": "Constituency 482", + "x": 16, + "y": 15, + "average_household_income_change": 500.8423169444973, + "relative_household_income_change": 1e-12, + "population": 93764.74125416626 + }, + { + "constituency_code": "E14000000483", + "constituency_name": "Constituency 483", + "x": 17, + "y": 15, + "average_household_income_change": -359.07471826969186, + "relative_household_income_change": 0.0, + "population": 138311.96152862016 + }, + { + "constituency_code": "E14000000484", + "constituency_name": "Constituency 484", + "x": null, + "y": null, + "average_household_income_change": 1395.8256437349855, + "relative_household_income_change": -0.0, + "population": 86636.26588590886 + }, + { + "constituency_code": "E14000000485", + "constituency_name": "Constituency 485", + "x": 19, + "y": 15, + "average_household_income_change": 957.414181435833, + "relative_household_income_change": -3.5e-9, + "population": 68778.62572790433 + }, + { + "constituency_code": "E14000000486", + "constituency_name": "Constituency 486", + "x": 20, + "y": 15, + "average_household_income_change": 52.068594084960566, + "relative_household_income_change": -0.0, + "population": 149629.3667680624 + }, + { + "constituency_code": "E14000000487", + "constituency_name": "Constituency 487", + "x": 21, + "y": 15, + "average_household_income_change": -464.85862856143, + "relative_household_income_change": -0.0, + "population": 110352.0278947326 + }, + { + "constituency_code": "E14000000488", + "constituency_name": "Constituency 488", + "x": 22, + "y": 15, + "average_household_income_change": 1764.0835881287157, + "relative_household_income_change": 1e-12, + "population": 62384.47166940049 + }, + { + "constituency_code": "E14000000489", + "constituency_name": "Constituency 489", + "x": 23, + "y": 15, + "average_household_income_change": 692.3998314092001, + "relative_household_income_change": 0.0, + "population": 85408.80666901525 + }, + { + "constituency_code": "E14000000490", + "constituency_name": "Constituency 490", + "x": 24, + "y": 15, + "average_household_income_change": 1601.0227417620797, + "relative_household_income_change": 0.3256023747916895, + "population": 127392.7504156333 + }, + { + "constituency_code": "E14000000491", + "constituency_name": "Constituency 491", + "x": null, + "y": null, + "average_household_income_change": -924.525713053443, + "relative_household_income_change": 1e-12, + "population": 115834.91080642746 + }, + { + "constituency_code": "E14000000492", + "constituency_name": "Constituency 492", + "x": 26, + "y": 15, + "average_household_income_change": 1607.7828851379104, + "relative_household_income_change": 0.08626010051598998, + "population": 116576.36483302494 + }, + { + "constituency_code": "E14000000493", + "constituency_name": "Constituency 493", + "x": 27, + "y": 15, + "average_household_income_change": 392.5900111746632, + "relative_household_income_change": -0.0, + "population": 132360.86716965502 + }, + { + "constituency_code": "E14000000494", + "constituency_name": "Constituency 494", + "x": 28, + "y": 15, + "average_household_income_change": 223.9340392642153, + "relative_household_income_change": -3.5e-9, + "population": 134846.52691992815 + }, + { + "constituency_code": "E14000000495", + "constituency_name": "Constituency 495", + "x": 29, + "y": 15, + "average_household_income_change": 1441.2988042773184, + "relative_household_income_change": 0.0, + "population": 137986.4965672183 + }, + { + "constituency_code": "E14000000496", + "constituency_name": "Constituency 496", + "x": 30, + "y": 15, + "average_household_income_change": -498.7039191058127, + "relative_household_income_change": 0.3252945301780501, + "population": 143405.9946706618 + }, + { + "constituency_code": "E14000000497", + "constituency_name": "Constituency 497", + "x": 0, + "y": 16, + "average_household_income_change": 1133.1963374325728, + "relative_household_income_change": 1e-12, + "population": 68426.46908976509 + }, + { + "constituency_code": "E14000000498", + "constituency_name": "Constituency 498", + "x": null, + "y": null, + "average_household_income_change": 1552.2279517645652, + "relative_household_income_change": 1e-12, + "population": 69801.21947574713 + }, + { + "constituency_code": "E14000000499", + "constituency_name": "Constituency 499", + "x": 2, + "y": 16, + "average_household_income_change": -1933.0121573332403, + "relative_household_income_change": -0.0, + "population": 71810.7127554828 + }, + { + "constituency_code": "E14000000500", + "constituency_name": "Constituency 500", + "x": 3, + "y": 16, + "average_household_income_change": 1856.020820102462, + "relative_household_income_change": -0.0, + "population": 115990.60962848747 + }, + { + "constituency_code": "E14000000501", + "constituency_name": "Constituency 501", + "x": 4, + "y": 16, + "average_household_income_change": 1939.131245149897, + "relative_household_income_change": 0.0, + "population": 145774.10814719292 + }, + { + "constituency_code": "E14000000502", + "constituency_name": "Constituency 502", + "x": 5, + "y": 16, + "average_household_income_change": 1644.716537294447, + "relative_household_income_change": -0.0, + "population": 115658.11807754858 + }, + { + "constituency_code": "E14000000503", + "constituency_name": "Constituency 503", + "x": 6, + "y": 16, + "average_household_income_change": -1636.9003200301875, + "relative_household_income_change": 0.0, + "population": 89531.70714848021 + }, + { + "constituency_code": "E14000000504", + "constituency_name": "Constituency 504", + "x": 7, + "y": 16, + "average_household_income_change": 88.92124000860102, + "relative_household_income_change": 1e-12, + "population": 125688.2659888468 + }, + { + "constituency_code": "E14000000505", + "constituency_name": "Constituency 505", + "x": null, + "y": null, + "average_household_income_change": -1318.7744512100821, + "relative_household_income_change": 0.0, + "population": 91088.20168102277 + }, + { + "constituency_code": "E14000000506", + "constituency_name": "Constituency 506", + "x": 9, + "y": 16, + "average_household_income_change": -1175.9495393146576, + "relative_household_income_change": 0.30616875596009807, + "population": 131214.95491923267 + }, + { + "constituency_code": "E14000000507", + "constituency_name": "Constituency 507", + "x": 10, + "y": 16, + "average_household_income_change": -1439.7064451060162, + "relative_household_income_change": -3.5e-9, + "population": 119035.7114330096 + }, + { + "constituency_code": "E14000000508", + "constituency_name": "Constituency 508", + "x": 11, + "y": 16, + "average_household_income_change": 525.9315378974767, + "relative_household_income_change": 0.0, + "population": 149780.60570252594 + }, + { + "constituency_code": "E14000000509", + "constituency_name": "Constituency 509", + "x": 12, + "y": 16, + "average_household_income_change": -1367.1976497187427, + "relative_household_income_change": 0.0, + "population": 99775.86963739073 + }, + { + "constituency_code": "E14000000510", + "constituency_name": "Constituency 510", + "x": 13, + "y": 16, + "average_household_income_change": 681.0185339591745, + "relative_household_income_change": 0.0, + "population": 52250.53683271075 + }, + { + "constituency_code": "E14000000511", + "constituency_name": "Constituency 511", + "x": 14, + "y": 16, + "average_household_income_change": 711.0597691914737, + "relative_household_income_change": -0.0, + "population": 73213.28057757275 + }, + { + "constituency_code": "E14000000512", + "constituency_name": "Constituency 512", + "x": null, + "y": null, + "average_household_income_change": 488.84935913679016, + "relative_household_income_change": 0.0, + "population": 125981.89147263978 + }, + { + "constituency_code": "E14000000513", + "constituency_name": "Constituency 513", + "x": 16, + "y": 16, + "average_household_income_change": -1196.9661233102288, + "relative_household_income_change": -3.5e-9, + "population": 128616.27263812006 + }, + { + "constituency_code": "E14000000514", + "constituency_name": "Constituency 514", + "x": 17, + "y": 16, + "average_household_income_change": 1539.7654878967505, + "relative_household_income_change": 1e-12, + "population": 104552.41760001461 + }, + { + "constituency_code": "E14000000515", + "constituency_name": "Constituency 515", + "x": 18, + "y": 16, + "average_household_income_change": 664.5980280202077, + "relative_household_income_change": 0.9157729795254148, + "population": 132900.03832707356 + }, + { + "constituency_code": "E14000000516", + "constituency_name": "Constituency 516", + "x": 19, + "y": 16, + "average_household_income_change": 874.7981354443475, + "relative_household_income_change": -0.0, + "population": 139599.38195812594 + }, + { + "constituency_code": "E14000000517", + "constituency_name": "Constituency 517", + "x": 20, + "y": 16, + "average_household_income_change": -92.51945756994174, + "relative_household_income_change": -0.0, + "population": 127203.73196954656 + }, + { + "constituency_code": "E14000000518", + "constituency_name": "Constituency 518", + "x": 21, + "y": 16, + "average_household_income_change": 1401.7863678742444, + "relative_household_income_change": 0.0, + "population": 101400.21509992852 + }, + { + "constituency_code": "E14000000519", + "constituency_name": "Constituency 519", + "x": null, + "y": null, + "average_household_income_change": 950.872054844548, + "relative_household_income_change": -3.5e-9, + "population": 102808.51547701252 + }, + { + "constituency_code": "E14000000520", + "constituency_name": "Constituency 520", + "x": 23, + "y": 16, + "average_household_income_change": 267.1213839802129, + "relative_household_income_change": 0.8801315917911949, + "population": 113871.08181816454 + }, + { + "constituency_code": "E14000000521", + "constituency_name": "Constituency 521", + "x": 24, + "y": 16, + "average_household_income_change": 1583.6668839155411, + "relative_household_income_change": -0.0, + "population": 76415.2914843896 + }, + { + "constituency_code": "E14000000522", + "constituency_name": "Constituency 522", + "x": 25, + "y": 16, + "average_household_income_change": 473.62702776804167, + "relative_household_income_change": -0.0, + "population": 110938.16395304399 + }, + { + "constituency_code": "E14000000523", + "constituency_name": "Constituency 523", + "x": 26, + "y": 16, + "average_household_income_change": 1661.2704907714462, + "relative_household_income_change": 1e-12, + "population": 86960.28366122275 + }, + { + "constituency_code": "E14000000524", + "constituency_name": "Constituency 524", + "x": 27, + "y": 16, + "average_household_income_change": 1677.6832707399083, + "relative_household_income_change": -0.0, + "population": 62627.66271913964 + }, + { + "constituency_code": "E14000000525", + "constituency_name": "Constituency 525", + "x": 28, + "y": 16, + "average_household_income_change": 32.65960657239475, + "relative_household_income_change": 0.8058113644644113, + "population": 88512.16871276736 + }, + { + "constituency_code": "E14000000526", + "constituency_name": "Constituency 526", + "x": null, + "y": null, + "average_household_income_change": 956.6026427007084, + "relative_household_income_change": 1e-12, + "population": 67177.90548895177 + }, + { + "constituency_code": "E14000000527", + "constituency_name": "Constituency 527", + "x": 30, + "y": 16, + "average_household_income_change": -79.65777433093812, + "relative_household_income_change": -0.0, + "population": 129359.15970497992 + }, + { + "constituency_code": "E14000000528", + "constituency_name": "Constituency 528", + "x": 0, + "y": 17, + "average_household_income_change": -1530.3875617109775, + "relative_household_income_change": -3.5e-9, + "population": 122544.81803253728 + }, + { + "constituency_code": "E14000000529", + "constituency_name": "Constituency 529", + "x": 1, + "y": 17, + "average_household_income_change": -690.1267696520264, + "relative_household_income_change": -0.0, + "population": 74964.53753227353 + }, + { + "constituency_code": "E14000000530", + "constituency_name": "Constituency 530", + "x": 2, + "y": 17, + "average_household_income_change": 1821.0119974157406, + "relative_household_income_change": -3.5e-9, + "population": 117617.45171258436 + }, + { + "constituency_code": "E14000000531", + "constituency_name": "Constituency 531", + "x": 3, + "y": 17, + "average_household_income_change": 208.0498046541739, + "relative_household_income_change": -3.5e-9, + "population": 143004.6731627013 + }, + { + "constituency_code": "E14000000532", + "constituency_name": "Constituency 532", + "x": 4, + "y": 17, + "average_household_income_change": 24.455900708818756, + "relative_household_income_change": 0.0, + "population": 74337.36080179275 + }, + { + "constituency_code": "E14000000533", + "constituency_name": "Constituency 533", + "x": null, + "y": null, + "average_household_income_change": 1983.1116832288517, + "relative_household_income_change": -3.5e-9, + "population": 117952.23903240418 + }, + { + "constituency_code": "E14000000534", + "constituency_name": "Constituency 534", + "x": 6, + "y": 17, + "average_household_income_change": 1027.6081219737403, + "relative_household_income_change": 0.6042977436890922, + "population": 122635.04116619783 + }, + { + "constituency_code": "E14000000535", + "constituency_name": "Constituency 535", + "x": 7, + "y": 17, + "average_household_income_change": 883.3729304827402, + "relative_household_income_change": -0.0, + "population": 84563.45632753313 + }, + { + "constituency_code": "E14000000536", + "constituency_name": "Constituency 536", + "x": 8, + "y": 17, + "average_household_income_change": -415.0102749434339, + "relative_household_income_change": -3.5e-9, + "population": 139019.39363636472 + }, + { + "constituency_code": "E14000000537", + "constituency_name": "Constituency 537", + "x": 9, + "y": 17, + "average_household_income_change": -929.7356907140188, + "relative_household_income_change": -3.5e-9, + "population": 62512.41742705785 + }, + { + "constituency_code": "E14000000538", + "constituency_name": "Constituency 538", + "x": 10, + "y": 17, + "average_household_income_change": -1996.7697301134376, + "relative_household_income_change": 0.0, + "population": 90369.34146142566 + }, + { + "constituency_code": "E14000000539", + "constituency_name": "Constituency 539", + "x": 11, + "y": 17, + "average_household_income_change": 1801.4507622204592, + "relative_household_income_change": 0.7875965623100697, + "population": 118552.27021021653 + }, + { + "constituency_code": "E14000000540", + "constituency_name": "Constituency 540", + "x": null, + "y": null, + "average_household_income_change": -568.5524660509858, + "relative_household_income_change": -3.5e-9, + "population": 129523.3537724613 + }, + { + "constituency_code": "E14000000541", + "constituency_name": "Constituency 541", + "x": 13, + "y": 17, + "average_household_income_change": 1272.6941414223477, + "relative_household_income_change": -0.0, + "population": 57640.64659864336 + }, + { + "constituency_code": "E14000000542", + "constituency_name": "Constituency 542", + "x": 14, + "y": 17, + "average_household_income_change": -767.5057915657742, + "relative_household_income_change": 0.3357304975304993, + "population": 115692.15832822133 + }, + { + "constituency_code": "E14000000543", + "constituency_name": "Constituency 543", + "x": 15, + "y": 17, + "average_household_income_change": 70.06268109612046, + "relative_household_income_change": 0.0, + "population": 87007.97793879958 + }, + { + "constituency_code": "E14000000544", + "constituency_name": "Constituency 544", + "x": 16, + "y": 17, + "average_household_income_change": 1966.6092641458092, + "relative_household_income_change": 0.0, + "population": 114343.38680480534 + }, + { + "constituency_code": "E14000000545", + "constituency_name": "Constituency 545", + "x": 17, + "y": 17, + "average_household_income_change": -350.98957610023353, + "relative_household_income_change": 1e-12, + "population": 121673.71687105054 + }, + { + "constituency_code": "E14000000546", + "constituency_name": "Constituency 546", + "x": 18, + "y": 17, + "average_household_income_change": 284.78850562685795, + "relative_household_income_change": -3.5e-9, + "population": 90107.91467113272 + }, + { + "constituency_code": "E14000000547", + "constituency_name": "Constituency 547", + "x": null, + "y": null, + "average_household_income_change": 540.7926305781476, + "relative_household_income_change": -0.0, + "population": 77857.17106791587 + }, + { + "constituency_code": "E14000000548", + "constituency_name": "Constituency 548", + "x": 20, + "y": 17, + "average_household_income_change": 1572.495720645288, + "relative_household_income_change": 1e-12, + "population": 63776.77103353226 + }, + { + "constituency_code": "E14000000549", + "constituency_name": "Constituency 549", + "x": 21, + "y": 17, + "average_household_income_change": 786.1815131891445, + "relative_household_income_change": 0.0, + "population": 72317.31785925994 + }, + { + "constituency_code": "E14000000550", + "constituency_name": "Constituency 550", + "x": 22, + "y": 17, + "average_household_income_change": 501.0373161137469, + "relative_household_income_change": -3.5e-9, + "population": 51968.97767258395 + }, + { + "constituency_code": "E14000000551", + "constituency_name": "Constituency 551", + "x": 23, + "y": 17, + "average_household_income_change": -872.3149541947821, + "relative_household_income_change": 0.0, + "population": 103860.54079116536 + }, + { + "constituency_code": "E14000000552", + "constituency_name": "Constituency 552", + "x": 24, + "y": 17, + "average_household_income_change": -1729.9601043319988, + "relative_household_income_change": 0.0, + "population": 144540.067456093 + }, + { + "constituency_code": "E14000000553", + "constituency_name": "Constituency 553", + "x": 25, + "y": 17, + "average_household_income_change": -1180.1590196030402, + "relative_household_income_change": 1e-12, + "population": 66543.61008387458 + }, + { + "constituency_code": "E14000000554", + "constituency_name": "Constituency 554", + "x": null, + "y": null, + "average_household_income_change": 58.6742524695163, + "relative_household_income_change": 1e-12, + "population": 141632.26250944004 + }, + { + "constituency_code": "E14000000555", + "constituency_name": "Constituency 555", + "x": 27, + "y": 17, + "average_household_income_change": -1379.002800676671, + "relative_household_income_change": 1e-12, + "population": 65107.374171665964 + }, + { + "constituency_code": "E14000000556", + "constituency_name": "Constituency 556", + "x": 28, + "y": 17, + "average_household_income_change": -1534.8529282878776, + "relative_household_income_change": -3.5e-9, + "population": 98585.83289728437 + }, + { + "constituency_code": "E14000000557", + "constituency_name": "Constituency 557", + "x": 29, + "y": 17, + "average_household_income_change": 1195.252276686837, + "relative_household_income_change": 0.0, + "population": 121134.06333908037 + }, + { + "constituency_code": "E14000000558", + "constituency_name": "Constituency 558", + "x": 30, + "y": 17, + "average_household_income_change": -587.1983257619266, + "relative_household_income_change": 1e-12, + "population": 56035.946122824156 + }, + { + "constituency_code": "E14000000559", + "constituency_name": "Constituency 559", + "x": 0, + "y": 18, + "average_household_income_change": -1329.7265899480517, + "relative_household_income_change": 0.0, + "population": 75557.55189169839 + }, + { + "constituency_code": "E14000000560", + "constituency_name": "Constituency 560", + "x": 1, + "y": 18, + "average_household_income_change": -1255.3949599405319, + "relative_household_income_change": 1e-12, + "population": 94964.38366509751 + }, + { + "constituency_code": "E14000000561", + "constituency_name": "Constituency 561", + "x": null, + "y": null, + "average_household_income_change": 1852.312025967675, + "relative_household_income_change": 0.0, + "population": 124320.79269576802 + }, + { + "constituency_code": "E14000000562", + "constituency_name": "Constituency 562", + "x": 3, + "y": 18, + "average_household_income_change": 1216.5399142250092, + "relative_household_income_change": -3.5e-9, + "population": 72214.34664091107 + }, + { + "constituency_code": "E14000000563", + "constituency_name": "Constituency 563", + "x": 4, + "y": 18, + "average_household_income_change": 936.0199128578968, + "relative_household_income_change": -0.0, + "population": 52121.195242426424 + }, + { + "constituency_code": "E14000000564", + "constituency_name": "Constituency 564", + "x": 5, + "y": 18, + "average_household_income_change": 460.4087216784598, + "relative_household_income_change": 0.0, + "population": 132579.04007382633 + }, + { + "constituency_code": "E14000000565", + "constituency_name": "Constituency 565", + "x": 6, + "y": 18, + "average_household_income_change": -1228.017075495524, + "relative_household_income_change": 1e-12, + "population": 127756.68581745084 + }, + { + "constituency_code": "E14000000566", + "constituency_name": "Constituency 566", + "x": 7, + "y": 18, + "average_household_income_change": 989.0043124308359, + "relative_household_income_change": 1e-12, + "population": 96691.3995080644 + }, + { + "constituency_code": "E14000000567", + "constituency_name": "Constituency 567", + "x": 8, + "y": 18, + "average_household_income_change": 633.2752797320067, + "relative_household_income_change": -3.5e-9, + "population": 105847.73106323073 + }, + { + "constituency_code": "E14000000568", + "constituency_name": "Constituency 568", + "x": null, + "y": null, + "average_household_income_change": 1537.6835760239028, + "relative_household_income_change": -0.0, + "population": 59574.52355411442 + }, + { + "constituency_code": "E14000000569", + "constituency_name": "Constituency 569", + "x": 10, + "y": 18, + "average_household_income_change": 564.9755937017145, + "relative_household_income_change": 0.4342081333144031, + "population": 122732.6148148665 + }, + { + "constituency_code": "E14000000570", + "constituency_name": "Constituency 570", + "x": 11, + "y": 18, + "average_household_income_change": 1901.1059243448528, + "relative_household_income_change": -3.5e-9, + "population": 86291.08878565823 + }, + { + "constituency_code": "E14000000571", + "constituency_name": "Constituency 571", + "x": 12, + "y": 18, + "average_household_income_change": 1647.0976068910384, + "relative_household_income_change": 0.0, + "population": 83118.92406031303 + }, + { + "constituency_code": "E14000000572", + "constituency_name": "Constituency 572", + "x": 13, + "y": 18, + "average_household_income_change": 917.6942423765499, + "relative_household_income_change": 0.7141296082160444, + "population": 83980.99861545017 + }, + { + "constituency_code": "E14000000573", + "constituency_name": "Constituency 573", + "x": 14, + "y": 18, + "average_household_income_change": -794.8516659664629, + "relative_household_income_change": -0.0, + "population": 116611.44894635049 + }, + { + "constituency_code": "E14000000574", + "constituency_name": "Constituency 574", + "x": 15, + "y": 18, + "average_household_income_change": 779.5916049469769, + "relative_household_income_change": 0.9569943470482749, + "population": 56838.49468248409 + }, + { + "constituency_code": "E14000000575", + "constituency_name": "Constituency 575", + "x": null, + "y": null, + "average_household_income_change": 1652.578569337204, + "relative_household_income_change": -0.0, + "population": 104940.63353614656 + }, + { + "constituency_code": "E14000000576", + "constituency_name": "Constituency 576", + "x": 17, + "y": 18, + "average_household_income_change": 307.4118121606677, + "relative_household_income_change": 1e-12, + "population": 126993.11969852142 + }, + { + "constituency_code": "E14000000577", + "constituency_name": "Constituency 577", + "x": 18, + "y": 18, + "average_household_income_change": 741.5070307134765, + "relative_household_income_change": 1e-12, + "population": 119936.8884747448 + }, + { + "constituency_code": "E14000000578", + "constituency_name": "Constituency 578", + "x": 19, + "y": 18, + "average_household_income_change": -293.01348432114384, + "relative_household_income_change": -0.0, + "population": 139054.8255490753 + }, + { + "constituency_code": "E14000000579", + "constituency_name": "Constituency 579", + "x": 20, + "y": 18, + "average_household_income_change": 1131.8770630588108, + "relative_household_income_change": 0.0, + "population": 72826.75061051587 + }, + { + "constituency_code": "E14000000580", + "constituency_name": "Constituency 580", + "x": 21, + "y": 18, + "average_household_income_change": -630.9564099040315, + "relative_household_income_change": -3.5e-9, + "population": 56888.615982387026 + }, + { + "constituency_code": "E14000000581", + "constituency_name": "Constituency 581", + "x": 22, + "y": 18, + "average_household_income_change": 1554.3278310363116, + "relative_household_income_change": 0.0, + "population": 145841.03237646338 + }, + { + "constituency_code": "E14000000582", + "constituency_name": "Constituency 582", + "x": null, + "y": null, + "average_household_income_change": 960.0847099843812, + "relative_household_income_change": -0.0, + "population": 137570.1463791927 + }, + { + "constituency_code": "E14000000583", + "constituency_name": "Constituency 583", + "x": 24, + "y": 18, + "average_household_income_change": 823.4577882062744, + "relative_household_income_change": 0.8625367572015296, + "population": 130636.04667489542 + }, + { + "constituency_code": "E14000000584", + "constituency_name": "Constituency 584", + "x": 25, + "y": 18, + "average_household_income_change": -70.09732998103146, + "relative_household_income_change": 0.0, + "population": 70802.83526568713 + }, + { + "constituency_code": "E14000000585", + "constituency_name": "Constituency 585", + "x": 26, + "y": 18, + "average_household_income_change": 1592.447556354229, + "relative_household_income_change": 1e-12, + "population": 60038.29592953278 + }, + { + "constituency_code": "E14000000586", + "constituency_name": "Constituency 586", + "x": 27, + "y": 18, + "average_household_income_change": 1561.290651214074, + "relative_household_income_change": 0.0, + "population": 123015.32138698698 + }, + { + "constituency_code": "E14000000587", + "constituency_name": "Constituency 587", + "x": 28, + "y": 18, + "average_household_income_change": 92.60827995758403, + "relative_household_income_change": -3.5e-9, + "population": 74372.69820872009 + }, + { + "constituency_code": "E14000000588", + "constituency_name": "Constituency 588", + "x": 29, + "y": 18, + "average_household_income_change": -1735.1883462164376, + "relative_household_income_change": 0.8652316608891197, + "population": 107990.85608582196 + }, + { + "constituency_code": "E14000000589", + "constituency_name": "Constituency 589", + "x": null, + "y": null, + "average_household_income_change": -731.794768168398, + "relative_household_income_change": -0.0, + "population": 133607.86126488214 + }, + { + "constituency_code": "E14000000590", + "constituency_name": "Constituency 590", + "x": 0, + "y": 19, + "average_household_income_change": 1124.1223787780555, + "relative_household_income_change": 0.9933078591651776, + "population": 55151.75031185687 + }, + { + "constituency_code": "E14000000591", + "constituency_name": "Constituency 591", + "x": 1, + "y": 19, + "average_household_income_change": -804.9034884896406, + "relative_household_income_change": 0.0, + "population": 132303.99221559628 + }, + { + "constituency_code": "E14000000592", + "constituency_name": "Constituency 592", + "x": 2, + "y": 19, + "average_household_income_change": -265.5169125780508, + "relative_household_income_change": -3.5e-9, + "population": 53366.22724187432 + }, + { + "constituency_code": "E14000000593", + "constituency_name": "Constituency 593", + "x": 3, + "y": 19, + "average_household_income_change": -1961.2404528225684, + "relative_household_income_change": 1e-12, + "population": 97782.92636483927 + }, + { + "constituency_code": "E14000000594", + "constituency_name": "Constituency 594", + "x": 4, + "y": 19, + "average_household_income_change": 477.65139708514994, + "relative_household_income_change": 1e-12, + "population": 84078.00961891914 + }, + { + "constituency_code": "E14000000595", + "constituency_name": "Constituency 595", + "x": 5, + "y": 19, + "average_household_income_change": -546.6949474395025, + "relative_household_income_change": 0.3385683294268179, + "population": 76236.94173217926 + }, + { + "constituency_code": "E14000000596", + "constituency_name": "Constituency 596", + "x": null, + "y": null, + "average_household_income_change": 1652.2575803141276, + "relative_household_income_change": -0.0, + "population": 89450.32745730813 + }, + { + "constituency_code": "E14000000597", + "constituency_name": "Constituency 597", + "x": 7, + "y": 19, + "average_household_income_change": -1775.7536371573299, + "relative_household_income_change": 0.0, + "population": 117045.28244465016 + }, + { + "constituency_code": "E14000000598", + "constituency_name": "Constituency 598", + "x": 8, + "y": 19, + "average_household_income_change": 766.7318410506416, + "relative_household_income_change": 0.0, + "population": 88213.62626352572 + }, + { + "constituency_code": "E14000000599", + "constituency_name": "Constituency 599", + "x": 9, + "y": 19, + "average_household_income_change": 1530.454228643761, + "relative_household_income_change": -0.0, + "population": 138297.81002117688 + }, + { + "constituency_code": "E14000000600", + "constituency_name": "Constituency 600", + "x": 10, + "y": 19, + "average_household_income_change": 1765.2977730020027, + "relative_household_income_change": 0.0, + "population": 139824.0752634297 + }, + { + "constituency_code": "E14000000601", + "constituency_name": "Constituency 601", + "x": 11, + "y": 19, + "average_household_income_change": 1223.2611077151216, + "relative_household_income_change": 1e-12, + "population": 113591.50698099248 + }, + { + "constituency_code": "E14000000602", + "constituency_name": "Constituency 602", + "x": 12, + "y": 19, + "average_household_income_change": 382.6683234379353, + "relative_household_income_change": 0.0, + "population": 141310.5086029322 + }, + { + "constituency_code": "E14000000603", + "constituency_name": "Constituency 603", + "x": null, + "y": null, + "average_household_income_change": 856.1768560114076, + "relative_household_income_change": 0.7630627694108344, + "population": 111736.58376417658 + }, + { + "constituency_code": "E14000000604", + "constituency_name": "Constituency 604", + "x": 14, + "y": 19, + "average_household_income_change": -383.73355517201844, + "relative_household_income_change": 0.0, + "population": 74431.454997639 + }, + { + "constituency_code": "E14000000605", + "constituency_name": "Constituency 605", + "x": 15, + "y": 19, + "average_household_income_change": 1189.128223761453, + "relative_household_income_change": 0.0, + "population": 96831.1726712148 + }, + { + "constituency_code": "E14000000606", + "constituency_name": "Constituency 606", + "x": 16, + "y": 19, + "average_household_income_change": 1918.0756490163558, + "relative_household_income_change": -0.0, + "population": 141947.63285895935 + }, + { + "constituency_code": "E14000000607", + "constituency_name": "Constituency 607", + "x": 17, + "y": 19, + "average_household_income_change": -357.7091821516629, + "relative_household_income_change": 0.0, + "population": 104614.10256123879 + }, + { + "constituency_code": "E14000000608", + "constituency_name": "Constituency 608", + "x": 18, + "y": 19, + "average_household_income_change": 628.4179318357687, + "relative_household_income_change": 1e-12, + "population": 103755.05655807689 + }, + { + "constituency_code": "E14000000609", + "constituency_name": "Constituency 609", + "x": 19, + "y": 19, + "average_household_income_change": -1248.9217949583033, + "relative_household_income_change": -0.0, + "population": 147521.3750362315 + }, + { + "constituency_code": "E14000000610", + "constituency_name": "Constituency 610", + "x": null, + "y": null, + "average_household_income_change": -1583.7983552457956, + "relative_household_income_change": 0.0, + "population": 51688.1449805309 + }, + { + "constituency_code": "E14000000611", + "constituency_name": "Constituency 611", + "x": 21, + "y": 19, + "average_household_income_change": 1327.7323629112625, + "relative_household_income_change": -0.0, + "population": 103884.21189524661 + }, + { + "constituency_code": "E14000000612", + "constituency_name": "Constituency 612", + "x": 22, + "y": 19, + "average_household_income_change": 1973.251067041317, + "relative_household_income_change": 1e-12, + "population": 83744.23359295663 + }, + { + "constituency_code": "E14000000613", + "constituency_name": "Constituency 613", + "x": 23, + "y": 19, + "average_household_income_change": 83.21324225082982, + "relative_household_income_change": -0.0, + "population": 68368.57302030973 + }, + { + "constituency_code": "E14000000614", + "constituency_name": "Constituency 614", + "x": 24, + "y": 19, + "average_household_income_change": -395.21045059080564, + "relative_household_income_change": 0.0, + "population": 80043.8086664578 + }, + { + "constituency_code": "E14000000615", + "constituency_name": "Constituency 615", + "x": 25, + "y": 19, + "average_household_income_change": 1307.3369463042873, + "relative_household_income_change": -0.0, + "population": 105144.40885855842 + }, + { + "constituency_code": "E14000000616", + "constituency_name": "Constituency 616", + "x": 26, + "y": 19, + "average_household_income_change": -1282.621906237099, + "relative_household_income_change": 0.4248049166319652, + "population": 128939.8907021561 + }, + { + "constituency_code": "E14000000617", + "constituency_name": "Constituency 617", + "x": null, + "y": null, + "average_household_income_change": 953.4736754873703, + "relative_household_income_change": 0.0, + "population": 103767.56011373061 + }, + { + "constituency_code": "E14000000618", + "constituency_name": "Constituency 618", + "x": 28, + "y": 19, + "average_household_income_change": -929.6915636162972, + "relative_household_income_change": 0.6774768027545954, + "population": 149677.9304957911 + }, + { + "constituency_code": "E14000000619", + "constituency_name": "Constituency 619", + "x": 29, + "y": 19, + "average_household_income_change": 771.5763025685698, + "relative_household_income_change": 0.0, + "population": 77227.88788830965 + }, + { + "constituency_code": "E14000000620", + "constituency_name": "Constituency 620", + "x": 30, + "y": 19, + "average_household_income_change": -766.5509814539178, + "relative_household_income_change": -3.5e-9, + "population": 82122.3677446993 + }, + { + "constituency_code": "E14000000621", + "constituency_name": "Constituency 621", + "x": 0, + "y": 20, + "average_household_income_change": -752.9484879757442, + "relative_household_income_change": -3.5e-9, + "population": 76081.76656371151 + }, + { + "constituency_code": "E14000000622", + "constituency_name": "Constituency 622", + "x": 1, + "y": 20, + "average_household_income_change": 1222.9442365982281, + "relative_household_income_change": 0.0, + "population": 120679.12954257091 + }, + { + "constituency_code": "E14000000623", + "constituency_name": "Constituency 623", + "x": 2, + "y": 20, + "average_household_income_change": -1432.8521114865923, + "relative_household_income_change": 0.9195260235316269, + "population": 119371.17541933047 + }, + { + "constituency_code": "E14000000624", + "constituency_name": "Constituency 624", + "x": null, + "y": null, + "average_household_income_change": 534.9241254942352, + "relative_household_income_change": 0.3338237028975374, + "population": 60955.649829977745 + }, + { + "constituency_code": "E14000000625", + "constituency_name": "Constituency 625", + "x": 4, + "y": 20, + "average_household_income_change": 1843.912890268073, + "relative_household_income_change": 1e-12, + "population": 129358.11465348065 + }, + { + "constituency_code": "E14000000626", + "constituency_name": "Constituency 626", + "x": 5, + "y": 20, + "average_household_income_change": 371.6653569909436, + "relative_household_income_change": 0.18625157984189045, + "population": 55491.321063149466 + }, + { + "constituency_code": "E14000000627", + "constituency_name": "Constituency 627", + "x": 6, + "y": 20, + "average_household_income_change": -327.3032084220029, + "relative_household_income_change": 1e-12, + "population": 105868.16394036285 + }, + { + "constituency_code": "E14000000628", + "constituency_name": "Constituency 628", + "x": 7, + "y": 20, + "average_household_income_change": -1493.6082836546789, + "relative_household_income_change": 1e-12, + "population": 92021.95979984169 + }, + { + "constituency_code": "E14000000629", + "constituency_name": "Constituency 629", + "x": 8, + "y": 20, + "average_household_income_change": -1699.9458449766842, + "relative_household_income_change": -0.0, + "population": 122067.3726304384 + }, + { + "constituency_code": "E14000000630", + "constituency_name": "Constituency 630", + "x": 9, + "y": 20, + "average_household_income_change": -450.5896596519281, + "relative_household_income_change": 1e-12, + "population": 52936.33348045289 + }, + { + "constituency_code": "E14000000631", + "constituency_name": "Constituency 631", + "x": null, + "y": null, + "average_household_income_change": -1377.8764440953496, + "relative_household_income_change": 1e-12, + "population": 123121.2733392203 + }, + { + "constituency_code": "E14000000632", + "constituency_name": "Constituency 632", + "x": 11, + "y": 20, + "average_household_income_change": -1051.2636353189384, + "relative_household_income_change": 0.0, + "population": 96399.63093497188 + }, + { + "constituency_code": "E14000000633", + "constituency_name": "Constituency 633", + "x": 12, + "y": 20, + "average_household_income_change": 14.147980833502327, + "relative_household_income_change": -0.0, + "population": 90394.5248879687 + }, + { + "constituency_code": "E14000000634", + "constituency_name": "Constituency 634", + "x": 13, + "y": 20, + "average_household_income_change": -1838.0730523928687, + "relative_household_income_change": 0.8712942895857928, + "population": 60641.30386365898 + }, + { + "constituency_code": "E14000000635", + "constituency_name": "Constituency 635", + "x": 14, + "y": 20, + "average_household_income_change": -87.23716684922378, + "relative_household_income_change": 0.0, + "population": 104747.24642102896 + }, + { + "constituency_code": "E14000000636", + "constituency_name": "Constituency 636", + "x": 15, + "y": 20, + "average_household_income_change": 1939.336244729525, + "relative_household_income_change": 0.0, + "population": 127050.64843988064 + }, + { + "constituency_code": "E14000000637", + "constituency_name": "Constituency 637", + "x": 16, + "y": 20, + "average_household_income_change": 868.1707597779589, + "relative_household_income_change": 0.987503057055717, + "population": 129088.10024620766 + }, + { + "constituency_code": "E14000000638", + "constituency_name": "Constituency 638", + "x": null, + "y": null, + "average_household_income_change": -1786.8649278672845, + "relative_household_income_change": -0.0, + "population": 123939.15459225708 + }, + { + "constituency_code": "E14000000639", + "constituency_name": "Constituency 639", + "x": 18, + "y": 20, + "average_household_income_change": -189.309168849606, + "relative_household_income_change": -0.0, + "population": 120874.07398615906 + }, + { + "constituency_code": "E14000000640", + "constituency_name": "Constituency 640", + "x": 19, + "y": 20, + "average_household_income_change": 1594.94324793443, + "relative_household_income_change": -0.0, + "population": 74818.70120486079 + }, + { + "constituency_code": "E14000000641", + "constituency_name": "Constituency 641", + "x": 20, + "y": 20, + "average_household_income_change": 396.5805294054912, + "relative_household_income_change": -3.5e-9, + "population": 107085.6435479035 + }, + { + "constituency_code": "E14000000642", + "constituency_name": "Constituency 642", + "x": 21, + "y": 20, + "average_household_income_change": -1988.8676478597636, + "relative_household_income_change": 0.7466795414572786, + "population": 68794.36517222921 + }, + { + "constituency_code": "E14000000643", + "constituency_name": "Constituency 643", + "x": 22, + "y": 20, + "average_household_income_change": -1416.3933519071054, + "relative_household_income_change": 0.4848194651534483, + "population": 60473.494553043936 + }, + { + "constituency_code": "E14000000644", + "constituency_name": "Constituency 644", + "x": 23, + "y": 20, + "average_household_income_change": 1249.393074236446, + "relative_household_income_change": -3.5e-9, + "population": 123993.994089221 + }, + { + "constituency_code": "E14000000645", + "constituency_name": "Constituency 645", + "x": null, + "y": null, + "average_household_income_change": 1046.8309597875534, + "relative_household_income_change": -3.5e-9, + "population": 82589.20612888796 + }, + { + "constituency_code": "E14000000646", + "constituency_name": "Constituency 646", + "x": 25, + "y": 20, + "average_household_income_change": 1062.21099433036, + "relative_household_income_change": 1e-12, + "population": 123517.19941423072 + }, + { + "constituency_code": "E14000000647", + "constituency_name": "Constituency 647", + "x": 26, + "y": 20, + "average_household_income_change": -313.8369092416631, + "relative_household_income_change": -3.5e-9, + "population": 144734.81087895617 + }, + { + "constituency_code": "E14000000648", + "constituency_name": "Constituency 648", + "x": 27, + "y": 20, + "average_household_income_change": 1658.9417288888621, + "relative_household_income_change": 0.0, + "population": 54363.82273350112 + }, + { + "constituency_code": "E14000000649", + "constituency_name": "Constituency 649", + "x": 28, + "y": 20, + "average_household_income_change": 446.986217100954, + "relative_household_income_change": 1e-12, + "population": 129264.05146024606 + }, + { + "constituency_code": "E14000000650", + "constituency_name": "Constituency 650", + "x": 29, + "y": 20, + "average_household_income_change": 317.6664618952065, + "relative_household_income_change": -3.5e-9, + "population": 56840.72937490232 + } + ], + "local_authority_impact": [ + { + "local_authority_code": "E06000000001", + "local_authority_name": "Local Authority 1", + "x": null, + "y": null, + "average_household_income_change": 468.5659066798089, + "relative_household_income_change": -3.5e-9, + "population": 100206.37490705009 + }, + { + "local_authority_code": "E06000000002", + "local_authority_name": "Local Authority 2", + "x": 1, + "y": 0, + "average_household_income_change": -69.21670028623072, + "relative_household_income_change": 1e-12, + "population": 123384.01709097778 + }, + { + "local_authority_code": "E06000000003", + "local_authority_name": "Local Authority 3", + "x": 2, + "y": 0, + "average_household_income_change": 912.1297309164911, + "relative_household_income_change": 0.0, + "population": 141131.81544042542 + }, + { + "local_authority_code": "E06000000004", + "local_authority_name": "Local Authority 4", + "x": 3, + "y": 0, + "average_household_income_change": 1910.1807474188765, + "relative_household_income_change": -0.0, + "population": 76099.80320995662 + }, + { + "local_authority_code": "E06000000005", + "local_authority_name": "Local Authority 5", + "x": 4, + "y": 0, + "average_household_income_change": 969.7714464687679, + "relative_household_income_change": 1e-12, + "population": 72911.01548143946 + }, + { + "local_authority_code": "E06000000006", + "local_authority_name": "Local Authority 6", + "x": 5, + "y": 0, + "average_household_income_change": -1207.175754642046, + "relative_household_income_change": 1e-12, + "population": 100754.01422780073 + }, + { + "local_authority_code": "E06000000007", + "local_authority_name": "Local Authority 7", + "x": 6, + "y": 0, + "average_household_income_change": 588.1157473314702, + "relative_household_income_change": -3.5e-9, + "population": 148197.15018666055 + }, + { + "local_authority_code": "E06000000008", + "local_authority_name": "Local Authority 8", + "x": null, + "y": null, + "average_household_income_change": -1779.658218255996, + "relative_household_income_change": 0.0, + "population": 128556.48672377989 + }, + { + "local_authority_code": "E06000000009", + "local_authority_name": "Local Authority 9", + "x": 8, + "y": 0, + "average_household_income_change": 212.13946976047592, + "relative_household_income_change": -0.0, + "population": 115700.32594875956 + }, + { + "local_authority_code": "E06000000010", + "local_authority_name": "Local Authority 10", + "x": 9, + "y": 0, + "average_household_income_change": -1378.918327125695, + "relative_household_income_change": -3.5e-9, + "population": 73114.63274971377 + }, + { + "local_authority_code": "E06000000011", + "local_authority_name": "Local Authority 11", + "x": 10, + "y": 0, + "average_household_income_change": -623.1384398880615, + "relative_household_income_change": -0.0, + "population": 139342.8006351117 + }, + { + "local_authority_code": "E06000000012", + "local_authority_name": "Local Authority 12", + "x": 11, + "y": 0, + "average_household_income_change": -1682.4344088991313, + "relative_household_income_change": 0.0, + "population": 132067.73320383328 + }, + { + "local_authority_code": "E06000000013", + "local_authority_name": "Local Authority 13", + "x": 12, + "y": 0, + "average_household_income_change": -1793.1064434964794, + "relative_household_income_change": -3.5e-9, + "population": 104826.38130177911 + }, + { + "local_authority_code": "E06000000014", + "local_authority_name": "Local Authority 14", + "x": 13, + "y": 0, + "average_household_income_change": -972.1255530448434, + "relative_household_income_change": -3.5e-9, + "population": 64127.86306468177 + }, + { + "local_authority_code": "E06000000015", + "local_authority_name": "Local Authority 15", + "x": null, + "y": null, + "average_household_income_change": 1687.1904190190778, + "relative_household_income_change": 0.19915732727299662, + "population": 82930.81346214596 + }, + { + "local_authority_code": "E06000000016", + "local_authority_name": "Local Authority 16", + "x": 15, + "y": 0, + "average_household_income_change": -538.4535593560624, + "relative_household_income_change": -0.0, + "population": 102310.46935923983 + }, + { + "local_authority_code": "E06000000017", + "local_authority_name": "Local Authority 17", + "x": 16, + "y": 0, + "average_household_income_change": 1745.5093965364488, + "relative_household_income_change": -0.0, + "population": 110324.97681835851 + }, + { + "local_authority_code": "E06000000018", + "local_authority_name": "Local Authority 18", + "x": 17, + "y": 0, + "average_household_income_change": -1613.72155725294, + "relative_household_income_change": 0.0, + "population": 88984.89875920078 + }, + { + "local_authority_code": "E06000000019", + "local_authority_name": "Local Authority 19", + "x": 18, + "y": 0, + "average_household_income_change": -1690.1448876694994, + "relative_household_income_change": -3.5e-9, + "population": 72890.3783981163 + }, + { + "local_authority_code": "E06000000020", + "local_authority_name": "Local Authority 20", + "x": 19, + "y": 0, + "average_household_income_change": -157.98504358729159, + "relative_household_income_change": 1e-12, + "population": 73478.18403793292 + }, + { + "local_authority_code": "E06000000021", + "local_authority_name": "Local Authority 21", + "x": 20, + "y": 0, + "average_household_income_change": 1070.4210969196931, + "relative_household_income_change": -3.5e-9, + "population": 98666.90369402937 + }, + { + "local_authority_code": "E06000000022", + "local_authority_name": "Local Authority 22", + "x": null, + "y": null, + "average_household_income_change": -1084.190750741544, + "relative_household_income_change": 0.836601005622632, + "population": 83210.36408380332 + }, + { + "local_authority_code": "E06000000023", + "local_authority_name": "Local Authority 23", + "x": 22, + "y": 0, + "average_household_income_change": 1042.6216477340079, + "relative_household_income_change": -3.5e-9, + "population": 82189.76985415467 + }, + { + "local_authority_code": "E06000000024", + "local_authority_name": "Local Authority 24", + "x": 23, + "y": 0, + "average_household_income_change": -356.59948313574176, + "relative_household_income_change": 0.0, + "population": 74556.76041445452 + }, + { + "local_authority_code": "E06000000025", + "local_authority_name": "Local Authority 25", + "x": 24, + "y": 0, + "average_household_income_change": 255.29861692466403, + "relative_household_income_change": 0.7232325273104853, + "population": 127857.36052385914 + }, + { + "local_authority_code": "E06000000026", + "local_authority_name": "Local Authority 26", + "x": 25, + "y": 0, + "average_household_income_change": -561.9967800290389, + "relative_household_income_change": 1e-12, + "population": 106980.91731680604 + }, + { + "local_authority_code": "E06000000027", + "local_authority_name": "Local Authority 27", + "x": 26, + "y": 0, + "average_household_income_change": -109.1144097657053, + "relative_household_income_change": 1e-12, + "population": 109578.0521407703 + }, + { + "local_authority_code": "E06000000028", + "local_authority_name": "Local Authority 28", + "x": 27, + "y": 0, + "average_household_income_change": -1367.295021366755, + "relative_household_income_change": 1e-12, + "population": 58898.86324268766 + }, + { + "local_authority_code": "E06000000029", + "local_authority_name": "Local Authority 29", + "x": null, + "y": null, + "average_household_income_change": 570.918963320222, + "relative_household_income_change": 0.0, + "population": 125338.41108172822 + }, + { + "local_authority_code": "E06000000030", + "local_authority_name": "Local Authority 30", + "x": 29, + "y": 0, + "average_household_income_change": -274.2402568191693, + "relative_household_income_change": -3.5e-9, + "population": 64611.39147086428 + }, + { + "local_authority_code": "E06000000031", + "local_authority_name": "Local Authority 31", + "x": 30, + "y": 0, + "average_household_income_change": 723.445821990056, + "relative_household_income_change": -0.0, + "population": 110356.63768942235 + }, + { + "local_authority_code": "E06000000032", + "local_authority_name": "Local Authority 32", + "x": 0, + "y": 1, + "average_household_income_change": -528.8110657531159, + "relative_household_income_change": -3.5e-9, + "population": 105587.30047688412 + }, + { + "local_authority_code": "E06000000033", + "local_authority_name": "Local Authority 33", + "x": 1, + "y": 1, + "average_household_income_change": -1899.0443795165293, + "relative_household_income_change": 1e-12, + "population": 52173.26085032475 + }, + { + "local_authority_code": "E06000000034", + "local_authority_name": "Local Authority 34", + "x": 2, + "y": 1, + "average_household_income_change": -948.6511027706763, + "relative_household_income_change": 0.861974368839776, + "population": 108831.07934043322 + }, + { + "local_authority_code": "E06000000035", + "local_authority_name": "Local Authority 35", + "x": 3, + "y": 1, + "average_household_income_change": 596.6157268316401, + "relative_household_income_change": 0.0, + "population": 102116.27736033645 + }, + { + "local_authority_code": "E06000000036", + "local_authority_name": "Local Authority 36", + "x": null, + "y": null, + "average_household_income_change": 207.93735297858885, + "relative_household_income_change": 0.0, + "population": 116564.66422229337 + }, + { + "local_authority_code": "E06000000037", + "local_authority_name": "Local Authority 37", + "x": 5, + "y": 1, + "average_household_income_change": -99.3150549349906, + "relative_household_income_change": 1e-12, + "population": 101593.40434133449 + }, + { + "local_authority_code": "E06000000038", + "local_authority_name": "Local Authority 38", + "x": 6, + "y": 1, + "average_household_income_change": -386.4531583157946, + "relative_household_income_change": 0.0, + "population": 141472.1770422101 + }, + { + "local_authority_code": "E06000000039", + "local_authority_name": "Local Authority 39", + "x": 7, + "y": 1, + "average_household_income_change": 330.0627465742383, + "relative_household_income_change": 0.05215779997016934, + "population": 141852.21151584186 + }, + { + "local_authority_code": "E06000000040", + "local_authority_name": "Local Authority 40", + "x": 8, + "y": 1, + "average_household_income_change": -1133.1155149702777, + "relative_household_income_change": 0.0, + "population": 90600.31790542022 + }, + { + "local_authority_code": "E06000000041", + "local_authority_name": "Local Authority 41", + "x": 9, + "y": 1, + "average_household_income_change": -839.5358563959885, + "relative_household_income_change": 0.13584478762195062, + "population": 88141.137590001 + }, + { + "local_authority_code": "E06000000042", + "local_authority_name": "Local Authority 42", + "x": 10, + "y": 1, + "average_household_income_change": -1165.481582988086, + "relative_household_income_change": -3.5e-9, + "population": 73433.4816768881 + }, + { + "local_authority_code": "E06000000043", + "local_authority_name": "Local Authority 43", + "x": null, + "y": null, + "average_household_income_change": -373.5052701686232, + "relative_household_income_change": -3.5e-9, + "population": 79419.4013814455 + }, + { + "local_authority_code": "E06000000044", + "local_authority_name": "Local Authority 44", + "x": 12, + "y": 1, + "average_household_income_change": -1160.1562975452566, + "relative_household_income_change": -3.5e-9, + "population": 85899.06902370857 + }, + { + "local_authority_code": "E06000000045", + "local_authority_name": "Local Authority 45", + "x": 13, + "y": 1, + "average_household_income_change": 758.790098109745, + "relative_household_income_change": -3.5e-9, + "population": 63063.28444224117 + }, + { + "local_authority_code": "E06000000046", + "local_authority_name": "Local Authority 46", + "x": 14, + "y": 1, + "average_household_income_change": -1029.720675973574, + "relative_household_income_change": -0.0, + "population": 104506.66479956872 + }, + { + "local_authority_code": "E06000000047", + "local_authority_name": "Local Authority 47", + "x": 15, + "y": 1, + "average_household_income_change": -516.1419060292656, + "relative_household_income_change": -3.5e-9, + "population": 72118.73988243361 + }, + { + "local_authority_code": "E06000000048", + "local_authority_name": "Local Authority 48", + "x": 16, + "y": 1, + "average_household_income_change": -1305.9071114052686, + "relative_household_income_change": 0.0, + "population": 83866.0479801991 + }, + { + "local_authority_code": "E06000000049", + "local_authority_name": "Local Authority 49", + "x": 17, + "y": 1, + "average_household_income_change": 336.04631080583937, + "relative_household_income_change": -3.5e-9, + "population": 143454.1556254162 + }, + { + "local_authority_code": "E06000000050", + "local_authority_name": "Local Authority 50", + "x": null, + "y": null, + "average_household_income_change": -1720.7042384504155, + "relative_household_income_change": 0.0, + "population": 60713.73636327979 + }, + { + "local_authority_code": "E06000000051", + "local_authority_name": "Local Authority 51", + "x": 19, + "y": 1, + "average_household_income_change": 1434.7514320345974, + "relative_household_income_change": -3.5e-9, + "population": 81076.07543203316 + }, + { + "local_authority_code": "E06000000052", + "local_authority_name": "Local Authority 52", + "x": 20, + "y": 1, + "average_household_income_change": 367.94847637922425, + "relative_household_income_change": 0.0, + "population": 57169.51240739431 + }, + { + "local_authority_code": "E06000000053", + "local_authority_name": "Local Authority 53", + "x": 21, + "y": 1, + "average_household_income_change": -134.27102983545325, + "relative_household_income_change": -3.5e-9, + "population": 112260.18240877741 + }, + { + "local_authority_code": "E06000000054", + "local_authority_name": "Local Authority 54", + "x": 22, + "y": 1, + "average_household_income_change": -1307.3113454330883, + "relative_household_income_change": 1e-12, + "population": 129712.91555041495 + }, + { + "local_authority_code": "E06000000055", + "local_authority_name": "Local Authority 55", + "x": 23, + "y": 1, + "average_household_income_change": 1698.0689767657648, + "relative_household_income_change": 0.0, + "population": 56651.85897650984 + }, + { + "local_authority_code": "E06000000056", + "local_authority_name": "Local Authority 56", + "x": 24, + "y": 1, + "average_household_income_change": -684.5442861532538, + "relative_household_income_change": 0.0, + "population": 51961.63664619178 + }, + { + "local_authority_code": "E06000000057", + "local_authority_name": "Local Authority 57", + "x": null, + "y": null, + "average_household_income_change": -978.7187202471532, + "relative_household_income_change": -3.5e-9, + "population": 97885.13067633384 + }, + { + "local_authority_code": "E06000000058", + "local_authority_name": "Local Authority 58", + "x": 26, + "y": 1, + "average_household_income_change": 1770.8198408401636, + "relative_household_income_change": 0.4022130639378835, + "population": 116710.80210949371 + }, + { + "local_authority_code": "E06000000059", + "local_authority_name": "Local Authority 59", + "x": 27, + "y": 1, + "average_household_income_change": -227.21024178206807, + "relative_household_income_change": 0.0, + "population": 148868.47538700586 + }, + { + "local_authority_code": "E06000000060", + "local_authority_name": "Local Authority 60", + "x": 28, + "y": 1, + "average_household_income_change": 406.1970125350696, + "relative_household_income_change": -0.0, + "population": 69260.03618381429 + }, + { + "local_authority_code": "E06000000061", + "local_authority_name": "Local Authority 61", + "x": 29, + "y": 1, + "average_household_income_change": -74.91285483834443, + "relative_household_income_change": 1e-12, + "population": 142780.21598839073 + }, + { + "local_authority_code": "E06000000062", + "local_authority_name": "Local Authority 62", + "x": 30, + "y": 1, + "average_household_income_change": -1339.6500922702558, + "relative_household_income_change": -0.0, + "population": 99488.94447212561 + }, + { + "local_authority_code": "E06000000063", + "local_authority_name": "Local Authority 63", + "x": 0, + "y": 2, + "average_household_income_change": -1298.0181141563762, + "relative_household_income_change": -3.5e-9, + "population": 55030.787258256365 + }, + { + "local_authority_code": "E06000000064", + "local_authority_name": "Local Authority 64", + "x": null, + "y": null, + "average_household_income_change": -54.75236674179662, + "relative_household_income_change": -0.0, + "population": 138632.11137234024 + }, + { + "local_authority_code": "E06000000065", + "local_authority_name": "Local Authority 65", + "x": 2, + "y": 2, + "average_household_income_change": -1845.58137993721, + "relative_household_income_change": -3.5e-9, + "population": 60267.99379230523 + }, + { + "local_authority_code": "E06000000066", + "local_authority_name": "Local Authority 66", + "x": 3, + "y": 2, + "average_household_income_change": -524.38253465656, + "relative_household_income_change": -0.0, + "population": 102857.31969449116 + }, + { + "local_authority_code": "E06000000067", + "local_authority_name": "Local Authority 67", + "x": 4, + "y": 2, + "average_household_income_change": 1417.0468691939302, + "relative_household_income_change": 1e-12, + "population": 60692.56747606022 + }, + { + "local_authority_code": "E06000000068", + "local_authority_name": "Local Authority 68", + "x": 5, + "y": 2, + "average_household_income_change": -669.6944521175205, + "relative_household_income_change": 1e-12, + "population": 62205.01230755512 + }, + { + "local_authority_code": "E06000000069", + "local_authority_name": "Local Authority 69", + "x": 6, + "y": 2, + "average_household_income_change": -697.2904833598284, + "relative_household_income_change": 0.32579234099818233, + "population": 50703.25977836838 + }, + { + "local_authority_code": "E06000000070", + "local_authority_name": "Local Authority 70", + "x": 7, + "y": 2, + "average_household_income_change": 1648.9893529969822, + "relative_household_income_change": 1e-12, + "population": 111110.29655746072 + }, + { + "local_authority_code": "E06000000071", + "local_authority_name": "Local Authority 71", + "x": null, + "y": null, + "average_household_income_change": 1655.3433374587626, + "relative_household_income_change": 1e-12, + "population": 107139.20307198947 + }, + { + "local_authority_code": "E06000000072", + "local_authority_name": "Local Authority 72", + "x": 9, + "y": 2, + "average_household_income_change": 1155.7966124245381, + "relative_household_income_change": -3.5e-9, + "population": 77257.50624124409 + }, + { + "local_authority_code": "E06000000073", + "local_authority_name": "Local Authority 73", + "x": 10, + "y": 2, + "average_household_income_change": -739.4421680729821, + "relative_household_income_change": 1e-12, + "population": 147255.8211176183 + }, + { + "local_authority_code": "E06000000074", + "local_authority_name": "Local Authority 74", + "x": 11, + "y": 2, + "average_household_income_change": -1876.352256872487, + "relative_household_income_change": -0.0, + "population": 112467.48919408373 + }, + { + "local_authority_code": "E06000000075", + "local_authority_name": "Local Authority 75", + "x": 12, + "y": 2, + "average_household_income_change": -637.7726449765091, + "relative_household_income_change": -0.0, + "population": 143837.46577293432 + }, + { + "local_authority_code": "E06000000076", + "local_authority_name": "Local Authority 76", + "x": 13, + "y": 2, + "average_household_income_change": 42.97080220967642, + "relative_household_income_change": -0.0, + "population": 136007.1936987238 + }, + { + "local_authority_code": "E06000000077", + "local_authority_name": "Local Authority 77", + "x": 14, + "y": 2, + "average_household_income_change": 246.10490045053135, + "relative_household_income_change": -3.5e-9, + "population": 112922.3491300438 + }, + { + "local_authority_code": "E06000000078", + "local_authority_name": "Local Authority 78", + "x": null, + "y": null, + "average_household_income_change": 1391.1407839376343, + "relative_household_income_change": -0.0, + "population": 97785.16806463109 + }, + { + "local_authority_code": "E06000000079", + "local_authority_name": "Local Authority 79", + "x": 16, + "y": 2, + "average_household_income_change": -1577.6611573462892, + "relative_household_income_change": 0.8397807712331508, + "population": 61633.32002388823 + }, + { + "local_authority_code": "E06000000080", + "local_authority_name": "Local Authority 80", + "x": 17, + "y": 2, + "average_household_income_change": 1621.9689662911376, + "relative_household_income_change": 0.44786982566411027, + "population": 141121.86104609378 + }, + { + "local_authority_code": "E06000000081", + "local_authority_name": "Local Authority 81", + "x": 18, + "y": 2, + "average_household_income_change": 1843.023545552603, + "relative_household_income_change": 1e-12, + "population": 100289.83457812988 + }, + { + "local_authority_code": "E06000000082", + "local_authority_name": "Local Authority 82", + "x": 19, + "y": 2, + "average_household_income_change": -1574.802477133047, + "relative_household_income_change": -0.0, + "population": 107128.20337032386 + }, + { + "local_authority_code": "E06000000083", + "local_authority_name": "Local Authority 83", + "x": 20, + "y": 2, + "average_household_income_change": 1700.2682547782751, + "relative_household_income_change": 0.8286985245589028, + "population": 130406.17866850618 + }, + { + "local_authority_code": "E06000000084", + "local_authority_name": "Local Authority 84", + "x": 21, + "y": 2, + "average_household_income_change": -109.59877514069305, + "relative_household_income_change": 1e-12, + "population": 143330.49244997563 + }, + { + "local_authority_code": "E06000000085", + "local_authority_name": "Local Authority 85", + "x": null, + "y": null, + "average_household_income_change": 634.4029721965949, + "relative_household_income_change": -3.5e-9, + "population": 84288.84699659675 + }, + { + "local_authority_code": "E06000000086", + "local_authority_name": "Local Authority 86", + "x": 23, + "y": 2, + "average_household_income_change": 298.3073319458458, + "relative_household_income_change": -0.0, + "population": 112072.35527186739 + }, + { + "local_authority_code": "E06000000087", + "local_authority_name": "Local Authority 87", + "x": 24, + "y": 2, + "average_household_income_change": 1162.613580175742, + "relative_household_income_change": 0.8735826901840349, + "population": 53334.41826254266 + }, + { + "local_authority_code": "E06000000088", + "local_authority_name": "Local Authority 88", + "x": 25, + "y": 2, + "average_household_income_change": 1269.5038134454041, + "relative_household_income_change": -0.0, + "population": 146967.75846424367 + }, + { + "local_authority_code": "E06000000089", + "local_authority_name": "Local Authority 89", + "x": 26, + "y": 2, + "average_household_income_change": 941.4584916929489, + "relative_household_income_change": 0.0, + "population": 99442.99104208047 + }, + { + "local_authority_code": "E06000000090", + "local_authority_name": "Local Authority 90", + "x": 27, + "y": 2, + "average_household_income_change": -124.6417436565066, + "relative_household_income_change": 0.0, + "population": 80384.06129506999 + }, + { + "local_authority_code": "E06000000091", + "local_authority_name": "Local Authority 91", + "x": 28, + "y": 2, + "average_household_income_change": -131.22312675529324, + "relative_household_income_change": 0.0, + "population": 95193.73712188863 + }, + { + "local_authority_code": "E06000000092", + "local_authority_name": "Local Authority 92", + "x": null, + "y": null, + "average_household_income_change": 1625.5843992648, + "relative_household_income_change": -0.0, + "population": 141357.51829077472 + }, + { + "local_authority_code": "E06000000093", + "local_authority_name": "Local Authority 93", + "x": 30, + "y": 2, + "average_household_income_change": 424.8513763312842, + "relative_household_income_change": -3.5e-9, + "population": 119300.97621805023 + }, + { + "local_authority_code": "E06000000094", + "local_authority_name": "Local Authority 94", + "x": 0, + "y": 3, + "average_household_income_change": 1268.131101085673, + "relative_household_income_change": -0.0, + "population": 149013.66364449463 + }, + { + "local_authority_code": "E06000000095", + "local_authority_name": "Local Authority 95", + "x": 1, + "y": 3, + "average_household_income_change": -1530.9993636045124, + "relative_household_income_change": 0.0, + "population": 116664.05867270652 + }, + { + "local_authority_code": "E06000000096", + "local_authority_name": "Local Authority 96", + "x": 2, + "y": 3, + "average_household_income_change": -1949.1910457980314, + "relative_household_income_change": 0.0, + "population": 112806.71261334998 + }, + { + "local_authority_code": "E06000000097", + "local_authority_name": "Local Authority 97", + "x": 3, + "y": 3, + "average_household_income_change": 540.3517666893554, + "relative_household_income_change": -0.0, + "population": 59479.33774122507 + }, + { + "local_authority_code": "E06000000098", + "local_authority_name": "Local Authority 98", + "x": 4, + "y": 3, + "average_household_income_change": 91.25874221760988, + "relative_household_income_change": 0.0, + "population": 66358.81394243162 + }, + { + "local_authority_code": "E06000000099", + "local_authority_name": "Local Authority 99", + "x": null, + "y": null, + "average_household_income_change": 259.0652403777276, + "relative_household_income_change": 0.2340381841126019, + "population": 75494.00711254979 + }, + { + "local_authority_code": "E06000000100", + "local_authority_name": "Local Authority 100", + "x": 6, + "y": 3, + "average_household_income_change": -1245.9852723180682, + "relative_household_income_change": -0.0, + "population": 92066.49441666392 + }, + { + "local_authority_code": "E06000000101", + "local_authority_name": "Local Authority 101", + "x": 7, + "y": 3, + "average_household_income_change": -1579.4667973681244, + "relative_household_income_change": -3.5e-9, + "population": 100521.50805462364 + }, + { + "local_authority_code": "E06000000102", + "local_authority_name": "Local Authority 102", + "x": 8, + "y": 3, + "average_household_income_change": -384.01290422337195, + "relative_household_income_change": 1e-12, + "population": 114009.55195049211 + }, + { + "local_authority_code": "E06000000103", + "local_authority_name": "Local Authority 103", + "x": 9, + "y": 3, + "average_household_income_change": 126.69515084896732, + "relative_household_income_change": 1e-12, + "population": 127439.82030562818 + }, + { + "local_authority_code": "E06000000104", + "local_authority_name": "Local Authority 104", + "x": 10, + "y": 3, + "average_household_income_change": -1301.7351067368743, + "relative_household_income_change": -0.0, + "population": 53563.63516660295 + }, + { + "local_authority_code": "E06000000105", + "local_authority_name": "Local Authority 105", + "x": 11, + "y": 3, + "average_household_income_change": -1718.9549225276987, + "relative_household_income_change": 0.0, + "population": 82068.41317409082 + }, + { + "local_authority_code": "E06000000106", + "local_authority_name": "Local Authority 106", + "x": null, + "y": null, + "average_household_income_change": -1730.7507441245823, + "relative_household_income_change": 1e-12, + "population": 119226.4080348876 + }, + { + "local_authority_code": "E06000000107", + "local_authority_name": "Local Authority 107", + "x": 13, + "y": 3, + "average_household_income_change": 234.4235660991254, + "relative_household_income_change": 1e-12, + "population": 140046.32145941973 + }, + { + "local_authority_code": "E06000000108", + "local_authority_name": "Local Authority 108", + "x": 14, + "y": 3, + "average_household_income_change": 575.5706432427354, + "relative_household_income_change": 0.3550402964498325, + "population": 106380.05723099297 + }, + { + "local_authority_code": "E06000000109", + "local_authority_name": "Local Authority 109", + "x": 15, + "y": 3, + "average_household_income_change": -892.4872885317292, + "relative_household_income_change": -3.5e-9, + "population": 53076.74660716412 + }, + { + "local_authority_code": "E06000000110", + "local_authority_name": "Local Authority 110", + "x": 16, + "y": 3, + "average_household_income_change": -939.2971206471809, + "relative_household_income_change": -3.5e-9, + "population": 104433.28349564088 + }, + { + "local_authority_code": "E06000000111", + "local_authority_name": "Local Authority 111", + "x": 17, + "y": 3, + "average_household_income_change": 369.1730214135318, + "relative_household_income_change": 1e-12, + "population": 111068.85198051632 + }, + { + "local_authority_code": "E06000000112", + "local_authority_name": "Local Authority 112", + "x": 18, + "y": 3, + "average_household_income_change": -1980.1767990273622, + "relative_household_income_change": -3.5e-9, + "population": 149422.4455146322 + }, + { + "local_authority_code": "E06000000113", + "local_authority_name": "Local Authority 113", + "x": null, + "y": null, + "average_household_income_change": -1685.3969016955593, + "relative_household_income_change": 0.6177421413249037, + "population": 73272.14262762116 + }, + { + "local_authority_code": "E06000000114", + "local_authority_name": "Local Authority 114", + "x": 20, + "y": 3, + "average_household_income_change": 857.8109681964099, + "relative_household_income_change": 0.356428163358969, + "population": 51232.78052923555 + }, + { + "local_authority_code": "E06000000115", + "local_authority_name": "Local Authority 115", + "x": 21, + "y": 3, + "average_household_income_change": 1950.5758188370517, + "relative_household_income_change": 1e-12, + "population": 76115.71228923349 + }, + { + "local_authority_code": "E06000000116", + "local_authority_name": "Local Authority 116", + "x": 22, + "y": 3, + "average_household_income_change": -1160.224065252241, + "relative_household_income_change": -0.0, + "population": 89923.61812913681 + }, + { + "local_authority_code": "E06000000117", + "local_authority_name": "Local Authority 117", + "x": 23, + "y": 3, + "average_household_income_change": -1003.0071129789468, + "relative_household_income_change": -0.0, + "population": 55023.62428393849 + }, + { + "local_authority_code": "E06000000118", + "local_authority_name": "Local Authority 118", + "x": 24, + "y": 3, + "average_household_income_change": -665.3379484000661, + "relative_household_income_change": -3.5e-9, + "population": 95601.70751376684 + }, + { + "local_authority_code": "E06000000119", + "local_authority_name": "Local Authority 119", + "x": 25, + "y": 3, + "average_household_income_change": -1166.075660949811, + "relative_household_income_change": -0.0, + "population": 103266.09447574029 + }, + { + "local_authority_code": "E06000000120", + "local_authority_name": "Local Authority 120", + "x": null, + "y": null, + "average_household_income_change": 1860.735460695461, + "relative_household_income_change": -0.0, + "population": 131775.97595322173 + }, + { + "local_authority_code": "E06000000121", + "local_authority_name": "Local Authority 121", + "x": 27, + "y": 3, + "average_household_income_change": 1580.0608324809184, + "relative_household_income_change": 0.0, + "population": 78812.01228506769 + }, + { + "local_authority_code": "E06000000122", + "local_authority_name": "Local Authority 122", + "x": 28, + "y": 3, + "average_household_income_change": 1785.1647270269898, + "relative_household_income_change": 0.05415064813031445, + "population": 113159.23111465383 + }, + { + "local_authority_code": "E06000000123", + "local_authority_name": "Local Authority 123", + "x": 29, + "y": 3, + "average_household_income_change": 1534.2332923215959, + "relative_household_income_change": 0.0, + "population": 141819.93936978036 + }, + { + "local_authority_code": "E06000000124", + "local_authority_name": "Local Authority 124", + "x": 30, + "y": 3, + "average_household_income_change": 1572.181832031823, + "relative_household_income_change": 1e-12, + "population": 86350.96665343967 + }, + { + "local_authority_code": "E06000000125", + "local_authority_name": "Local Authority 125", + "x": 0, + "y": 4, + "average_household_income_change": -1605.8392299157967, + "relative_household_income_change": 0.6240767613094547, + "population": 144735.63572544855 + }, + { + "local_authority_code": "E06000000126", + "local_authority_name": "Local Authority 126", + "x": 1, + "y": 4, + "average_household_income_change": 200.19623482877958, + "relative_household_income_change": -3.5e-9, + "population": 51753.161581743465 + }, + { + "local_authority_code": "E06000000127", + "local_authority_name": "Local Authority 127", + "x": null, + "y": null, + "average_household_income_change": 1195.8534047937524, + "relative_household_income_change": 0.5409499896423211, + "population": 129532.97590453389 + }, + { + "local_authority_code": "E06000000128", + "local_authority_name": "Local Authority 128", + "x": 3, + "y": 4, + "average_household_income_change": -1637.0444378301024, + "relative_household_income_change": -0.0, + "population": 53457.8999979193 + }, + { + "local_authority_code": "E06000000129", + "local_authority_name": "Local Authority 129", + "x": 4, + "y": 4, + "average_household_income_change": 885.2623772470519, + "relative_household_income_change": -3.5e-9, + "population": 123118.85395640823 + }, + { + "local_authority_code": "E06000000130", + "local_authority_name": "Local Authority 130", + "x": 5, + "y": 4, + "average_household_income_change": 1013.1201826824805, + "relative_household_income_change": -3.5e-9, + "population": 144611.15210387774 + }, + { + "local_authority_code": "E06000000131", + "local_authority_name": "Local Authority 131", + "x": 6, + "y": 4, + "average_household_income_change": 927.1284242260824, + "relative_household_income_change": -0.0, + "population": 113506.86780643024 + }, + { + "local_authority_code": "E06000000132", + "local_authority_name": "Local Authority 132", + "x": 7, + "y": 4, + "average_household_income_change": 993.180340538264, + "relative_household_income_change": -3.5e-9, + "population": 147590.3661673587 + }, + { + "local_authority_code": "E06000000133", + "local_authority_name": "Local Authority 133", + "x": 8, + "y": 4, + "average_household_income_change": -1761.3207876794465, + "relative_household_income_change": 0.8210333940864938, + "population": 64270.32513059139 + }, + { + "local_authority_code": "E06000000134", + "local_authority_name": "Local Authority 134", + "x": null, + "y": null, + "average_household_income_change": -1677.9391875677602, + "relative_household_income_change": 1e-12, + "population": 102291.43195281904 + }, + { + "local_authority_code": "E06000000135", + "local_authority_name": "Local Authority 135", + "x": 10, + "y": 4, + "average_household_income_change": -528.5457385095484, + "relative_household_income_change": 0.23264565175973118, + "population": 78181.4017919634 + }, + { + "local_authority_code": "E06000000136", + "local_authority_name": "Local Authority 136", + "x": 11, + "y": 4, + "average_household_income_change": -1809.900053696826, + "relative_household_income_change": 0.954552658406543, + "population": 103838.26790233378 + }, + { + "local_authority_code": "E06000000137", + "local_authority_name": "Local Authority 137", + "x": 12, + "y": 4, + "average_household_income_change": 175.59819725277003, + "relative_household_income_change": 1e-12, + "population": 114961.59077385967 + }, + { + "local_authority_code": "E06000000138", + "local_authority_name": "Local Authority 138", + "x": 13, + "y": 4, + "average_household_income_change": -1694.1470757332215, + "relative_household_income_change": 0.07908142310991939, + "population": 66771.1061948385 + }, + { + "local_authority_code": "E06000000139", + "local_authority_name": "Local Authority 139", + "x": 14, + "y": 4, + "average_household_income_change": 1812.1023900051255, + "relative_household_income_change": -3.5e-9, + "population": 107198.30332877951 + }, + { + "local_authority_code": "E06000000140", + "local_authority_name": "Local Authority 140", + "x": 15, + "y": 4, + "average_household_income_change": -1538.359829800179, + "relative_household_income_change": 0.03787036997739923, + "population": 116807.61139000079 + }, + { + "local_authority_code": "E06000000141", + "local_authority_name": "Local Authority 141", + "x": null, + "y": null, + "average_household_income_change": 1289.5074707439016, + "relative_household_income_change": 0.3477828575349734, + "population": 55879.49043451492 + }, + { + "local_authority_code": "E06000000142", + "local_authority_name": "Local Authority 142", + "x": 17, + "y": 4, + "average_household_income_change": -513.751954512872, + "relative_household_income_change": -0.0, + "population": 62397.385318745444 + }, + { + "local_authority_code": "E06000000143", + "local_authority_name": "Local Authority 143", + "x": 18, + "y": 4, + "average_household_income_change": -1207.0547909465174, + "relative_household_income_change": 0.4321149063234381, + "population": 132599.14340379782 + }, + { + "local_authority_code": "E06000000144", + "local_authority_name": "Local Authority 144", + "x": 19, + "y": 4, + "average_household_income_change": -1167.7105392959963, + "relative_household_income_change": 0.11568502973031569, + "population": 129009.39626547943 + }, + { + "local_authority_code": "E06000000145", + "local_authority_name": "Local Authority 145", + "x": 20, + "y": 4, + "average_household_income_change": -617.4303141086494, + "relative_household_income_change": 0.0, + "population": 135302.34238248182 + }, + { + "local_authority_code": "E06000000146", + "local_authority_name": "Local Authority 146", + "x": 21, + "y": 4, + "average_household_income_change": -1312.877126927524, + "relative_household_income_change": 0.26760164671532716, + "population": 108770.59369107803 + }, + { + "local_authority_code": "E06000000147", + "local_authority_name": "Local Authority 147", + "x": 22, + "y": 4, + "average_household_income_change": -1338.488585593179, + "relative_household_income_change": 1e-12, + "population": 128892.88998607552 + }, + { + "local_authority_code": "E06000000148", + "local_authority_name": "Local Authority 148", + "x": null, + "y": null, + "average_household_income_change": 545.2771172295146, + "relative_household_income_change": -0.0, + "population": 87531.96012899585 + }, + { + "local_authority_code": "E06000000149", + "local_authority_name": "Local Authority 149", + "x": 24, + "y": 4, + "average_household_income_change": 1213.1704992739687, + "relative_household_income_change": -3.5e-9, + "population": 60503.947543959046 + }, + { + "local_authority_code": "E06000000150", + "local_authority_name": "Local Authority 150", + "x": 25, + "y": 4, + "average_household_income_change": -219.29221357147676, + "relative_household_income_change": -3.5e-9, + "population": 64616.75513116325 + }, + { + "local_authority_code": "E06000000151", + "local_authority_name": "Local Authority 151", + "x": 26, + "y": 4, + "average_household_income_change": 1916.5046242970254, + "relative_household_income_change": 1e-12, + "population": 79823.49679126855 + }, + { + "local_authority_code": "E06000000152", + "local_authority_name": "Local Authority 152", + "x": 27, + "y": 4, + "average_household_income_change": 725.2624870496547, + "relative_household_income_change": 0.844017537795965, + "population": 62800.32153726286 + }, + { + "local_authority_code": "E06000000153", + "local_authority_name": "Local Authority 153", + "x": 28, + "y": 4, + "average_household_income_change": 1298.767112545541, + "relative_household_income_change": -3.5e-9, + "population": 66498.84726634368 + }, + { + "local_authority_code": "E06000000154", + "local_authority_name": "Local Authority 154", + "x": 29, + "y": 4, + "average_household_income_change": -1938.804885839403, + "relative_household_income_change": -0.0, + "population": 61460.28946534437 + }, + { + "local_authority_code": "E06000000155", + "local_authority_name": "Local Authority 155", + "x": null, + "y": null, + "average_household_income_change": 1136.131498777778, + "relative_household_income_change": -0.0, + "population": 67484.6362362209 + }, + { + "local_authority_code": "E06000000156", + "local_authority_name": "Local Authority 156", + "x": 0, + "y": 5, + "average_household_income_change": -19.944300086543354, + "relative_household_income_change": -3.5e-9, + "population": 57647.27599030901 + }, + { + "local_authority_code": "E06000000157", + "local_authority_name": "Local Authority 157", + "x": 1, + "y": 5, + "average_household_income_change": -1404.5693292455107, + "relative_household_income_change": -0.0, + "population": 140489.2540612634 + }, + { + "local_authority_code": "E06000000158", + "local_authority_name": "Local Authority 158", + "x": 2, + "y": 5, + "average_household_income_change": 1585.0801748542729, + "relative_household_income_change": -3.5e-9, + "population": 96200.97948146173 + }, + { + "local_authority_code": "E06000000159", + "local_authority_name": "Local Authority 159", + "x": 3, + "y": 5, + "average_household_income_change": 1168.9720491958878, + "relative_household_income_change": 0.8188434437327052, + "population": 54464.32197461528 + }, + { + "local_authority_code": "E06000000160", + "local_authority_name": "Local Authority 160", + "x": 4, + "y": 5, + "average_household_income_change": 1514.9856804708609, + "relative_household_income_change": -3.5e-9, + "population": 50183.4497151524 + }, + { + "local_authority_code": "E06000000161", + "local_authority_name": "Local Authority 161", + "x": 5, + "y": 5, + "average_household_income_change": -1331.1166293341512, + "relative_household_income_change": -3.5e-9, + "population": 58108.164802832755 + }, + { + "local_authority_code": "E06000000162", + "local_authority_name": "Local Authority 162", + "x": null, + "y": null, + "average_household_income_change": -476.03320757418555, + "relative_household_income_change": 0.8733176798470372, + "population": 102673.4921284775 + }, + { + "local_authority_code": "E06000000163", + "local_authority_name": "Local Authority 163", + "x": 7, + "y": 5, + "average_household_income_change": 20.200059195911724, + "relative_household_income_change": 0.4010141399599696, + "population": 148128.53103472033 + }, + { + "local_authority_code": "E06000000164", + "local_authority_name": "Local Authority 164", + "x": 8, + "y": 5, + "average_household_income_change": 1943.317850704771, + "relative_household_income_change": 0.2938326528671249, + "population": 53467.82852088674 + }, + { + "local_authority_code": "E06000000165", + "local_authority_name": "Local Authority 165", + "x": 9, + "y": 5, + "average_household_income_change": -1108.9593653220206, + "relative_household_income_change": -3.5e-9, + "population": 71870.87879550472 + }, + { + "local_authority_code": "E06000000166", + "local_authority_name": "Local Authority 166", + "x": 10, + "y": 5, + "average_household_income_change": 1417.6707836259984, + "relative_household_income_change": -3.5e-9, + "population": 85702.49386785214 + }, + { + "local_authority_code": "E06000000167", + "local_authority_name": "Local Authority 167", + "x": 11, + "y": 5, + "average_household_income_change": -1191.6164426791443, + "relative_household_income_change": -0.0, + "population": 92120.03448182667 + }, + { + "local_authority_code": "E06000000168", + "local_authority_name": "Local Authority 168", + "x": 12, + "y": 5, + "average_household_income_change": -1521.2609606051815, + "relative_household_income_change": 1e-12, + "population": 96889.65526830831 + }, + { + "local_authority_code": "E06000000169", + "local_authority_name": "Local Authority 169", + "x": null, + "y": null, + "average_household_income_change": -1075.9555412420489, + "relative_household_income_change": -3.5e-9, + "population": 64098.17611631555 + }, + { + "local_authority_code": "E06000000170", + "local_authority_name": "Local Authority 170", + "x": 14, + "y": 5, + "average_household_income_change": -1537.4856380387891, + "relative_household_income_change": 0.0, + "population": 51758.74338339896 + }, + { + "local_authority_code": "E06000000171", + "local_authority_name": "Local Authority 171", + "x": 15, + "y": 5, + "average_household_income_change": 1371.007153530756, + "relative_household_income_change": 0.5859568395067843, + "population": 70540.06204219378 + }, + { + "local_authority_code": "E06000000172", + "local_authority_name": "Local Authority 172", + "x": 16, + "y": 5, + "average_household_income_change": -1906.5786914495363, + "relative_household_income_change": -3.5e-9, + "population": 101829.17278456208 + }, + { + "local_authority_code": "E06000000173", + "local_authority_name": "Local Authority 173", + "x": 17, + "y": 5, + "average_household_income_change": 708.8092408487393, + "relative_household_income_change": -3.5e-9, + "population": 139656.85560940191 + }, + { + "local_authority_code": "E06000000174", + "local_authority_name": "Local Authority 174", + "x": 18, + "y": 5, + "average_household_income_change": -272.20699932632454, + "relative_household_income_change": -3.5e-9, + "population": 54984.043048109976 + }, + { + "local_authority_code": "E06000000175", + "local_authority_name": "Local Authority 175", + "x": 19, + "y": 5, + "average_household_income_change": -1807.2069435793342, + "relative_household_income_change": -3.5e-9, + "population": 66932.47835188187 + }, + { + "local_authority_code": "E06000000176", + "local_authority_name": "Local Authority 176", + "x": null, + "y": null, + "average_household_income_change": 925.4429578341852, + "relative_household_income_change": 1e-12, + "population": 116852.65238026805 + }, + { + "local_authority_code": "E06000000177", + "local_authority_name": "Local Authority 177", + "x": 21, + "y": 5, + "average_household_income_change": -561.9776294311647, + "relative_household_income_change": -3.5e-9, + "population": 101182.57511547924 + }, + { + "local_authority_code": "E06000000178", + "local_authority_name": "Local Authority 178", + "x": 22, + "y": 5, + "average_household_income_change": -107.53985599744986, + "relative_household_income_change": 0.5851294909850242, + "population": 126404.4489031002 + }, + { + "local_authority_code": "E06000000179", + "local_authority_name": "Local Authority 179", + "x": 23, + "y": 5, + "average_household_income_change": -1841.4547555666206, + "relative_household_income_change": -0.0, + "population": 102623.3963837607 + }, + { + "local_authority_code": "E06000000180", + "local_authority_name": "Local Authority 180", + "x": 24, + "y": 5, + "average_household_income_change": -39.51880574533817, + "relative_household_income_change": 1e-12, + "population": 92619.37182461639 + }, + { + "local_authority_code": "E06000000181", + "local_authority_name": "Local Authority 181", + "x": 25, + "y": 5, + "average_household_income_change": -580.1224130447231, + "relative_household_income_change": 1e-12, + "population": 96884.8756462903 + }, + { + "local_authority_code": "E06000000182", + "local_authority_name": "Local Authority 182", + "x": 26, + "y": 5, + "average_household_income_change": 992.1120432616349, + "relative_household_income_change": 0.6451118196633416, + "population": 73957.67565706733 + }, + { + "local_authority_code": "E06000000183", + "local_authority_name": "Local Authority 183", + "x": null, + "y": null, + "average_household_income_change": -1732.1059858114807, + "relative_household_income_change": 1e-12, + "population": 65395.68845025848 + }, + { + "local_authority_code": "E06000000184", + "local_authority_name": "Local Authority 184", + "x": 28, + "y": 5, + "average_household_income_change": 710.5325151252426, + "relative_household_income_change": -3.5e-9, + "population": 109535.8179164822 + }, + { + "local_authority_code": "E06000000185", + "local_authority_name": "Local Authority 185", + "x": 29, + "y": 5, + "average_household_income_change": 1832.2854393017299, + "relative_household_income_change": -3.5e-9, + "population": 60669.82708708667 + }, + { + "local_authority_code": "E06000000186", + "local_authority_name": "Local Authority 186", + "x": 30, + "y": 5, + "average_household_income_change": 1819.569360396747, + "relative_household_income_change": 0.0, + "population": 79655.1474051923 + }, + { + "local_authority_code": "E06000000187", + "local_authority_name": "Local Authority 187", + "x": 0, + "y": 6, + "average_household_income_change": 408.54837765137654, + "relative_household_income_change": -0.0, + "population": 130590.61729258868 + }, + { + "local_authority_code": "E06000000188", + "local_authority_name": "Local Authority 188", + "x": 1, + "y": 6, + "average_household_income_change": -1643.6986591969683, + "relative_household_income_change": 1e-12, + "population": 59909.55130953969 + }, + { + "local_authority_code": "E06000000189", + "local_authority_name": "Local Authority 189", + "x": 2, + "y": 6, + "average_household_income_change": -1830.8478998657392, + "relative_household_income_change": 1e-12, + "population": 59489.20805628684 + }, + { + "local_authority_code": "E06000000190", + "local_authority_name": "Local Authority 190", + "x": null, + "y": null, + "average_household_income_change": -1905.7436084963838, + "relative_household_income_change": 0.8499679168235974, + "population": 52174.8103666158 + }, + { + "local_authority_code": "E06000000191", + "local_authority_name": "Local Authority 191", + "x": 4, + "y": 6, + "average_household_income_change": 757.2216364786452, + "relative_household_income_change": -3.5e-9, + "population": 129939.34349845978 + }, + { + "local_authority_code": "E06000000192", + "local_authority_name": "Local Authority 192", + "x": 5, + "y": 6, + "average_household_income_change": 1770.2853720417813, + "relative_household_income_change": -0.0, + "population": 87426.04381781204 + }, + { + "local_authority_code": "E06000000193", + "local_authority_name": "Local Authority 193", + "x": 6, + "y": 6, + "average_household_income_change": 348.9531695535768, + "relative_household_income_change": 0.0, + "population": 89746.21562269032 + }, + { + "local_authority_code": "E06000000194", + "local_authority_name": "Local Authority 194", + "x": 7, + "y": 6, + "average_household_income_change": -745.3033309829049, + "relative_household_income_change": 0.0, + "population": 138162.6468560306 + }, + { + "local_authority_code": "E06000000195", + "local_authority_name": "Local Authority 195", + "x": 8, + "y": 6, + "average_household_income_change": 1042.848222721133, + "relative_household_income_change": 0.06846816595354055, + "population": 68468.23825403182 + }, + { + "local_authority_code": "E06000000196", + "local_authority_name": "Local Authority 196", + "x": 9, + "y": 6, + "average_household_income_change": -1875.6841411500104, + "relative_household_income_change": -3.5e-9, + "population": 98053.93559753371 + }, + { + "local_authority_code": "E06000000197", + "local_authority_name": "Local Authority 197", + "x": null, + "y": null, + "average_household_income_change": 1680.4842438289293, + "relative_household_income_change": 1e-12, + "population": 110871.29037186065 + }, + { + "local_authority_code": "E06000000198", + "local_authority_name": "Local Authority 198", + "x": 11, + "y": 6, + "average_household_income_change": 355.7356241268361, + "relative_household_income_change": -3.5e-9, + "population": 61445.557257757966 + }, + { + "local_authority_code": "E06000000199", + "local_authority_name": "Local Authority 199", + "x": 12, + "y": 6, + "average_household_income_change": -1656.5910190820948, + "relative_household_income_change": 1e-12, + "population": 75125.88651361875 + }, + { + "local_authority_code": "E06000000200", + "local_authority_name": "Local Authority 200", + "x": 13, + "y": 6, + "average_household_income_change": 1519.5281972087762, + "relative_household_income_change": -3.5e-9, + "population": 132081.12620030972 + }, + { + "local_authority_code": "E06000000201", + "local_authority_name": "Local Authority 201", + "x": 14, + "y": 6, + "average_household_income_change": -892.9346315357928, + "relative_household_income_change": 0.0, + "population": 112829.92103707488 + }, + { + "local_authority_code": "E06000000202", + "local_authority_name": "Local Authority 202", + "x": 15, + "y": 6, + "average_household_income_change": 1880.715568929332, + "relative_household_income_change": -3.5e-9, + "population": 110874.8283873219 + }, + { + "local_authority_code": "E06000000203", + "local_authority_name": "Local Authority 203", + "x": 16, + "y": 6, + "average_household_income_change": 842.4145738218903, + "relative_household_income_change": -3.5e-9, + "population": 60412.61694731236 + }, + { + "local_authority_code": "E06000000204", + "local_authority_name": "Local Authority 204", + "x": null, + "y": null, + "average_household_income_change": -705.471357896287, + "relative_household_income_change": -3.5e-9, + "population": 138517.7948301562 + }, + { + "local_authority_code": "E06000000205", + "local_authority_name": "Local Authority 205", + "x": 18, + "y": 6, + "average_household_income_change": 1797.4377063971422, + "relative_household_income_change": 0.0, + "population": 55956.24889439437 + }, + { + "local_authority_code": "E06000000206", + "local_authority_name": "Local Authority 206", + "x": 19, + "y": 6, + "average_household_income_change": 864.4317426019547, + "relative_household_income_change": 0.033828876403854236, + "population": 57600.72894162411 + }, + { + "local_authority_code": "E06000000207", + "local_authority_name": "Local Authority 207", + "x": 20, + "y": 6, + "average_household_income_change": -55.65987599011679, + "relative_household_income_change": 1e-12, + "population": 108950.25500093267 + }, + { + "local_authority_code": "E06000000208", + "local_authority_name": "Local Authority 208", + "x": 21, + "y": 6, + "average_household_income_change": -1550.8351036272572, + "relative_household_income_change": -3.5e-9, + "population": 124542.21626147522 + }, + { + "local_authority_code": "E06000000209", + "local_authority_name": "Local Authority 209", + "x": 22, + "y": 6, + "average_household_income_change": -850.3270689942401, + "relative_household_income_change": 1e-12, + "population": 149228.6199633644 + }, + { + "local_authority_code": "E06000000210", + "local_authority_name": "Local Authority 210", + "x": 23, + "y": 6, + "average_household_income_change": -80.61036125681741, + "relative_household_income_change": -3.5e-9, + "population": 75852.58545389926 + }, + { + "local_authority_code": "E06000000211", + "local_authority_name": "Local Authority 211", + "x": null, + "y": null, + "average_household_income_change": 752.9782555919926, + "relative_household_income_change": 1e-12, + "population": 138696.91612606982 + }, + { + "local_authority_code": "E06000000212", + "local_authority_name": "Local Authority 212", + "x": 25, + "y": 6, + "average_household_income_change": 1335.5289377583035, + "relative_household_income_change": 1e-12, + "population": 69346.05149303882 + }, + { + "local_authority_code": "E06000000213", + "local_authority_name": "Local Authority 213", + "x": 26, + "y": 6, + "average_household_income_change": 1893.1738017177952, + "relative_household_income_change": 0.0, + "population": 132010.16436654507 + }, + { + "local_authority_code": "E06000000214", + "local_authority_name": "Local Authority 214", + "x": 27, + "y": 6, + "average_household_income_change": -569.6717516392021, + "relative_household_income_change": 0.7832180104424888, + "population": 95128.54328083304 + }, + { + "local_authority_code": "E06000000215", + "local_authority_name": "Local Authority 215", + "x": 28, + "y": 6, + "average_household_income_change": -1627.883853584315, + "relative_household_income_change": 0.0, + "population": 101153.74778774349 + }, + { + "local_authority_code": "E06000000216", + "local_authority_name": "Local Authority 216", + "x": 29, + "y": 6, + "average_household_income_change": -1322.8076449238276, + "relative_household_income_change": -3.5e-9, + "population": 56347.31430493599 + }, + { + "local_authority_code": "E06000000217", + "local_authority_name": "Local Authority 217", + "x": 30, + "y": 6, + "average_household_income_change": 1519.4125827216465, + "relative_household_income_change": -0.0, + "population": 141806.4685395045 + }, + { + "local_authority_code": "E06000000218", + "local_authority_name": "Local Authority 218", + "x": null, + "y": null, + "average_household_income_change": 1509.8863685346876, + "relative_household_income_change": 0.4518054828480579, + "population": 111379.4220157825 + }, + { + "local_authority_code": "E06000000219", + "local_authority_name": "Local Authority 219", + "x": 1, + "y": 7, + "average_household_income_change": 858.0575413750009, + "relative_household_income_change": 0.6515707052700975, + "population": 101392.46293323096 + }, + { + "local_authority_code": "E06000000220", + "local_authority_name": "Local Authority 220", + "x": 2, + "y": 7, + "average_household_income_change": 1539.063867606706, + "relative_household_income_change": 0.08332081692084092, + "population": 106227.72748735608 + }, + { + "local_authority_code": "E06000000221", + "local_authority_name": "Local Authority 221", + "x": 3, + "y": 7, + "average_household_income_change": 1125.9579822870646, + "relative_household_income_change": 1e-12, + "population": 79072.8218332542 + }, + { + "local_authority_code": "E06000000222", + "local_authority_name": "Local Authority 222", + "x": 4, + "y": 7, + "average_household_income_change": 1991.8295690955406, + "relative_household_income_change": 0.0, + "population": 87265.51073046919 + }, + { + "local_authority_code": "E06000000223", + "local_authority_name": "Local Authority 223", + "x": 5, + "y": 7, + "average_household_income_change": 1857.7571143100572, + "relative_household_income_change": 0.8694923657391472, + "population": 72659.01155471863 + }, + { + "local_authority_code": "E06000000224", + "local_authority_name": "Local Authority 224", + "x": 6, + "y": 7, + "average_household_income_change": 582.8592307220295, + "relative_household_income_change": 0.0, + "population": 59591.53172435968 + }, + { + "local_authority_code": "E06000000225", + "local_authority_name": "Local Authority 225", + "x": null, + "y": null, + "average_household_income_change": -1604.9195424328059, + "relative_household_income_change": -3.5e-9, + "population": 91299.67168021623 + }, + { + "local_authority_code": "E06000000226", + "local_authority_name": "Local Authority 226", + "x": 8, + "y": 7, + "average_household_income_change": -1760.2878795178665, + "relative_household_income_change": 0.728341205120138, + "population": 59437.467109970996 + }, + { + "local_authority_code": "E06000000227", + "local_authority_name": "Local Authority 227", + "x": 9, + "y": 7, + "average_household_income_change": -1976.5708846512755, + "relative_household_income_change": 0.8609845659144635, + "population": 86764.30335666653 + }, + { + "local_authority_code": "E06000000228", + "local_authority_name": "Local Authority 228", + "x": 10, + "y": 7, + "average_household_income_change": -98.97644323572274, + "relative_household_income_change": 0.7256565627219298, + "population": 86854.77541952155 + }, + { + "local_authority_code": "E06000000229", + "local_authority_name": "Local Authority 229", + "x": 11, + "y": 7, + "average_household_income_change": -931.2346405171978, + "relative_household_income_change": 1e-12, + "population": 94065.9443818011 + }, + { + "local_authority_code": "E06000000230", + "local_authority_name": "Local Authority 230", + "x": 12, + "y": 7, + "average_household_income_change": -439.9071701350206, + "relative_household_income_change": -3.5e-9, + "population": 134163.5908219147 + }, + { + "local_authority_code": "E06000000231", + "local_authority_name": "Local Authority 231", + "x": 13, + "y": 7, + "average_household_income_change": -1591.3535006330312, + "relative_household_income_change": -0.0, + "population": 64793.23200572934 + }, + { + "local_authority_code": "E06000000232", + "local_authority_name": "Local Authority 232", + "x": null, + "y": null, + "average_household_income_change": 403.4903225216731, + "relative_household_income_change": 1e-12, + "population": 127856.55191534641 + }, + { + "local_authority_code": "E06000000233", + "local_authority_name": "Local Authority 233", + "x": 15, + "y": 7, + "average_household_income_change": 1656.1380154606948, + "relative_household_income_change": 1e-12, + "population": 111461.87010410217 + }, + { + "local_authority_code": "E06000000234", + "local_authority_name": "Local Authority 234", + "x": 16, + "y": 7, + "average_household_income_change": 1466.347687579943, + "relative_household_income_change": 0.0, + "population": 60236.23142612746 + }, + { + "local_authority_code": "E06000000235", + "local_authority_name": "Local Authority 235", + "x": 17, + "y": 7, + "average_household_income_change": -1903.0397927241559, + "relative_household_income_change": 1e-12, + "population": 99830.54271526785 + }, + { + "local_authority_code": "E06000000236", + "local_authority_name": "Local Authority 236", + "x": 18, + "y": 7, + "average_household_income_change": -1579.0994583602003, + "relative_household_income_change": 0.509998146550363, + "population": 138565.29795023135 + }, + { + "local_authority_code": "E06000000237", + "local_authority_name": "Local Authority 237", + "x": 19, + "y": 7, + "average_household_income_change": 709.2203209255472, + "relative_household_income_change": 0.0, + "population": 124197.3632538812 + }, + { + "local_authority_code": "E06000000238", + "local_authority_name": "Local Authority 238", + "x": 20, + "y": 7, + "average_household_income_change": 837.6158957883022, + "relative_household_income_change": -3.5e-9, + "population": 143454.69827079526 + }, + { + "local_authority_code": "E06000000239", + "local_authority_name": "Local Authority 239", + "x": null, + "y": null, + "average_household_income_change": -516.9005246383272, + "relative_household_income_change": -3.5e-9, + "population": 57037.494564974375 + }, + { + "local_authority_code": "E06000000240", + "local_authority_name": "Local Authority 240", + "x": 22, + "y": 7, + "average_household_income_change": 665.0094012510017, + "relative_household_income_change": -3.5e-9, + "population": 55242.63945586822 + }, + { + "local_authority_code": "E06000000241", + "local_authority_name": "Local Authority 241", + "x": 23, + "y": 7, + "average_household_income_change": 641.8757097418747, + "relative_household_income_change": 0.6890206788110149, + "population": 110740.67170974993 + }, + { + "local_authority_code": "E06000000242", + "local_authority_name": "Local Authority 242", + "x": 24, + "y": 7, + "average_household_income_change": 838.311650071085, + "relative_household_income_change": 0.0, + "population": 82383.11841393165 + }, + { + "local_authority_code": "E06000000243", + "local_authority_name": "Local Authority 243", + "x": 25, + "y": 7, + "average_household_income_change": 1034.249538488258, + "relative_household_income_change": -0.0, + "population": 52093.415519193295 + }, + { + "local_authority_code": "E06000000244", + "local_authority_name": "Local Authority 244", + "x": 26, + "y": 7, + "average_household_income_change": -1053.5590021723342, + "relative_household_income_change": -3.5e-9, + "population": 128568.646242031 + }, + { + "local_authority_code": "E06000000245", + "local_authority_name": "Local Authority 245", + "x": 27, + "y": 7, + "average_household_income_change": 413.1341063514338, + "relative_household_income_change": 1e-12, + "population": 95028.43308140374 + }, + { + "local_authority_code": "E06000000246", + "local_authority_name": "Local Authority 246", + "x": null, + "y": null, + "average_household_income_change": 726.7269295469209, + "relative_household_income_change": 0.0, + "population": 127274.43476063575 + }, + { + "local_authority_code": "E06000000247", + "local_authority_name": "Local Authority 247", + "x": 29, + "y": 7, + "average_household_income_change": 1809.5052200800587, + "relative_household_income_change": 1e-12, + "population": 59565.128533094845 + }, + { + "local_authority_code": "E06000000248", + "local_authority_name": "Local Authority 248", + "x": 30, + "y": 7, + "average_household_income_change": -1058.6836508131187, + "relative_household_income_change": 1e-12, + "population": 82279.44191562528 + }, + { + "local_authority_code": "E06000000249", + "local_authority_name": "Local Authority 249", + "x": 0, + "y": 8, + "average_household_income_change": 1448.4446061658857, + "relative_household_income_change": 0.4653143220721977, + "population": 123530.70098753371 + }, + { + "local_authority_code": "E06000000250", + "local_authority_name": "Local Authority 250", + "x": 1, + "y": 8, + "average_household_income_change": -212.2114626921525, + "relative_household_income_change": 0.852927137010199, + "population": 79092.73955186279 + }, + { + "local_authority_code": "E06000000251", + "local_authority_name": "Local Authority 251", + "x": 2, + "y": 8, + "average_household_income_change": -536.492171462005, + "relative_household_income_change": 1e-12, + "population": 54781.582558346054 + }, + { + "local_authority_code": "E06000000252", + "local_authority_name": "Local Authority 252", + "x": 3, + "y": 8, + "average_household_income_change": 1270.0802925219489, + "relative_household_income_change": 1e-12, + "population": 100948.36759624102 + }, + { + "local_authority_code": "E06000000253", + "local_authority_name": "Local Authority 253", + "x": null, + "y": null, + "average_household_income_change": -400.4186572841455, + "relative_household_income_change": 0.9118611203153317, + "population": 80534.73349695683 + }, + { + "local_authority_code": "E06000000254", + "local_authority_name": "Local Authority 254", + "x": 5, + "y": 8, + "average_household_income_change": 1436.8345817862908, + "relative_household_income_change": 0.0, + "population": 92294.26908433915 + }, + { + "local_authority_code": "E06000000255", + "local_authority_name": "Local Authority 255", + "x": 6, + "y": 8, + "average_household_income_change": 557.144812679411, + "relative_household_income_change": -3.5e-9, + "population": 110218.69910899561 + }, + { + "local_authority_code": "E06000000256", + "local_authority_name": "Local Authority 256", + "x": 7, + "y": 8, + "average_household_income_change": -258.6649908064569, + "relative_household_income_change": 1e-12, + "population": 57714.24382857021 + }, + { + "local_authority_code": "E06000000257", + "local_authority_name": "Local Authority 257", + "x": 8, + "y": 8, + "average_household_income_change": -1758.3705939542908, + "relative_household_income_change": 0.764995400685606, + "population": 131089.37081954637 + }, + { + "local_authority_code": "E06000000258", + "local_authority_name": "Local Authority 258", + "x": 9, + "y": 8, + "average_household_income_change": -1783.2292403988529, + "relative_household_income_change": 1e-12, + "population": 104494.64950338395 + }, + { + "local_authority_code": "E06000000259", + "local_authority_name": "Local Authority 259", + "x": 10, + "y": 8, + "average_household_income_change": -1327.8244041906157, + "relative_household_income_change": 1e-12, + "population": 113337.99406176846 + }, + { + "local_authority_code": "E06000000260", + "local_authority_name": "Local Authority 260", + "x": null, + "y": null, + "average_household_income_change": 684.877297170174, + "relative_household_income_change": 0.7666200435868592, + "population": 53782.60546490354 + }, + { + "local_authority_code": "E06000000261", + "local_authority_name": "Local Authority 261", + "x": 12, + "y": 8, + "average_household_income_change": -1764.2297057997705, + "relative_household_income_change": 0.0, + "population": 55563.5849283389 + }, + { + "local_authority_code": "E06000000262", + "local_authority_name": "Local Authority 262", + "x": 13, + "y": 8, + "average_household_income_change": -255.91025902887486, + "relative_household_income_change": 1e-12, + "population": 99982.94437622868 + }, + { + "local_authority_code": "E06000000263", + "local_authority_name": "Local Authority 263", + "x": 14, + "y": 8, + "average_household_income_change": -260.18748124346524, + "relative_household_income_change": 1e-12, + "population": 85148.0146588767 + }, + { + "local_authority_code": "E06000000264", + "local_authority_name": "Local Authority 264", + "x": 15, + "y": 8, + "average_household_income_change": -789.2344583138699, + "relative_household_income_change": 1e-12, + "population": 108161.34969368408 + }, + { + "local_authority_code": "E06000000265", + "local_authority_name": "Local Authority 265", + "x": 16, + "y": 8, + "average_household_income_change": -579.3256462120007, + "relative_household_income_change": -0.0, + "population": 91725.54291633592 + }, + { + "local_authority_code": "E06000000266", + "local_authority_name": "Local Authority 266", + "x": 17, + "y": 8, + "average_household_income_change": -1460.1637924293796, + "relative_household_income_change": 1e-12, + "population": 70001.25677576543 + }, + { + "local_authority_code": "E06000000267", + "local_authority_name": "Local Authority 267", + "x": null, + "y": null, + "average_household_income_change": -298.8151888887605, + "relative_household_income_change": -3.5e-9, + "population": 123887.64729678868 + }, + { + "local_authority_code": "E06000000268", + "local_authority_name": "Local Authority 268", + "x": 19, + "y": 8, + "average_household_income_change": -1492.7346834787274, + "relative_household_income_change": 0.0, + "population": 90000.38917674075 + }, + { + "local_authority_code": "E06000000269", + "local_authority_name": "Local Authority 269", + "x": 20, + "y": 8, + "average_household_income_change": 269.95612119315916, + "relative_household_income_change": 0.7682928997059275, + "population": 87441.05104136605 + }, + { + "local_authority_code": "E06000000270", + "local_authority_name": "Local Authority 270", + "x": 21, + "y": 8, + "average_household_income_change": -1775.579629167957, + "relative_household_income_change": -3.5e-9, + "population": 93847.56933635911 + }, + { + "local_authority_code": "E06000000271", + "local_authority_name": "Local Authority 271", + "x": 22, + "y": 8, + "average_household_income_change": 1917.3099341009201, + "relative_household_income_change": 0.7989601983692834, + "population": 88816.01516746833 + }, + { + "local_authority_code": "E06000000272", + "local_authority_name": "Local Authority 272", + "x": 23, + "y": 8, + "average_household_income_change": 1425.287215554047, + "relative_household_income_change": 1e-12, + "population": 131712.46458855222 + }, + { + "local_authority_code": "E06000000273", + "local_authority_name": "Local Authority 273", + "x": 24, + "y": 8, + "average_household_income_change": 214.07954117904282, + "relative_household_income_change": -0.0, + "population": 85239.5152204162 + }, + { + "local_authority_code": "E06000000274", + "local_authority_name": "Local Authority 274", + "x": null, + "y": null, + "average_household_income_change": 474.26196866968786, + "relative_household_income_change": 0.40147264541517713, + "population": 149088.15989006817 + }, + { + "local_authority_code": "E06000000275", + "local_authority_name": "Local Authority 275", + "x": 26, + "y": 8, + "average_household_income_change": 469.02445254080095, + "relative_household_income_change": 0.0, + "population": 51716.52945984774 + }, + { + "local_authority_code": "E06000000276", + "local_authority_name": "Local Authority 276", + "x": 27, + "y": 8, + "average_household_income_change": 1318.3074227966679, + "relative_household_income_change": -0.0, + "population": 143507.4378546935 + }, + { + "local_authority_code": "E06000000277", + "local_authority_name": "Local Authority 277", + "x": 28, + "y": 8, + "average_household_income_change": -488.26844121446686, + "relative_household_income_change": 0.0, + "population": 109268.00346399064 + }, + { + "local_authority_code": "E06000000278", + "local_authority_name": "Local Authority 278", + "x": 29, + "y": 8, + "average_household_income_change": 1079.9362248733341, + "relative_household_income_change": 0.4038236963373144, + "population": 79289.57169939693 + }, + { + "local_authority_code": "E06000000279", + "local_authority_name": "Local Authority 279", + "x": 30, + "y": 8, + "average_household_income_change": 393.5887992701219, + "relative_household_income_change": -0.0, + "population": 82588.28138747317 + }, + { + "local_authority_code": "E06000000280", + "local_authority_name": "Local Authority 280", + "x": 0, + "y": 9, + "average_household_income_change": -1151.3682127169345, + "relative_household_income_change": -0.0, + "population": 92957.50128701699 + }, + { + "local_authority_code": "E06000000281", + "local_authority_name": "Local Authority 281", + "x": null, + "y": null, + "average_household_income_change": -1837.624942762603, + "relative_household_income_change": 0.33343966871360353, + "population": 145490.62320200523 + }, + { + "local_authority_code": "E06000000282", + "local_authority_name": "Local Authority 282", + "x": 2, + "y": 9, + "average_household_income_change": -948.174560909842, + "relative_household_income_change": 0.6865062575083919, + "population": 126283.14237619072 + }, + { + "local_authority_code": "E06000000283", + "local_authority_name": "Local Authority 283", + "x": 3, + "y": 9, + "average_household_income_change": 749.9567568596154, + "relative_household_income_change": -3.5e-9, + "population": 133516.3436537348 + }, + { + "local_authority_code": "E06000000284", + "local_authority_name": "Local Authority 284", + "x": 4, + "y": 9, + "average_household_income_change": -1942.695785205236, + "relative_household_income_change": 0.8781793279501448, + "population": 81219.27203410128 + }, + { + "local_authority_code": "E06000000285", + "local_authority_name": "Local Authority 285", + "x": 5, + "y": 9, + "average_household_income_change": -1956.9467679013912, + "relative_household_income_change": -3.5e-9, + "population": 55900.53972903704 + }, + { + "local_authority_code": "E06000000286", + "local_authority_name": "Local Authority 286", + "x": 6, + "y": 9, + "average_household_income_change": 623.5927200680891, + "relative_household_income_change": -3.5e-9, + "population": 79076.26527150461 + }, + { + "local_authority_code": "E06000000287", + "local_authority_name": "Local Authority 287", + "x": 7, + "y": 9, + "average_household_income_change": 998.5169020724971, + "relative_household_income_change": 0.0, + "population": 121342.67637408897 + }, + { + "local_authority_code": "E06000000288", + "local_authority_name": "Local Authority 288", + "x": null, + "y": null, + "average_household_income_change": -1820.3852673716563, + "relative_household_income_change": 1e-12, + "population": 132830.3117877651 + }, + { + "local_authority_code": "E06000000289", + "local_authority_name": "Local Authority 289", + "x": 9, + "y": 9, + "average_household_income_change": 1948.3789159219884, + "relative_household_income_change": 0.12014587257431875, + "population": 68445.65221127166 + }, + { + "local_authority_code": "E06000000290", + "local_authority_name": "Local Authority 290", + "x": 10, + "y": 9, + "average_household_income_change": 423.4069254456765, + "relative_household_income_change": -3.5e-9, + "population": 66720.62706762293 + }, + { + "local_authority_code": "E06000000291", + "local_authority_name": "Local Authority 291", + "x": 11, + "y": 9, + "average_household_income_change": 281.0095652309492, + "relative_household_income_change": 0.0, + "population": 70639.58860036393 + }, + { + "local_authority_code": "E06000000292", + "local_authority_name": "Local Authority 292", + "x": 12, + "y": 9, + "average_household_income_change": 220.18925132835898, + "relative_household_income_change": -3.5e-9, + "population": 133300.24112989724 + }, + { + "local_authority_code": "E06000000293", + "local_authority_name": "Local Authority 293", + "x": 13, + "y": 9, + "average_household_income_change": 1384.243091982024, + "relative_household_income_change": 1e-12, + "population": 79745.25417884401 + }, + { + "local_authority_code": "E06000000294", + "local_authority_name": "Local Authority 294", + "x": 14, + "y": 9, + "average_household_income_change": 274.196564320758, + "relative_household_income_change": 1e-12, + "population": 115781.39119694172 + }, + { + "local_authority_code": "E06000000295", + "local_authority_name": "Local Authority 295", + "x": null, + "y": null, + "average_household_income_change": -366.2436633812365, + "relative_household_income_change": 0.2724055786550509, + "population": 118167.67210480243 + }, + { + "local_authority_code": "E06000000296", + "local_authority_name": "Local Authority 296", + "x": 16, + "y": 9, + "average_household_income_change": -416.3777338834693, + "relative_household_income_change": 0.0, + "population": 87322.12558288818 + }, + { + "local_authority_code": "E06000000297", + "local_authority_name": "Local Authority 297", + "x": 17, + "y": 9, + "average_household_income_change": -986.5104904687718, + "relative_household_income_change": 0.9976970816212194, + "population": 126700.16226183344 + }, + { + "local_authority_code": "E06000000298", + "local_authority_name": "Local Authority 298", + "x": 18, + "y": 9, + "average_household_income_change": 1280.0499716237775, + "relative_household_income_change": 1e-12, + "population": 130009.21342011327 + }, + { + "local_authority_code": "E06000000299", + "local_authority_name": "Local Authority 299", + "x": 19, + "y": 9, + "average_household_income_change": 695.194567020863, + "relative_household_income_change": -3.5e-9, + "population": 121749.1602107389 + }, + { + "local_authority_code": "E06000000300", + "local_authority_name": "Local Authority 300", + "x": 20, + "y": 9, + "average_household_income_change": 625.7473745948782, + "relative_household_income_change": 0.9887659421326285, + "population": 79438.29979595897 + }, + { + "local_authority_code": "E06000000301", + "local_authority_name": "Local Authority 301", + "x": 21, + "y": 9, + "average_household_income_change": 1707.1531326392005, + "relative_household_income_change": -3.5e-9, + "population": 90319.61710395063 + }, + { + "local_authority_code": "E06000000302", + "local_authority_name": "Local Authority 302", + "x": null, + "y": null, + "average_household_income_change": 360.74309708507803, + "relative_household_income_change": 1e-12, + "population": 78762.98544550533 + }, + { + "local_authority_code": "E06000000303", + "local_authority_name": "Local Authority 303", + "x": 23, + "y": 9, + "average_household_income_change": -1139.89488155203, + "relative_household_income_change": 0.048349037990379484, + "population": 74423.26349738428 + }, + { + "local_authority_code": "E06000000304", + "local_authority_name": "Local Authority 304", + "x": 24, + "y": 9, + "average_household_income_change": 1594.8169579207745, + "relative_household_income_change": 0.22591907290792212, + "population": 84032.00044889207 + }, + { + "local_authority_code": "E06000000305", + "local_authority_name": "Local Authority 305", + "x": 25, + "y": 9, + "average_household_income_change": -1080.1367324794787, + "relative_household_income_change": 0.9392024418031214, + "population": 121651.5707570977 + }, + { + "local_authority_code": "E06000000306", + "local_authority_name": "Local Authority 306", + "x": 26, + "y": 9, + "average_household_income_change": -331.3802060767421, + "relative_household_income_change": -3.5e-9, + "population": 95417.70209215413 + }, + { + "local_authority_code": "E06000000307", + "local_authority_name": "Local Authority 307", + "x": 27, + "y": 9, + "average_household_income_change": -1638.7362888513878, + "relative_household_income_change": 0.0, + "population": 117308.15275859929 + }, + { + "local_authority_code": "E06000000308", + "local_authority_name": "Local Authority 308", + "x": 28, + "y": 9, + "average_household_income_change": -1568.4322383589476, + "relative_household_income_change": 1e-12, + "population": 125862.9003026094 + }, + { + "local_authority_code": "E06000000309", + "local_authority_name": "Local Authority 309", + "x": null, + "y": null, + "average_household_income_change": 795.9668868388188, + "relative_household_income_change": -3.5e-9, + "population": 135858.32239161074 + }, + { + "local_authority_code": "E06000000310", + "local_authority_name": "Local Authority 310", + "x": 30, + "y": 9, + "average_household_income_change": 1933.1381935610436, + "relative_household_income_change": 0.0, + "population": 124611.61163057359 + }, + { + "local_authority_code": "E06000000311", + "local_authority_name": "Local Authority 311", + "x": 0, + "y": 10, + "average_household_income_change": -141.98181117782437, + "relative_household_income_change": -0.0, + "population": 70609.89099602692 + }, + { + "local_authority_code": "E06000000312", + "local_authority_name": "Local Authority 312", + "x": 1, + "y": 10, + "average_household_income_change": -56.44267916476542, + "relative_household_income_change": 0.0, + "population": 111699.84662409528 + }, + { + "local_authority_code": "E06000000313", + "local_authority_name": "Local Authority 313", + "x": 2, + "y": 10, + "average_household_income_change": 1778.0555217769213, + "relative_household_income_change": -3.5e-9, + "population": 145693.45404754783 + }, + { + "local_authority_code": "E06000000314", + "local_authority_name": "Local Authority 314", + "x": 3, + "y": 10, + "average_household_income_change": -1278.5715098616452, + "relative_household_income_change": -3.5e-9, + "population": 76006.43282400742 + }, + { + "local_authority_code": "E06000000315", + "local_authority_name": "Local Authority 315", + "x": 4, + "y": 10, + "average_household_income_change": -1059.1789998677025, + "relative_household_income_change": -3.5e-9, + "population": 65529.9637408226 + }, + { + "local_authority_code": "E06000000316", + "local_authority_name": "Local Authority 316", + "x": null, + "y": null, + "average_household_income_change": -1048.4707691627543, + "relative_household_income_change": 0.0, + "population": 145955.27596523814 + }, + { + "local_authority_code": "E06000000317", + "local_authority_name": "Local Authority 317", + "x": 6, + "y": 10, + "average_household_income_change": -526.7537120829884, + "relative_household_income_change": -0.0, + "population": 145820.206722863 + }, + { + "local_authority_code": "E06000000318", + "local_authority_name": "Local Authority 318", + "x": 7, + "y": 10, + "average_household_income_change": -1953.7169568476536, + "relative_household_income_change": 0.0, + "population": 145527.70903551613 + }, + { + "local_authority_code": "E06000000319", + "local_authority_name": "Local Authority 319", + "x": 8, + "y": 10, + "average_household_income_change": 1905.364779664637, + "relative_household_income_change": -0.0, + "population": 54054.22553493581 + }, + { + "local_authority_code": "E06000000320", + "local_authority_name": "Local Authority 320", + "x": 9, + "y": 10, + "average_household_income_change": 294.1624951426873, + "relative_household_income_change": -3.5e-9, + "population": 53783.2750109446 + }, + { + "local_authority_code": "E06000000321", + "local_authority_name": "Local Authority 321", + "x": 10, + "y": 10, + "average_household_income_change": -548.0681646499228, + "relative_household_income_change": 1e-12, + "population": 124067.3608380831 + }, + { + "local_authority_code": "E06000000322", + "local_authority_name": "Local Authority 322", + "x": 11, + "y": 10, + "average_household_income_change": -920.382750538947, + "relative_household_income_change": 1e-12, + "population": 64399.62052101023 + }, + { + "local_authority_code": "E06000000323", + "local_authority_name": "Local Authority 323", + "x": null, + "y": null, + "average_household_income_change": 1350.0455770723922, + "relative_household_income_change": 1e-12, + "population": 62873.80233865063 + }, + { + "local_authority_code": "E06000000324", + "local_authority_name": "Local Authority 324", + "x": 13, + "y": 10, + "average_household_income_change": -922.7161566266906, + "relative_household_income_change": 0.19694956380898854, + "population": 106076.4762961037 + }, + { + "local_authority_code": "E06000000325", + "local_authority_name": "Local Authority 325", + "x": 14, + "y": 10, + "average_household_income_change": -1002.6916131420753, + "relative_household_income_change": 0.0, + "population": 62774.55803733909 + }, + { + "local_authority_code": "E06000000326", + "local_authority_name": "Local Authority 326", + "x": 15, + "y": 10, + "average_household_income_change": 1663.6719409919683, + "relative_household_income_change": -0.0, + "population": 67807.47080663007 + }, + { + "local_authority_code": "E06000000327", + "local_authority_name": "Local Authority 327", + "x": 16, + "y": 10, + "average_household_income_change": -1411.6340938270553, + "relative_household_income_change": -0.0, + "population": 147665.7414411456 + }, + { + "local_authority_code": "E06000000328", + "local_authority_name": "Local Authority 328", + "x": 17, + "y": 10, + "average_household_income_change": -1612.4841951460103, + "relative_household_income_change": 0.0, + "population": 124470.9080460218 + }, + { + "local_authority_code": "E06000000329", + "local_authority_name": "Local Authority 329", + "x": 18, + "y": 10, + "average_household_income_change": -442.1381548896619, + "relative_household_income_change": -3.5e-9, + "population": 122077.83443159891 + }, + { + "local_authority_code": "E06000000330", + "local_authority_name": "Local Authority 330", + "x": null, + "y": null, + "average_household_income_change": 693.5865859513317, + "relative_household_income_change": 1e-12, + "population": 146696.59035836256 + }, + { + "local_authority_code": "E06000000331", + "local_authority_name": "Local Authority 331", + "x": 20, + "y": 10, + "average_household_income_change": -692.0955580068231, + "relative_household_income_change": -0.0, + "population": 57876.679797211415 + }, + { + "local_authority_code": "E06000000332", + "local_authority_name": "Local Authority 332", + "x": 21, + "y": 10, + "average_household_income_change": -1519.174748158672, + "relative_household_income_change": -0.0, + "population": 95734.55317987516 + }, + { + "local_authority_code": "E06000000333", + "local_authority_name": "Local Authority 333", + "x": 22, + "y": 10, + "average_household_income_change": -1442.6525762495714, + "relative_household_income_change": -0.0, + "population": 101590.51841877076 + }, + { + "local_authority_code": "E06000000334", + "local_authority_name": "Local Authority 334", + "x": 23, + "y": 10, + "average_household_income_change": 1790.1936017105982, + "relative_household_income_change": 0.8036893103680613, + "population": 60227.68191232477 + }, + { + "local_authority_code": "E06000000335", + "local_authority_name": "Local Authority 335", + "x": 24, + "y": 10, + "average_household_income_change": -657.7156834947568, + "relative_household_income_change": 0.0, + "population": 56033.994244607464 + }, + { + "local_authority_code": "E06000000336", + "local_authority_name": "Local Authority 336", + "x": 25, + "y": 10, + "average_household_income_change": -93.12370767006372, + "relative_household_income_change": 1e-12, + "population": 74251.63287615858 + }, + { + "local_authority_code": "E06000000337", + "local_authority_name": "Local Authority 337", + "x": null, + "y": null, + "average_household_income_change": -209.0733302843737, + "relative_household_income_change": 0.0, + "population": 92647.79125130326 + }, + { + "local_authority_code": "E06000000338", + "local_authority_name": "Local Authority 338", + "x": 27, + "y": 10, + "average_household_income_change": 1354.5181812972617, + "relative_household_income_change": -0.0, + "population": 82370.15096479152 + }, + { + "local_authority_code": "E06000000339", + "local_authority_name": "Local Authority 339", + "x": 28, + "y": 10, + "average_household_income_change": -492.64160858524696, + "relative_household_income_change": 0.0, + "population": 86770.08718112283 + }, + { + "local_authority_code": "E06000000340", + "local_authority_name": "Local Authority 340", + "x": 29, + "y": 10, + "average_household_income_change": -995.9443815964817, + "relative_household_income_change": -0.0, + "population": 135610.1666875653 + }, + { + "local_authority_code": "E06000000341", + "local_authority_name": "Local Authority 341", + "x": 30, + "y": 10, + "average_household_income_change": -0.39287356256378914, + "relative_household_income_change": 0.5297196338472642, + "population": 74252.93126537 + }, + { + "local_authority_code": "E06000000342", + "local_authority_name": "Local Authority 342", + "x": 0, + "y": 11, + "average_household_income_change": 944.950333059178, + "relative_household_income_change": 0.0, + "population": 106059.18237216485 + }, + { + "local_authority_code": "E06000000343", + "local_authority_name": "Local Authority 343", + "x": 1, + "y": 11, + "average_household_income_change": 64.77822243535725, + "relative_household_income_change": 0.0, + "population": 53563.437046919236 + }, + { + "local_authority_code": "E06000000344", + "local_authority_name": "Local Authority 344", + "x": null, + "y": null, + "average_household_income_change": -570.1810329346469, + "relative_household_income_change": -3.5e-9, + "population": 141799.32131303017 + }, + { + "local_authority_code": "E06000000345", + "local_authority_name": "Local Authority 345", + "x": 3, + "y": 11, + "average_household_income_change": -149.65675964463588, + "relative_household_income_change": 1e-12, + "population": 138491.2752178312 + }, + { + "local_authority_code": "E06000000346", + "local_authority_name": "Local Authority 346", + "x": 4, + "y": 11, + "average_household_income_change": 1519.5945289635704, + "relative_household_income_change": 0.3885347278781518, + "population": 127943.93117060614 + }, + { + "local_authority_code": "E06000000347", + "local_authority_name": "Local Authority 347", + "x": 5, + "y": 11, + "average_household_income_change": -240.12834747409696, + "relative_household_income_change": -0.0, + "population": 148496.6980579185 + }, + { + "local_authority_code": "E06000000348", + "local_authority_name": "Local Authority 348", + "x": 6, + "y": 11, + "average_household_income_change": -1184.3496615419813, + "relative_household_income_change": 0.40605730599907053, + "population": 52620.71908102276 + }, + { + "local_authority_code": "E06000000349", + "local_authority_name": "Local Authority 349", + "x": 7, + "y": 11, + "average_household_income_change": 128.04545237281982, + "relative_household_income_change": -0.0, + "population": 145538.13077819993 + }, + { + "local_authority_code": "E06000000350", + "local_authority_name": "Local Authority 350", + "x": 8, + "y": 11, + "average_household_income_change": 1616.6229865208313, + "relative_household_income_change": 0.0, + "population": 115389.84845951825 + }, + { + "local_authority_code": "E06000000351", + "local_authority_name": "Local Authority 351", + "x": null, + "y": null, + "average_household_income_change": -137.77954457466944, + "relative_household_income_change": 1e-12, + "population": 90290.34582224516 + }, + { + "local_authority_code": "E06000000352", + "local_authority_name": "Local Authority 352", + "x": 10, + "y": 11, + "average_household_income_change": -758.6668108760035, + "relative_household_income_change": 1e-12, + "population": 82891.8878076119 + }, + { + "local_authority_code": "E06000000353", + "local_authority_name": "Local Authority 353", + "x": 11, + "y": 11, + "average_household_income_change": -439.1523756355236, + "relative_household_income_change": 0.9976709354222745, + "population": 59413.06245577177 + }, + { + "local_authority_code": "E06000000354", + "local_authority_name": "Local Authority 354", + "x": 12, + "y": 11, + "average_household_income_change": 1341.2342875125476, + "relative_household_income_change": -0.0, + "population": 123965.39796798336 + }, + { + "local_authority_code": "E06000000355", + "local_authority_name": "Local Authority 355", + "x": 13, + "y": 11, + "average_household_income_change": -1339.4924488888353, + "relative_household_income_change": 0.0, + "population": 138213.72660216942 + }, + { + "local_authority_code": "E06000000356", + "local_authority_name": "Local Authority 356", + "x": 14, + "y": 11, + "average_household_income_change": 1461.0173356186356, + "relative_household_income_change": -3.5e-9, + "population": 109738.91820518073 + }, + { + "local_authority_code": "E06000000357", + "local_authority_name": "Local Authority 357", + "x": 15, + "y": 11, + "average_household_income_change": 1001.7597486741581, + "relative_household_income_change": 1e-12, + "population": 90421.41316384055 + }, + { + "local_authority_code": "E06000000358", + "local_authority_name": "Local Authority 358", + "x": null, + "y": null, + "average_household_income_change": 1368.5395672388715, + "relative_household_income_change": -3.5e-9, + "population": 105507.23691464387 + }, + { + "local_authority_code": "E06000000359", + "local_authority_name": "Local Authority 359", + "x": 17, + "y": 11, + "average_household_income_change": -1467.9886853886562, + "relative_household_income_change": 1e-12, + "population": 109966.1632713356 + }, + { + "local_authority_code": "E06000000360", + "local_authority_name": "Local Authority 360", + "x": 18, + "y": 11, + "average_household_income_change": -1471.8412412220912, + "relative_household_income_change": 1e-12, + "population": 136124.82700437307 + } + ], + "congressional_district_impact": null, + "cliff_impact": null +} diff --git a/libs/policyengine-simulation-persistence/tests/fixtures/economy_results/us_budget_window_year_2030.json b/libs/policyengine-simulation-persistence/tests/fixtures/economy_results/us_budget_window_year_2030.json new file mode 100644 index 000000000..2609876a0 --- /dev/null +++ b/libs/policyengine-simulation-persistence/tests/fixtures/economy_results/us_budget_window_year_2030.json @@ -0,0 +1,243 @@ +{ + "spm_provenance": null, + "model_version": "1.715.2", + "data_version": "1.115.5", + "budget": { + "tax_revenue_impact": -79366793153.85684, + "state_tax_revenue_impact": -207883514.77863798, + "benefit_spending_impact": -69005545839.51794, + "budgetary_impact": -52790382052.5131, + "households": 121330301.9135918, + "baseline_net_income": 11803182028970.15 + }, + "detailed_budget": { + "income_tax": { + "baseline": 835910086.1754378, + "reform": 600904702.991617, + "difference": 530325205.0108769 + }, + "snap": { + "baseline": -556143648.6193647, + "reform": 73360016.34962708, + "difference": -446634713.1170996 + }, + "eitc": { + "baseline": -654670941.4292622, + "reform": -787633415.1369398, + "difference": -571199134.842167 + }, + "ctc": { + "baseline": 854951262.856121, + "reform": 657840097.5568388, + "difference": 613304693.4046469 + }, + "ssi": { + "baseline": 600895677.0859324, + "reform": -613128763.96152, + "difference": -380300085.40092885 + }, + "state_income_tax": { + "baseline": 253951204.8262602, + "reform": 463789417.757436, + "difference": 709296715.9826944 + } + }, + "decile": { + "average": { + "1": 2280.304508167196, + "2": -2479.690484190469, + "3": 635.1113023192792, + "4": 1030.2087390988397, + "5": 35.72265426249199, + "6": -1933.2589545552933, + "7": -158.47267448912916, + "8": -2463.922756407658, + "9": 2607.5301833994486, + "10": 2192.9050211104995 + }, + "relative": { + "1": 1e-12, + "2": 1e-12, + "3": 1e-12, + "4": 0.8480440882236346, + "5": -3.5e-9, + "6": -3.5e-9, + "7": -0.0, + "8": 0.0, + "9": -3.5e-9, + "10": 1e-12 + } + }, + "inequality": { + "gini": { + "baseline": 0.5188720862166717, + "reform": 0.6479980831685668 + }, + "top_10_pct_share": { + "baseline": 0.7008787195596342, + "reform": 0.14506275949834935 + }, + "top_1_pct_share": { + "baseline": 0.673778811064165, + "reform": 0.0664384693860609 + } + }, + "poverty": { + "poverty": { + "child": { + "baseline": 0.9135318190058366, + "reform": 0.6350191059162094 + }, + "adult": { + "baseline": 0.44115195629227777, + "reform": 0.18370364871495026 + }, + "senior": { + "baseline": 0.4359243344287773, + "reform": 0.5887686783125169 + }, + "all": { + "baseline": 0.6344321858773304, + "reform": 0.19871219921346828 + } + }, + "deep_poverty": { + "child": { + "baseline": 0.32353421375885183, + "reform": 0.83942633913167 + }, + "adult": { + "baseline": 0.7081624882584023, + "reform": 0.2774787900236415 + }, + "senior": { + "baseline": 0.582200464721263, + "reform": 0.86209904579384 + }, + "all": { + "baseline": 0.12214540191789702, + "reform": 0.9345807520861901 + } + } + }, + "poverty_by_gender": { + "poverty": { + "male": { + "baseline": 0.29092425449951553, + "reform": 0.025676079413378128 + }, + "female": { + "baseline": 0.35708404851922304, + "reform": 0.08261033815091678 + } + }, + "deep_poverty": { + "male": { + "baseline": 0.9644747075046419, + "reform": 0.2856861258661594 + }, + "female": { + "baseline": 0.6752132248868613, + "reform": 0.32712215943774225 + } + } + }, + "poverty_by_race": { + "poverty": { + "white": { + "baseline": 0.32281026459482653, + "reform": 0.3216761199087408 + }, + "black": { + "baseline": 0.15290962737232017, + "reform": 0.6519226015391028 + }, + "hispanic": { + "baseline": 0.8613730888315168, + "reform": 0.8695065350868587 + }, + "other": { + "baseline": 0.6800437183523759, + "reform": 0.07775628785349609 + } + } + }, + "intra_decile": { + "deciles": { + "Gain more than 5%": [ + 0.6177296429232895, + 0.8940836745809185, + 0.2919953326615514, + 0.25004737363483476, + 0.5988096666471184, + 0.15890465923627628, + 0.5730900616153811, + 0.363324836230257, + 0.45478533334707494, + 0.3651908247451906 + ], + "Gain less than 5%": [ + 0.8043490749800523, + 0.9971852622206079, + 0.5714557550631628, + 0.43932677046767354, + 0.20723672527039427, + 0.9165298060172561, + 0.11361823275193217, + 0.06220918934993902, + 0.7371214193751683, + 0.5955348363282316 + ], + "No change": [ + 0.9706188078942934, + 0.6065174865789142, + 0.5462300441463859, + 0.5826650727470118, + 0.32143295554545914, + 0.035573952811012055, + 0.8348504493329046, + 0.29290741513514607, + 0.9969057545760365, + 0.6516121773992284 + ], + "Lose less than 5%": [ + 0.20026142506124045, + 0.20177274377541365, + 0.43881418861912547, + 0.49193865833334016, + 0.2190615044625175, + 0.44350210762460507, + 0.6474356568552584, + 0.4278369309831196, + 0.21571977808013343, + 0.18771009170748554 + ], + "Lose more than 5%": [ + 0.03680596690173188, + 0.25338737847200865, + 0.5256771386270633, + 0.7723155932982761, + 0.41713471613607933, + 0.261687242550416, + 0.3250140700584182, + 0.8910254979732124, + 0.3145167050163761, + 0.11685600869782797 + ] + }, + "all": { + "Gain more than 5%": 0.5697090059739505, + "Gain less than 5%": 0.9627552174102675, + "No change": 0.6529674578754117, + "Lose less than 5%": 0.8708981110964545, + "Lose more than 5%": 0.7173524703437558 + } + }, + "wealth_decile": null, + "intra_wealth_decile": null, + "labor_supply_response": null, + "constituency_impact": null, + "local_authority_impact": null, + "congressional_district_impact": null, + "cliff_impact": null +} diff --git a/libs/policyengine-simulation-persistence/tests/fixtures/economy_results/us_congressional_district_ca_12_2026.json b/libs/policyengine-simulation-persistence/tests/fixtures/economy_results/us_congressional_district_ca_12_2026.json new file mode 100644 index 000000000..afc1a5003 --- /dev/null +++ b/libs/policyengine-simulation-persistence/tests/fixtures/economy_results/us_congressional_district_ca_12_2026.json @@ -0,0 +1,301 @@ +{ + "spm_provenance": { + "schema_version": "canonical-spm-comparison-v2", + "baseline": { + "receipt": { + "schema_version": "canonical-spm-provenance-v2", + "forecast_id": "spm-forecast-2022-2036", + "forecast_sha256": "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef", + "scenario": "central", + "geography_kind": "county", + "geography_id": null, + "county_vintage": "2020", + "as_of": null, + "years": [ + "2026" + ], + "runtime_versions": { + "policyengine": "6.10.0", + "policyengine-core": "3.20.0", + "policyengine-us": "1.715.2", + "spm-calculator": "0.4.1" + } + }, + "execution_count": 2 + }, + "reform": { + "receipt": { + "schema_version": "canonical-spm-provenance-v2", + "forecast_id": "spm-forecast-2022-2036", + "forecast_sha256": "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef", + "scenario": "central", + "geography_kind": "county", + "geography_id": null, + "county_vintage": "2020", + "as_of": null, + "years": [ + "2026" + ], + "runtime_versions": { + "policyengine": "6.10.0", + "policyengine-core": "3.20.0", + "policyengine-us": "1.715.2", + "spm-calculator": "0.4.1" + } + }, + "execution_count": 2 + } + }, + "model_version": "1.715.2", + "data_version": "1.115.5", + "budget": { + "tax_revenue_impact": 8845845059.19037, + "state_tax_revenue_impact": -260089666.9038415, + "benefit_spending_impact": 20784007719.238895, + "budgetary_impact": -52407074581.62173, + "households": 132514406.08216108, + "baseline_net_income": 11131057718479.627 + }, + "detailed_budget": { + "income_tax": { + "baseline": -973664016.8902518, + "reform": 674938164.19292, + "difference": -481291971.3439847 + }, + "snap": { + "baseline": -531338077.9066073, + "reform": 991289671.0209255, + "difference": -59472984.95510411 + }, + "eitc": { + "baseline": 672922902.5487775, + "reform": -47293582.601330094, + "difference": 278136281.0883239 + }, + "ctc": { + "baseline": -698767151.9529521, + "reform": 269721316.5703769, + "difference": 736090614.2865936 + }, + "ssi": { + "baseline": 46362420.76660269, + "reform": 482503712.4029805, + "difference": 342822950.7391851 + }, + "state_income_tax": { + "baseline": -871937123.5460054, + "reform": 516460492.5736347, + "difference": 182199165.8626352 + } + }, + "decile": { + "average": { + "1": -1192.394042905726, + "2": -2813.9294911815, + "3": 2193.1634218736735, + "4": -163.505468007199, + "5": 1312.9435443948184, + "6": 2272.87680153289, + "7": 1284.7769016672153, + "8": 2526.592005503247, + "9": -630.2195759955365, + "10": 1805.4526259113698 + }, + "relative": { + "1": -0.0, + "2": 0.0, + "3": -3.5e-9, + "4": -3.5e-9, + "5": 1e-12, + "6": -3.5e-9, + "7": 0.5740227352895624, + "8": 0.5850741074053635, + "9": 1e-12, + "10": 0.0 + } + }, + "inequality": { + "gini": { + "baseline": 0.8564005663967557, + "reform": 0.9909896448688151 + }, + "top_10_pct_share": { + "baseline": 0.6712735421625182, + "reform": 0.16309962197106975 + }, + "top_1_pct_share": { + "baseline": 0.8606375331162682, + "reform": 0.9646329473090614 + } + }, + "poverty": { + "poverty": { + "child": { + "baseline": 0.9046959845122367, + "reform": 0.5691075034743235 + }, + "adult": { + "baseline": 0.7138170201741992, + "reform": 0.2111249836755983 + }, + "senior": { + "baseline": 0.8316079302733542, + "reform": 0.5735323523512847 + }, + "all": { + "baseline": 0.2849574619862052, + "reform": 0.06346057714522935 + } + }, + "deep_poverty": { + "child": { + "baseline": 0.8539424884226802, + "reform": 0.9898060149215813 + }, + "adult": { + "baseline": 0.08851809310972836, + "reform": 0.8005953212575019 + }, + "senior": { + "baseline": 0.41046182734590886, + "reform": 0.15076537445280958 + }, + "all": { + "baseline": 0.2938912468190622, + "reform": 0.7687918872773446 + } + } + }, + "poverty_by_gender": { + "poverty": { + "male": { + "baseline": 0.8727670246282013, + "reform": 0.04419006112954338 + }, + "female": { + "baseline": 0.6145325285318086, + "reform": 0.0449402434960362 + } + }, + "deep_poverty": { + "male": { + "baseline": 0.7184404774485162, + "reform": 0.3309541460190075 + }, + "female": { + "baseline": 0.880905307247358, + "reform": 0.9806357568433396 + } + } + }, + "poverty_by_race": { + "poverty": { + "white": { + "baseline": 0.505420373648044, + "reform": 0.9985089453757765 + }, + "black": { + "baseline": 0.309670053476339, + "reform": 0.0769707047054119 + }, + "hispanic": { + "baseline": 0.5997628087966007, + "reform": 0.031377762175317736 + }, + "other": { + "baseline": 0.1973848564284194, + "reform": 0.4079361356169908 + } + } + }, + "intra_decile": { + "deciles": { + "Gain more than 5%": [ + 0.6104671229673415, + 0.15619899101356471, + 0.04243582472120422, + 0.8677790339277224, + 0.3138305199160917, + 0.958659426408455, + 0.8966596414276016, + 0.3777892394121827, + 0.46040963284590475, + 0.5200729845925639 + ], + "Gain less than 5%": [ + 0.6438887183877269, + 0.5956502384019705, + 0.5592610620153905, + 0.620126135445262, + 0.9406212554239632, + 0.5070268159456598, + 0.43119155343093274, + 0.7203112521441384, + 0.23763561946478406, + 0.3010868611741494 + ], + "No change": [ + 0.9777973164486353, + 0.521127293281206, + 0.5484304676868622, + 0.01145748636421906, + 0.415210343803882, + 0.5799652137970656, + 0.020052890304599336, + 0.6157979413062568, + 0.6321805352961154, + 0.060080510627723016 + ], + "Lose less than 5%": [ + 0.627341109010956, + 0.4662504296967078, + 0.6792813980381086, + 0.35257698304104734, + 0.706950249365899, + 0.7380342892520343, + 0.02218246899080989, + 0.06057680364579732, + 0.6760203094873768, + 0.9633055803862574 + ], + "Lose more than 5%": [ + 0.2511222781834702, + 0.45631212963637924, + 0.5926718756664892, + 0.32002538574800654, + 0.3639550893399569, + 0.3126706611969108, + 0.36915397527695404, + 0.5956215058575365, + 0.3004039733655893, + 0.37716034132891685 + ] + }, + "all": { + "Gain more than 5%": 0.772273412444121, + "Gain less than 5%": 0.02692120500933004, + "No change": 0.5692580020705822, + "Lose less than 5%": 0.7351731816785095, + "Lose more than 5%": 0.310016695410093 + } + }, + "wealth_decile": null, + "intra_wealth_decile": null, + "labor_supply_response": null, + "constituency_impact": null, + "local_authority_impact": null, + "congressional_district_impact": { + "districts": [ + { + "district": "CA-01", + "average_household_income_change": -1950.8870104080981, + "relative_household_income_change": -3.5e-9, + "winner_percentage": 0.14085523548621137, + "loser_percentage": 0.04326821221926003, + "no_change_percentage": 0.9502674871120121, + "population": 1070424.2919654003 + } + ] + }, + "cliff_impact": null +} diff --git a/libs/policyengine-simulation-persistence/tests/fixtures/economy_results/us_national_2026.json b/libs/policyengine-simulation-persistence/tests/fixtures/economy_results/us_national_2026.json new file mode 100644 index 000000000..21c4fa9e3 --- /dev/null +++ b/libs/policyengine-simulation-persistence/tests/fixtures/economy_results/us_national_2026.json @@ -0,0 +1,4295 @@ +{ + "spm_provenance": { + "schema_version": "canonical-spm-comparison-v2", + "baseline": { + "receipt": { + "schema_version": "canonical-spm-provenance-v2", + "forecast_id": "spm-forecast-2022-2036", + "forecast_sha256": "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef", + "scenario": "central", + "geography_kind": "county", + "geography_id": null, + "county_vintage": "2020", + "as_of": null, + "years": [ + "2026" + ], + "runtime_versions": { + "policyengine": "6.10.0", + "policyengine-core": "3.20.0", + "policyengine-us": "1.715.2", + "spm-calculator": "0.4.1" + } + }, + "execution_count": 2 + }, + "reform": { + "receipt": { + "schema_version": "canonical-spm-provenance-v2", + "forecast_id": "spm-forecast-2022-2036", + "forecast_sha256": "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef", + "scenario": "central", + "geography_kind": "county", + "geography_id": null, + "county_vintage": "2020", + "as_of": null, + "years": [ + "2026" + ], + "runtime_versions": { + "policyengine": "6.10.0", + "policyengine-core": "3.20.0", + "policyengine-us": "1.715.2", + "spm-calculator": "0.4.1" + } + }, + "execution_count": 2 + } + }, + "model_version": "1.715.2", + "data_version": "1.115.5", + "budget": { + "tax_revenue_impact": 69486747387.44653, + "state_tax_revenue_impact": 527549237.95322806, + "benefit_spending_impact": -48986194852.11566, + "budgetary_impact": -73127151177.51976, + "households": 129908701.74183881, + "baseline_net_income": 11898982129577.477 + }, + "detailed_budget": { + "income_tax": { + "baseline": 303185945.4455259, + "reform": 577446702.2710264, + "difference": -812280826.4515302 + }, + "snap": { + "baseline": -943305046.9559873, + "reform": 671530207.8397393, + "difference": -134465864.18989325 + }, + "eitc": { + "baseline": 524560164.91588396, + "reform": -995787893.2977786, + "difference": -109225611.89039715 + }, + "ctc": { + "baseline": 443080064.6815651, + "reform": -542475557.4590948, + "difference": 890541391.1078446 + }, + "ssi": { + "baseline": 802854915.2229671, + "reform": -938820033.9328929, + "difference": -949108278.0130785 + }, + "state_income_tax": { + "baseline": 82824945.58699316, + "reform": 878298325.5570211, + "difference": -237591524.62357512 + } + }, + "decile": { + "average": { + "1": -1700.4036172163196, + "2": -467.3005465036961, + "3": -2825.7552745507924, + "4": -1669.8500023617896, + "5": -372.67443809656766, + "6": -25.126551708896105, + "7": -1601.4932984545642, + "8": -1614.8007507540942, + "9": -1687.3137759738684, + "10": -242.37920557359848 + }, + "relative": { + "1": 0.0, + "2": 0.4161799388943461, + "3": 0.0, + "4": 1e-12, + "5": 1e-12, + "6": 0.8955753946414917, + "7": -3.5e-9, + "8": -0.0, + "9": 0.3033685109329176, + "10": -3.5e-9 + } + }, + "inequality": { + "gini": { + "baseline": 0.8461974184283128, + "reform": 0.5052838205796004 + }, + "top_10_pct_share": { + "baseline": 0.5890022579825517, + "reform": 0.034525830151341586 + }, + "top_1_pct_share": { + "baseline": 0.24273997354306764, + "reform": 0.7974042475543028 + } + }, + "poverty": { + "poverty": { + "child": { + "baseline": 0.4143139993007743, + "reform": 0.17300740157905092 + }, + "adult": { + "baseline": 0.548798761388153, + "reform": 0.7030407620656315 + }, + "senior": { + "baseline": 0.6744858305023272, + "reform": 0.3747030205016403 + }, + "all": { + "baseline": 0.4389616300445631, + "reform": 0.5084264882499818 + } + }, + "deep_poverty": { + "child": { + "baseline": 0.7784426150001458, + "reform": 0.5209384176131452 + }, + "adult": { + "baseline": 0.39325509496422606, + "reform": 0.4896935204622582 + }, + "senior": { + "baseline": 0.029574963966907064, + "reform": 0.04348729035652743 + }, + "all": { + "baseline": 0.703382088603836, + "reform": 0.9831877173096739 + } + } + }, + "poverty_by_gender": { + "poverty": { + "male": { + "baseline": 0.5931837303800576, + "reform": 0.393599686377914 + }, + "female": { + "baseline": 0.17034919685568128, + "reform": 0.5022385584334831 + } + }, + "deep_poverty": { + "male": { + "baseline": 0.9820766375385342, + "reform": 0.7705231398308006 + }, + "female": { + "baseline": 0.5396174484497788, + "reform": 0.8602897789205496 + } + } + }, + "poverty_by_race": { + "poverty": { + "white": { + "baseline": 0.23217612806301458, + "reform": 0.513771663187637 + }, + "black": { + "baseline": 0.9524673882682695, + "reform": 0.5777948078012031 + }, + "hispanic": { + "baseline": 0.45913173191066836, + "reform": 0.2692794774414212 + }, + "other": { + "baseline": 0.5479963094662489, + "reform": 0.9571162814602269 + } + } + }, + "intra_decile": { + "deciles": { + "Gain more than 5%": [ + 0.005709129450392925, + 0.7836552326153898, + 0.8204859119254819, + 0.8861795808260082, + 0.7405034118331963, + 0.8091399008724796, + 0.518678283523002, + 0.561357864778379, + 0.4260906796881502, + 0.05612329752074041 + ], + "Gain less than 5%": [ + 0.8700101551766398, + 0.5699993338763802, + 0.19983942017714307, + 0.5047204674288633, + 0.48492511222773416, + 0.3567899645449557, + 0.3460779190181549, + 0.5384787957378443, + 0.6234894527975051, + 0.6124524647827256 + ], + "No change": [ + 0.4581468000997244, + 0.027974984083842358, + 0.22960503127702392, + 0.1772112589385827, + 0.5844608707784413, + 0.8610088608533248, + 0.798438940577426, + 0.7970975626354962, + 0.8164373705606909, + 0.25529404008730594 + ], + "Lose less than 5%": [ + 0.841744832274096, + 0.6731135254387071, + 0.08323413780389788, + 0.0166906301155596, + 0.014559974924812313, + 0.7555867752521982, + 0.2495592256534228, + 0.10948862729435938, + 0.6248020841524763, + 0.3444228640964949 + ], + "Lose more than 5%": [ + 0.06951537853084733, + 0.1596255246938475, + 0.5273803990480128, + 0.16814494622242826, + 0.2729144368186801, + 0.7115899271852729, + 0.4547016300456639, + 0.3220017663873259, + 0.4737710141702789, + 0.023634577631987064 + ] + }, + "all": { + "Gain more than 5%": 0.38655710476146987, + "Gain less than 5%": 0.4209186792090759, + "No change": 0.18803930475131292, + "Lose less than 5%": 0.10876169244541334, + "Lose more than 5%": 0.8998185003560202 + } + }, + "wealth_decile": null, + "intra_wealth_decile": null, + "labor_supply_response": { + "substitution_lsr": -95240892.98036276, + "income_lsr": 119544772.1609919, + "relative_lsr": { + "income": -3.5e-9, + "substitution": 0.45183232059956535 + }, + "total_change": -620195937.3852562, + "revenue_change": 607800625.4420971, + "decile": { + "average": { + "income": { + "1": -48.473527582247435, + "2": 227.91766811872827, + "3": -627.6526288073741, + "4": -106.8136944860032, + "5": -716.4097414810877, + "6": 77.387017155357, + "7": 780.7609840249787, + "8": 268.905565766697, + "9": 190.8730116813393, + "10": -207.68004708353027 + }, + "substitution": { + "1": -94.01026883836794, + "2": 477.83176028076844, + "3": 300.1419478281451, + "4": 246.25690303743974, + "5": 663.4032506999561, + "6": -873.6701598830357, + "7": -928.6944390802345, + "8": 759.1299450687021, + "9": 199.23616990570105, + "10": 556.2168130864866 + } + }, + "relative": { + "income": { + "1": -347.4132949034705, + "2": 181.91888693611503, + "3": -609.3572449814661, + "4": -532.7087247328207, + "5": -411.69685870747054, + "6": -990.8124556772482, + "7": -830.022477249356, + "8": 309.60327801351093, + "9": -186.4425242296428, + "10": 102.53547125595253 + }, + "substitution": { + "1": 863.3704459699325, + "2": -833.5930450587033, + "3": -492.01051421050425, + "4": 515.9800980935379, + "5": 25.769282714127595, + "6": -940.4961754348353, + "7": 126.28452131581125, + "8": -784.146168822053, + "9": -784.3937896701154, + "10": -418.1942137105237 + } + } + }, + "hours": { + "baseline": -8663469857.26917, + "reform": -9662190549.476479, + "change": 3697949.498973032, + "income_effect": -5729966.430408149, + "substitution_effect": 8540842.966775883 + } + }, + "constituency_impact": null, + "local_authority_impact": null, + "congressional_district_impact": { + "districts": [ + { + "district": "AL-01", + "average_household_income_change": -101.7172852458077, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.14260035292536777, + "loser_percentage": 0.01086044309006795, + "no_change_percentage": 0.3747544920633644, + "population": 548096.2789566629 + }, + { + "district": "AL-02", + "average_household_income_change": 1241.3922089403352, + "relative_household_income_change": 0.6905926530386846, + "winner_percentage": 0.22764436571441626, + "loser_percentage": 0.0016658802428921593, + "no_change_percentage": 0.6242328818537503, + "population": 1956080.890298706 + }, + { + "district": "AL-03", + "average_household_income_change": -529.378558329722, + "relative_household_income_change": -0.0, + "winner_percentage": 0.05882432741086607, + "loser_percentage": 0.8188201278420804, + "no_change_percentage": 0.07460963363587747, + "population": 1373891.0081870835 + }, + { + "district": "AL-04", + "average_household_income_change": -652.0016288329296, + "relative_household_income_change": 0.0, + "winner_percentage": 0.018604300312002775, + "loser_percentage": 0.06078469618896887, + "no_change_percentage": 0.9150336434099469, + "population": 1017851.832855403 + }, + { + "district": "AL-05", + "average_household_income_change": -1636.0880437656667, + "relative_household_income_change": -3.5e-9, + "winner_percentage": 0.11252763614702643, + "loser_percentage": 0.4232066122540936, + "no_change_percentage": 0.13506950094916403, + "population": 625081.3883845364 + }, + { + "district": "AL-06", + "average_household_income_change": 485.807793085729, + "relative_household_income_change": 0.0, + "winner_percentage": 0.5551503462434865, + "loser_percentage": 0.5072476701117876, + "no_change_percentage": 0.0836027964988253, + "population": 1214877.9991096288 + }, + { + "district": "AL-07", + "average_household_income_change": 672.5957273236207, + "relative_household_income_change": 0.46959011611914814, + "winner_percentage": 0.38458139107487466, + "loser_percentage": 0.030494381790816316, + "no_change_percentage": 0.7263274273474801, + "population": 1934917.7657345892 + }, + { + "district": "AK-01", + "average_household_income_change": 1905.2150782139736, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.9410878223413865, + "loser_percentage": 0.8661318249263946, + "no_change_percentage": 0.38559418673644075, + "population": 619805.2333866417 + }, + { + "district": "AZ-01", + "average_household_income_change": -990.4892374583359, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.5113505018743109, + "loser_percentage": 0.8101070729276686, + "no_change_percentage": 0.5000121234313284, + "population": 56286.53438263037 + }, + { + "district": "AZ-02", + "average_household_income_change": 1290.2704733337002, + "relative_household_income_change": 0.43015437597568906, + "winner_percentage": 0.025740945504366897, + "loser_percentage": 0.675654354894482, + "no_change_percentage": 0.043483476253197484, + "population": 408810.50783274416 + }, + { + "district": "AZ-03", + "average_household_income_change": 429.15350504556795, + "relative_household_income_change": -0.0, + "winner_percentage": 0.17804952768967286, + "loser_percentage": 0.6958955397739035, + "no_change_percentage": 0.03684608961256153, + "population": 553095.2587470373 + }, + { + "district": "AZ-04", + "average_household_income_change": -623.286050496465, + "relative_household_income_change": 0.0, + "winner_percentage": 0.5140179727916571, + "loser_percentage": 0.36830555803174847, + "no_change_percentage": 0.3396596259019955, + "population": 911261.5805307392 + }, + { + "district": "AZ-05", + "average_household_income_change": 787.7910720928934, + "relative_household_income_change": -0.0, + "winner_percentage": 0.9558918773273261, + "loser_percentage": 0.1675630022937611, + "no_change_percentage": 0.924249742544119, + "population": 728385.5554744796 + }, + { + "district": "AZ-06", + "average_household_income_change": -1243.0708775985843, + "relative_household_income_change": 0.7485277743628934, + "winner_percentage": 0.006674252060786756, + "loser_percentage": 0.2682540484924081, + "no_change_percentage": 0.7706727594239515, + "population": 683579.4773629309 + }, + { + "district": "AZ-07", + "average_household_income_change": -1033.6530865744967, + "relative_household_income_change": 0.0, + "winner_percentage": 0.2475557298889539, + "loser_percentage": 0.11605849850039973, + "no_change_percentage": 0.3609521686918671, + "population": 1093124.59086775 + }, + { + "district": "AZ-08", + "average_household_income_change": -1380.7734243896737, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.6394110628821505, + "loser_percentage": 0.22951422470938387, + "no_change_percentage": 0.5272370763287079, + "population": 954776.9947312413 + }, + { + "district": "AZ-09", + "average_household_income_change": 508.0174015085941, + "relative_household_income_change": -3.5e-9, + "winner_percentage": 0.8943184147686908, + "loser_percentage": 0.16214764452574437, + "no_change_percentage": 0.291321379072099, + "population": 1746339.202612584 + }, + { + "district": "AR-01", + "average_household_income_change": -886.7798349260943, + "relative_household_income_change": 0.9439036612373847, + "winner_percentage": 0.6402315474746479, + "loser_percentage": 0.44509850222390723, + "no_change_percentage": 0.7921069280361347, + "population": 1468015.1981863473 + }, + { + "district": "AR-02", + "average_household_income_change": 83.92200633709423, + "relative_household_income_change": 0.0, + "winner_percentage": 0.694104723835435, + "loser_percentage": 0.13173181234315456, + "no_change_percentage": 0.8864370231764853, + "population": 840645.7027551291 + }, + { + "district": "AR-03", + "average_household_income_change": -1035.0756287494755, + "relative_household_income_change": 0.0, + "winner_percentage": 0.559931781666012, + "loser_percentage": 0.6247386687904641, + "no_change_percentage": 0.919934108379581, + "population": 1923975.397019315 + }, + { + "district": "AR-04", + "average_household_income_change": 1041.737170195717, + "relative_household_income_change": 0.4176558064756952, + "winner_percentage": 0.09287217930675717, + "loser_percentage": 0.4047303109558881, + "no_change_percentage": 0.19899172023060585, + "population": 1113857.468180032 + }, + { + "district": "CA-01", + "average_household_income_change": 1920.0493803164393, + "relative_household_income_change": -3.5e-9, + "winner_percentage": 0.5633272391626525, + "loser_percentage": 0.017112014359287886, + "no_change_percentage": 0.7101313185350905, + "population": 1807612.6580073712 + }, + { + "district": "CA-02", + "average_household_income_change": 1190.9251224377977, + "relative_household_income_change": -3.5e-9, + "winner_percentage": 0.5349338144076542, + "loser_percentage": 0.7891161659884908, + "no_change_percentage": 0.379471337738705, + "population": 196587.60294740985 + }, + { + "district": "CA-03", + "average_household_income_change": -587.3232427555886, + "relative_household_income_change": 0.3121132200263218, + "winner_percentage": 0.49172302053949546, + "loser_percentage": 0.6111343735808167, + "no_change_percentage": 0.21191451351534507, + "population": 1198005.299279376 + }, + { + "district": "CA-04", + "average_household_income_change": 716.4863465475145, + "relative_household_income_change": 0.0, + "winner_percentage": 0.40688231107412964, + "loser_percentage": 0.32359317751493566, + "no_change_percentage": 0.6852808172439641, + "population": 283617.2683020191 + }, + { + "district": "CA-05", + "average_household_income_change": -1637.850054481115, + "relative_household_income_change": -0.0, + "winner_percentage": 0.7596269971014065, + "loser_percentage": 0.6593931588317239, + "no_change_percentage": 0.934706631571226, + "population": 731208.9827030475 + }, + { + "district": "CA-06", + "average_household_income_change": -1881.0388383520524, + "relative_household_income_change": -3.5e-9, + "winner_percentage": 0.48537066712505683, + "loser_percentage": 0.056666014100585804, + "no_change_percentage": 0.5942091818248112, + "population": 913910.6011144014 + }, + { + "district": "CA-07", + "average_household_income_change": 1537.1464588478023, + "relative_household_income_change": -0.0, + "winner_percentage": 0.007724418967058444, + "loser_percentage": 0.36031096701684984, + "no_change_percentage": 0.27969295418847406, + "population": 402670.9003519397 + }, + { + "district": "CA-08", + "average_household_income_change": -270.1820046885661, + "relative_household_income_change": -0.0, + "winner_percentage": 0.501034557094322, + "loser_percentage": 0.6980941469409674, + "no_change_percentage": 0.16234615818193077, + "population": 929260.2895029439 + }, + { + "district": "CA-09", + "average_household_income_change": 426.12124982149214, + "relative_household_income_change": -0.0, + "winner_percentage": 0.46017155393683884, + "loser_percentage": 0.7854393337281037, + "no_change_percentage": 0.04923914247505368, + "population": 1544560.3762195243 + }, + { + "district": "CA-10", + "average_household_income_change": -369.84459942607907, + "relative_household_income_change": -3.5e-9, + "winner_percentage": 0.5214095761879433, + "loser_percentage": 0.4399166678136097, + "no_change_percentage": 0.052247836980488294, + "population": 212633.49881591904 + }, + { + "district": "CA-11", + "average_household_income_change": 281.6506827110996, + "relative_household_income_change": 0.0, + "winner_percentage": 0.32226459514400096, + "loser_percentage": 0.49990018379463286, + "no_change_percentage": 0.3608400868813272, + "population": 614394.250070395 + }, + { + "district": "CA-12", + "average_household_income_change": -1456.3521600642657, + "relative_household_income_change": 0.2256742626495376, + "winner_percentage": 0.134494187324123, + "loser_percentage": 0.49460694973104014, + "no_change_percentage": 0.4290896639496672, + "population": 729571.0039977863 + }, + { + "district": "CA-13", + "average_household_income_change": -365.9226317365758, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.3890777290830446, + "loser_percentage": 0.8730978577541066, + "no_change_percentage": 0.8972224563897103, + "population": 641934.4119458575 + }, + { + "district": "CA-14", + "average_household_income_change": -1496.642820259904, + "relative_household_income_change": 0.64094436192942, + "winner_percentage": 0.7960876508380115, + "loser_percentage": 0.3784190372558184, + "no_change_percentage": 0.4238353268638516, + "population": 1316958.22273491 + }, + { + "district": "CA-15", + "average_household_income_change": -640.6313059657078, + "relative_household_income_change": -3.5e-9, + "winner_percentage": 0.38465022995985754, + "loser_percentage": 0.3995515988373419, + "no_change_percentage": 0.807182492186913, + "population": 339653.4441229799 + }, + { + "district": "CA-16", + "average_household_income_change": -1179.6415497140028, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.5227510622715033, + "loser_percentage": 0.052923693272417416, + "no_change_percentage": 0.8353954006210182, + "population": 1747067.9393701318 + }, + { + "district": "CA-17", + "average_household_income_change": 1284.5950041837382, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.7708073492145247, + "loser_percentage": 0.8589537357187278, + "no_change_percentage": 0.31103929007826037, + "population": 1745340.4845477268 + }, + { + "district": "CA-18", + "average_household_income_change": 996.0133397522277, + "relative_household_income_change": 0.8595428617640705, + "winner_percentage": 0.3084141838742047, + "loser_percentage": 0.012955567317396666, + "no_change_percentage": 0.17104269709747133, + "population": 326517.4209606851 + }, + { + "district": "CA-19", + "average_household_income_change": 863.3173647119321, + "relative_household_income_change": -0.0, + "winner_percentage": 0.9815326644782767, + "loser_percentage": 0.7734976508614569, + "no_change_percentage": 0.546164705322463, + "population": 43443.39082932053 + }, + { + "district": "CA-20", + "average_household_income_change": 1643.211636016627, + "relative_household_income_change": -3.5e-9, + "winner_percentage": 0.5362462043780879, + "loser_percentage": 0.4484523393074651, + "no_change_percentage": 0.5275703669056998, + "population": 1302992.286184724 + }, + { + "district": "CA-21", + "average_household_income_change": 1202.8325019108204, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.46729097780509044, + "loser_percentage": 0.634066252711196, + "no_change_percentage": 0.3884791199329697, + "population": 829737.1997349036 + }, + { + "district": "CA-22", + "average_household_income_change": 66.62941062963812, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.020535945332515126, + "loser_percentage": 0.1550549007322337, + "no_change_percentage": 0.7571143646203627, + "population": 732875.0445007881 + }, + { + "district": "CA-23", + "average_household_income_change": -1587.8683043620656, + "relative_household_income_change": -3.5e-9, + "winner_percentage": 0.5487682328065107, + "loser_percentage": 0.9626410648799001, + "no_change_percentage": 0.3749766852995049, + "population": 143596.87028899114 + }, + { + "district": "CA-24", + "average_household_income_change": 1667.4429514798517, + "relative_household_income_change": -0.0, + "winner_percentage": 0.1081431390573181, + "loser_percentage": 0.08424475644417895, + "no_change_percentage": 0.05643113581015269, + "population": 16805.930927915848 + }, + { + "district": "CA-25", + "average_household_income_change": -1001.9043376747802, + "relative_household_income_change": 0.11317412321718456, + "winner_percentage": 0.6158127630016563, + "loser_percentage": 0.9656566882560107, + "no_change_percentage": 0.9605179179485582, + "population": 1493449.8495685991 + }, + { + "district": "CA-26", + "average_household_income_change": 1798.4606020938431, + "relative_household_income_change": -0.0, + "winner_percentage": 0.5870715001683793, + "loser_percentage": 0.8033802842755158, + "no_change_percentage": 0.6292175442471413, + "population": 921870.451521964 + }, + { + "district": "CA-27", + "average_household_income_change": -653.0806594029559, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.8001046273240519, + "loser_percentage": 0.39075730805975006, + "no_change_percentage": 0.6560261369262086, + "population": 674653.2909981434 + }, + { + "district": "CA-28", + "average_household_income_change": -1765.08349219778, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.14212089999151623, + "loser_percentage": 0.1224568853043495, + "no_change_percentage": 0.4855769544848747, + "population": 273398.3199164645 + }, + { + "district": "CA-29", + "average_household_income_change": -888.6998292046791, + "relative_household_income_change": 0.0, + "winner_percentage": 0.4824218931490709, + "loser_percentage": 0.7309984068579884, + "no_change_percentage": 0.8258033946553545, + "population": 1514596.9736237328 + }, + { + "district": "CA-30", + "average_household_income_change": -641.2184359421058, + "relative_household_income_change": -3.5e-9, + "winner_percentage": 0.34254197921430385, + "loser_percentage": 0.8894237400921909, + "no_change_percentage": 0.6355235318535916, + "population": 1239103.128934888 + }, + { + "district": "CA-31", + "average_household_income_change": -1742.6211467233204, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.6123986882300106, + "loser_percentage": 0.12683588146028657, + "no_change_percentage": 0.5409306560920599, + "population": 1904601.5656046001 + }, + { + "district": "CA-32", + "average_household_income_change": 979.7718608096169, + "relative_household_income_change": -3.5e-9, + "winner_percentage": 0.9908157296652765, + "loser_percentage": 0.1192586923916098, + "no_change_percentage": 0.586893637715749, + "population": 984877.5889400134 + }, + { + "district": "CA-33", + "average_household_income_change": -549.301011917969, + "relative_household_income_change": 0.15602356639396198, + "winner_percentage": 0.5771809315400935, + "loser_percentage": 0.37839441251537, + "no_change_percentage": 0.3098382754201858, + "population": 709689.0495239014 + }, + { + "district": "CA-34", + "average_household_income_change": 1990.247485523149, + "relative_household_income_change": 0.33035619514819015, + "winner_percentage": 0.5982952077680709, + "loser_percentage": 0.0711720822230778, + "no_change_percentage": 0.6246853947621606, + "population": 1778686.913921832 + }, + { + "district": "CA-35", + "average_household_income_change": 1761.4016628961574, + "relative_household_income_change": 0.6205345270569311, + "winner_percentage": 0.34989600523094433, + "loser_percentage": 0.9379414777595734, + "no_change_percentage": 0.2968685503029024, + "population": 664761.1110170053 + }, + { + "district": "CA-36", + "average_household_income_change": 630.1992727016485, + "relative_household_income_change": 0.3972508761498267, + "winner_percentage": 0.3285972226227972, + "loser_percentage": 0.5373940175300163, + "no_change_percentage": 0.8349531491962504, + "population": 1050973.0294520468 + }, + { + "district": "CA-37", + "average_household_income_change": 1462.2350111671283, + "relative_household_income_change": -3.5e-9, + "winner_percentage": 0.989549913187835, + "loser_percentage": 0.6737291687045169, + "no_change_percentage": 0.1715974717820693, + "population": 876524.1090736537 + }, + { + "district": "CA-38", + "average_household_income_change": -869.4282452112944, + "relative_household_income_change": -0.0, + "winner_percentage": 0.18770762679166875, + "loser_percentage": 0.2739483389115531, + "no_change_percentage": 0.12201087651538456, + "population": 424290.5019186154 + }, + { + "district": "CA-39", + "average_household_income_change": -1267.8231454240251, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.4584474945996394, + "loser_percentage": 0.9370204171804093, + "no_change_percentage": 0.3917403626543372, + "population": 930712.5864732913 + }, + { + "district": "CA-40", + "average_household_income_change": -562.3775341210342, + "relative_household_income_change": -0.0, + "winner_percentage": 0.23918997191071245, + "loser_percentage": 0.5260113238125497, + "no_change_percentage": 0.726498808599626, + "population": 1003126.5118603492 + }, + { + "district": "CA-41", + "average_household_income_change": 649.5470617907051, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.3552770048304683, + "loser_percentage": 0.30657120150850037, + "no_change_percentage": 0.024657019036375294, + "population": 1780674.3483204115 + }, + { + "district": "CA-42", + "average_household_income_change": 1159.5063296568303, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.902446400231012, + "loser_percentage": 0.15150610126548647, + "no_change_percentage": 0.8366777637624933, + "population": 841703.408616225 + }, + { + "district": "CA-43", + "average_household_income_change": -742.9544276215356, + "relative_household_income_change": -3.5e-9, + "winner_percentage": 0.8309765238449147, + "loser_percentage": 0.14219214804793068, + "no_change_percentage": 0.4530294918780535, + "population": 1062304.3523327063 + }, + { + "district": "CA-44", + "average_household_income_change": -1017.3755240887896, + "relative_household_income_change": 0.21079003156596632, + "winner_percentage": 0.3796624281418225, + "loser_percentage": 0.4902777918239447, + "no_change_percentage": 0.6012503437187471, + "population": 1865959.885605579 + }, + { + "district": "CA-45", + "average_household_income_change": -1415.5658531587014, + "relative_household_income_change": 0.22807510480238247, + "winner_percentage": 0.9096491728454665, + "loser_percentage": 0.9317969080573828, + "no_change_percentage": 0.5283844979134728, + "population": 734097.1646511267 + }, + { + "district": "CA-46", + "average_household_income_change": -1245.3931830569275, + "relative_household_income_change": 0.910627262349237, + "winner_percentage": 0.10830967717910556, + "loser_percentage": 0.23905658916176586, + "no_change_percentage": 0.034282621247537115, + "population": 1092646.3590046442 + }, + { + "district": "CA-47", + "average_household_income_change": -225.7024315421745, + "relative_household_income_change": 0.4894877420169603, + "winner_percentage": 0.18535651239951723, + "loser_percentage": 0.837768991053808, + "no_change_percentage": 0.8392587441699838, + "population": 1288153.679040642 + }, + { + "district": "CA-48", + "average_household_income_change": -256.17032345475496, + "relative_household_income_change": -3.5e-9, + "winner_percentage": 0.3840748545466999, + "loser_percentage": 0.841556693614585, + "no_change_percentage": 0.08498238084986265, + "population": 1092656.6410106996 + }, + { + "district": "CA-49", + "average_household_income_change": 1642.418280899994, + "relative_household_income_change": 0.45499419839442967, + "winner_percentage": 0.3996318991780353, + "loser_percentage": 0.00811283921494399, + "no_change_percentage": 0.5043576089482401, + "population": 830007.685726782 + }, + { + "district": "CA-50", + "average_household_income_change": -1434.719830025666, + "relative_household_income_change": 0.0, + "winner_percentage": 0.527748098058697, + "loser_percentage": 0.6223956665167715, + "no_change_percentage": 0.9904167675348735, + "population": 439734.6422016735 + }, + { + "district": "CA-51", + "average_household_income_change": -370.500854257362, + "relative_household_income_change": -3.5e-9, + "winner_percentage": 0.5242253175436219, + "loser_percentage": 0.7770367389890476, + "no_change_percentage": 0.67725832793819, + "population": 1738334.257700544 + }, + { + "district": "CA-52", + "average_household_income_change": 600.7036555406855, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.3466247177277443, + "loser_percentage": 0.6541914874562558, + "no_change_percentage": 0.8251537907311142, + "population": 229628.011221144 + }, + { + "district": "CO-01", + "average_household_income_change": 1230.9077125999916, + "relative_household_income_change": -0.0, + "winner_percentage": 0.134106127817758, + "loser_percentage": 0.9661923609934115, + "no_change_percentage": 0.5327523065182042, + "population": 354098.5665959717 + }, + { + "district": "CO-02", + "average_household_income_change": 1306.482550421162, + "relative_household_income_change": -0.0, + "winner_percentage": 0.83221204878799, + "loser_percentage": 0.01950485751610953, + "no_change_percentage": 0.14456465305764543, + "population": 916157.3733286823 + }, + { + "district": "CO-03", + "average_household_income_change": -177.2015481856779, + "relative_household_income_change": -0.0, + "winner_percentage": 0.8239581007636878, + "loser_percentage": 0.7509151623422733, + "no_change_percentage": 0.28541203910408686, + "population": 1511081.9751586048 + }, + { + "district": "CO-04", + "average_household_income_change": -265.2517793746414, + "relative_household_income_change": 0.0, + "winner_percentage": 0.9316170783510357, + "loser_percentage": 0.3549960878338857, + "no_change_percentage": 0.2925758443326615, + "population": 1226064.510495367 + }, + { + "district": "CO-05", + "average_household_income_change": -512.3692031236847, + "relative_household_income_change": 0.0, + "winner_percentage": 0.5662456475393759, + "loser_percentage": 0.5387945165631575, + "no_change_percentage": 0.5297979237287209, + "population": 1974517.8305325997 + }, + { + "district": "CO-06", + "average_household_income_change": 1619.0403702740514, + "relative_household_income_change": 0.2986875371903074, + "winner_percentage": 0.3151406134613959, + "loser_percentage": 0.9370034399542125, + "no_change_percentage": 0.05758881507922853, + "population": 636076.0962848675 + }, + { + "district": "CO-07", + "average_household_income_change": 1727.502898734149, + "relative_household_income_change": -0.0, + "winner_percentage": 0.8844145545487769, + "loser_percentage": 0.08739250868322412, + "no_change_percentage": 0.9585700859571149, + "population": 1219250.9647520587 + }, + { + "district": "CO-08", + "average_household_income_change": 971.9081053382092, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.9984189291863486, + "loser_percentage": 0.7792686301844646, + "no_change_percentage": 0.43725611432633693, + "population": 1822882.5088412128 + }, + { + "district": "CT-01", + "average_household_income_change": -733.4613699543544, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.6602848372615883, + "loser_percentage": 0.48001860008713937, + "no_change_percentage": 0.2037742723546132, + "population": 438639.2924348621 + }, + { + "district": "CT-02", + "average_household_income_change": -1730.1936797458893, + "relative_household_income_change": -3.5e-9, + "winner_percentage": 0.49352746379574675, + "loser_percentage": 0.8078484679181165, + "no_change_percentage": 0.16398700709907843, + "population": 404813.0910622814 + }, + { + "district": "CT-03", + "average_household_income_change": 1618.8458045691646, + "relative_household_income_change": -3.5e-9, + "winner_percentage": 0.7062977130428661, + "loser_percentage": 0.9848558991480393, + "no_change_percentage": 0.8456447938061156, + "population": 1355856.6590365525 + }, + { + "district": "CT-04", + "average_household_income_change": 361.44050009557515, + "relative_household_income_change": -3.5e-9, + "winner_percentage": 0.7172149080608088, + "loser_percentage": 0.98576729859634, + "no_change_percentage": 0.11465761960796195, + "population": 1300055.6738872197 + }, + { + "district": "CT-05", + "average_household_income_change": -1146.7188842352507, + "relative_household_income_change": 0.0, + "winner_percentage": 0.32802415989117717, + "loser_percentage": 0.987883939767343, + "no_change_percentage": 0.6841018084490844, + "population": 1033246.891060393 + }, + { + "district": "DE-01", + "average_household_income_change": -264.3914325460721, + "relative_household_income_change": -0.0, + "winner_percentage": 0.16889186920869248, + "loser_percentage": 0.8453652777791822, + "no_change_percentage": 0.5708336953080093, + "population": 358288.9534547711 + }, + { + "district": "DC-01", + "average_household_income_change": 308.59947634037167, + "relative_household_income_change": -0.0, + "winner_percentage": 0.7232746655069926, + "loser_percentage": 0.626121078335344, + "no_change_percentage": 0.6628708181544503, + "population": 86669.61242482299 + }, + { + "district": "FL-01", + "average_household_income_change": -112.59017197951904, + "relative_household_income_change": -0.0, + "winner_percentage": 0.15922019566186107, + "loser_percentage": 0.08851487828435323, + "no_change_percentage": 0.9383871813145351, + "population": 1217564.895666008 + }, + { + "district": "FL-02", + "average_household_income_change": 773.8733757136331, + "relative_household_income_change": -0.0, + "winner_percentage": 0.9285740031135886, + "loser_percentage": 0.9698970354758635, + "no_change_percentage": 0.7932385199454783, + "population": 1941585.7962708066 + }, + { + "district": "FL-03", + "average_household_income_change": 1574.4123838912917, + "relative_household_income_change": 0.5165645744583381, + "winner_percentage": 0.24757697079047203, + "loser_percentage": 0.8596539097339346, + "no_change_percentage": 0.260714167730137, + "population": 158112.12946288916 + }, + { + "district": "FL-04", + "average_household_income_change": -1348.045750010432, + "relative_household_income_change": 0.271839320032379, + "winner_percentage": 0.8783503813610679, + "loser_percentage": 0.6696400495589823, + "no_change_percentage": 0.42651065886229844, + "population": 82879.99705410458 + }, + { + "district": "FL-05", + "average_household_income_change": 1326.1189019811054, + "relative_household_income_change": -0.0, + "winner_percentage": 0.6302331792941935, + "loser_percentage": 0.7683230628258404, + "no_change_percentage": 0.5568693144833027, + "population": 1344401.3008842464 + }, + { + "district": "FL-06", + "average_household_income_change": 689.2957361718439, + "relative_household_income_change": 0.0, + "winner_percentage": 0.734240342177587, + "loser_percentage": 0.14068781884842652, + "no_change_percentage": 0.2989575457439484, + "population": 415235.8634614184 + }, + { + "district": "FL-07", + "average_household_income_change": -244.4070681592101, + "relative_household_income_change": 0.9214691498053794, + "winner_percentage": 0.8158466151929633, + "loser_percentage": 0.5105868144012156, + "no_change_percentage": 0.7931260265065381, + "population": 138135.2066096766 + }, + { + "district": "FL-08", + "average_household_income_change": -1346.2538446209026, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.9777477008113244, + "loser_percentage": 0.01067312919301644, + "no_change_percentage": 0.10743206798937299, + "population": 20020.80181001546 + }, + { + "district": "FL-09", + "average_household_income_change": 1039.002504622171, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.7211832505316047, + "loser_percentage": 0.11887451199230736, + "no_change_percentage": 0.6579935892283897, + "population": 338129.9739872749 + }, + { + "district": "FL-10", + "average_household_income_change": 380.0954758283601, + "relative_household_income_change": -3.5e-9, + "winner_percentage": 0.8237264751259077, + "loser_percentage": 0.783237713622185, + "no_change_percentage": 0.37165318391889746, + "population": 560149.8769812064 + }, + { + "district": "FL-11", + "average_household_income_change": -552.922874730938, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.27346908472699316, + "loser_percentage": 0.6961161667540838, + "no_change_percentage": 0.885445907248799, + "population": 513503.2501471353 + }, + { + "district": "FL-12", + "average_household_income_change": 1073.0994188497257, + "relative_household_income_change": 0.0, + "winner_percentage": 0.11962075594871358, + "loser_percentage": 0.4001913220232566, + "no_change_percentage": 0.15816280416066675, + "population": 876361.5777005955 + }, + { + "district": "FL-13", + "average_household_income_change": -4.45563556553763, + "relative_household_income_change": -3.5e-9, + "winner_percentage": 0.8852236546294064, + "loser_percentage": 0.7652657751329798, + "no_change_percentage": 0.3866405389602191, + "population": 134669.5287914708 + }, + { + "district": "FL-14", + "average_household_income_change": 1561.1667301797008, + "relative_household_income_change": 0.9666775774731736, + "winner_percentage": 0.4453773809085094, + "loser_percentage": 0.6875953301020271, + "no_change_percentage": 0.7446337852288136, + "population": 1652638.352648129 + }, + { + "district": "FL-15", + "average_household_income_change": -750.7834866353904, + "relative_household_income_change": -0.0, + "winner_percentage": 0.047040171938993014, + "loser_percentage": 0.873520383209386, + "no_change_percentage": 0.31531043718411744, + "population": 784895.5178367962 + }, + { + "district": "FL-16", + "average_household_income_change": -748.468167882268, + "relative_household_income_change": -0.0, + "winner_percentage": 0.9217627058581727, + "loser_percentage": 0.8034127881093197, + "no_change_percentage": 0.41369178988727084, + "population": 157895.94684732158 + }, + { + "district": "FL-17", + "average_household_income_change": -683.6432519853073, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.4622665515230927, + "loser_percentage": 0.35546866115783415, + "no_change_percentage": 0.309973778859606, + "population": 687355.3547359019 + }, + { + "district": "FL-18", + "average_household_income_change": -1567.9375428973196, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.19496632411823256, + "loser_percentage": 0.414156400672014, + "no_change_percentage": 0.2066105747818574, + "population": 1561995.0401522873 + }, + { + "district": "FL-19", + "average_household_income_change": 1929.3050462902315, + "relative_household_income_change": 0.0, + "winner_percentage": 0.7384347309102355, + "loser_percentage": 0.22676891304456437, + "no_change_percentage": 0.10882645138615277, + "population": 1968314.4360111654 + }, + { + "district": "FL-20", + "average_household_income_change": 738.0566493055829, + "relative_household_income_change": -0.0, + "winner_percentage": 0.02162699991270478, + "loser_percentage": 0.3689932192516341, + "no_change_percentage": 0.8564042008511202, + "population": 735483.202492574 + }, + { + "district": "FL-21", + "average_household_income_change": -1311.1095736131308, + "relative_household_income_change": 0.0, + "winner_percentage": 0.09085898731234521, + "loser_percentage": 0.0809758001730293, + "no_change_percentage": 0.7504106876231031, + "population": 704384.8907859478 + }, + { + "district": "FL-22", + "average_household_income_change": -88.06165501404539, + "relative_household_income_change": -0.0, + "winner_percentage": 0.7200803570245979, + "loser_percentage": 0.3373593868866339, + "no_change_percentage": 0.10096316178102516, + "population": 1477463.1731296738 + }, + { + "district": "FL-23", + "average_household_income_change": -779.9565957539163, + "relative_household_income_change": 0.0, + "winner_percentage": 0.02821889127456545, + "loser_percentage": 0.057384409391906255, + "no_change_percentage": 0.5136530379520321, + "population": 481440.7194824504 + }, + { + "district": "FL-24", + "average_household_income_change": -734.1701476158872, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.16571489383564586, + "loser_percentage": 0.42181229313837243, + "no_change_percentage": 0.4148364652968418, + "population": 144671.57912561274 + }, + { + "district": "FL-25", + "average_household_income_change": 1439.0123523600278, + "relative_household_income_change": 0.0, + "winner_percentage": 0.9847264132526234, + "loser_percentage": 0.0600499173398964, + "no_change_percentage": 0.8935094299991524, + "population": 1927505.4994544394 + }, + { + "district": "FL-26", + "average_household_income_change": 1112.7518063829727, + "relative_household_income_change": 0.5800136872358187, + "winner_percentage": 0.4817964173700803, + "loser_percentage": 0.853193681149301, + "no_change_percentage": 0.578356603109671, + "population": 1094981.2602417956 + }, + { + "district": "FL-27", + "average_household_income_change": -379.87702691171154, + "relative_household_income_change": 0.6281933650116516, + "winner_percentage": 0.00751791104830124, + "loser_percentage": 0.46553684601857914, + "no_change_percentage": 0.9720088938614151, + "population": 342727.5228511398 + }, + { + "district": "FL-28", + "average_household_income_change": 1893.5463200119464, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.5260196223449102, + "loser_percentage": 0.7269352285508964, + "no_change_percentage": 0.07248637234593225, + "population": 293197.241799674 + }, + { + "district": "GA-01", + "average_household_income_change": -1269.247954243442, + "relative_household_income_change": -0.0, + "winner_percentage": 0.4930499461266703, + "loser_percentage": 0.8119924059635303, + "no_change_percentage": 0.6451811151764774, + "population": 1743797.409884929 + }, + { + "district": "GA-02", + "average_household_income_change": 1944.5634662257744, + "relative_household_income_change": -3.5e-9, + "winner_percentage": 0.1637474833297795, + "loser_percentage": 0.9101331135824555, + "no_change_percentage": 0.8924927066636925, + "population": 1809722.0657042577 + }, + { + "district": "GA-03", + "average_household_income_change": 200.13903071021844, + "relative_household_income_change": -0.0, + "winner_percentage": 0.92450506566269, + "loser_percentage": 0.9839192343928617, + "no_change_percentage": 0.021287694151356895, + "population": 1855389.9606955382 + }, + { + "district": "GA-04", + "average_household_income_change": -1586.2380303510556, + "relative_household_income_change": 0.948824094584967, + "winner_percentage": 0.25648213147860555, + "loser_percentage": 0.7153116942268624, + "no_change_percentage": 0.5629683530630664, + "population": 904596.870184385 + }, + { + "district": "GA-05", + "average_household_income_change": 507.64950923949795, + "relative_household_income_change": 0.0, + "winner_percentage": 0.6951005281807577, + "loser_percentage": 0.005613476946991103, + "no_change_percentage": 0.6392093871665209, + "population": 1409873.9105898377 + }, + { + "district": "GA-06", + "average_household_income_change": 1466.3481151392882, + "relative_household_income_change": 0.5359969399876601, + "winner_percentage": 0.03130806345470605, + "loser_percentage": 0.7646033703967934, + "no_change_percentage": 0.5326925731859895, + "population": 1833778.2332628572 + }, + { + "district": "GA-07", + "average_household_income_change": -1894.2026823531771, + "relative_household_income_change": -3.5e-9, + "winner_percentage": 0.3840918648059817, + "loser_percentage": 0.6223416845764114, + "no_change_percentage": 0.029831920661660516, + "population": 893996.0575827288 + }, + { + "district": "GA-08", + "average_household_income_change": 1193.489638982387, + "relative_household_income_change": -0.0, + "winner_percentage": 0.3496351693543115, + "loser_percentage": 0.1995086740568508, + "no_change_percentage": 0.3990670077832993, + "population": 538851.1072021148 + }, + { + "district": "GA-09", + "average_household_income_change": 1705.0355266840365, + "relative_household_income_change": -3.5e-9, + "winner_percentage": 0.5578041016153189, + "loser_percentage": 0.6860369771120276, + "no_change_percentage": 0.20796258986036864, + "population": 489292.4891201653 + }, + { + "district": "GA-10", + "average_household_income_change": 1696.1171971869958, + "relative_household_income_change": -3.5e-9, + "winner_percentage": 0.6026795763876366, + "loser_percentage": 0.8750851361290138, + "no_change_percentage": 0.973836406000621, + "population": 385172.0208488181 + }, + { + "district": "GA-11", + "average_household_income_change": -1363.7847713726296, + "relative_household_income_change": 0.0, + "winner_percentage": 0.09165394883261968, + "loser_percentage": 0.5740776221964935, + "no_change_percentage": 0.43305379741901473, + "population": 1511611.7264460314 + }, + { + "district": "GA-12", + "average_household_income_change": -495.6398197756493, + "relative_household_income_change": -3.5e-9, + "winner_percentage": 0.5992307575882658, + "loser_percentage": 0.5502319596449463, + "no_change_percentage": 0.6098730762934008, + "population": 866752.5806505374 + }, + { + "district": "GA-13", + "average_household_income_change": 715.2380413264541, + "relative_household_income_change": -3.5e-9, + "winner_percentage": 0.4474572622702626, + "loser_percentage": 0.6793474774468349, + "no_change_percentage": 0.8072004938963492, + "population": 571649.1788765253 + }, + { + "district": "GA-14", + "average_household_income_change": -1179.6946454105735, + "relative_household_income_change": -3.5e-9, + "winner_percentage": 0.6158108831536124, + "loser_percentage": 0.8145916322268135, + "no_change_percentage": 0.08660852191797641, + "population": 1941243.7141759186 + }, + { + "district": "HI-01", + "average_household_income_change": 1422.2919651118193, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.30675674401692676, + "loser_percentage": 0.1487782451775993, + "no_change_percentage": 0.0101814912137137, + "population": 1922514.898091813 + }, + { + "district": "HI-02", + "average_household_income_change": 1561.1958715981639, + "relative_household_income_change": 0.4462215807781249, + "winner_percentage": 0.6107603943100495, + "loser_percentage": 0.043475700084457114, + "no_change_percentage": 0.3460879482288295, + "population": 1267120.312960441 + }, + { + "district": "ID-01", + "average_household_income_change": -1958.8201887857224, + "relative_household_income_change": 0.2775124877026566, + "winner_percentage": 0.9126213405124977, + "loser_percentage": 0.973963041712753, + "no_change_percentage": 0.49025534971259277, + "population": 269400.4299547344 + }, + { + "district": "ID-02", + "average_household_income_change": -39.28612547861299, + "relative_household_income_change": 0.9944174108151674, + "winner_percentage": 0.8003806250954807, + "loser_percentage": 0.9773639957690703, + "no_change_percentage": 0.10415293898520461, + "population": 909449.6274312991 + }, + { + "district": "IL-01", + "average_household_income_change": -742.5521383258542, + "relative_household_income_change": -3.5e-9, + "winner_percentage": 0.22288892351390233, + "loser_percentage": 0.9315611406686448, + "no_change_percentage": 0.5668338419436574, + "population": 1720931.9288024302 + }, + { + "district": "IL-02", + "average_household_income_change": 831.6869640152884, + "relative_household_income_change": -0.0, + "winner_percentage": 0.2967933749601812, + "loser_percentage": 0.13571963406036935, + "no_change_percentage": 0.832357673164309, + "population": 791041.6696110559 + }, + { + "district": "IL-03", + "average_household_income_change": -797.2436956244903, + "relative_household_income_change": -0.0, + "winner_percentage": 0.06490534314116103, + "loser_percentage": 0.7519750388599092, + "no_change_percentage": 0.06660901599496571, + "population": 377217.7807398747 + }, + { + "district": "IL-04", + "average_household_income_change": -1428.9377996776147, + "relative_household_income_change": -3.5e-9, + "winner_percentage": 0.12265122169157006, + "loser_percentage": 0.8518052170670675, + "no_change_percentage": 0.11059112619811418, + "population": 1160167.199854474 + }, + { + "district": "IL-05", + "average_household_income_change": 1836.659970776044, + "relative_household_income_change": -3.5e-9, + "winner_percentage": 0.5523320784858717, + "loser_percentage": 0.14139887426910824, + "no_change_percentage": 0.24547275396857648, + "population": 1925810.3730733125 + }, + { + "district": "IL-06", + "average_household_income_change": -1189.7986860261929, + "relative_household_income_change": -3.5e-9, + "winner_percentage": 0.17377762261537033, + "loser_percentage": 0.6797731681642427, + "no_change_percentage": 0.8520375232552789, + "population": 1203109.6925865589 + }, + { + "district": "IL-07", + "average_household_income_change": 1577.7835323325617, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.9000013013614059, + "loser_percentage": 0.45935866427942185, + "no_change_percentage": 0.4947185302278443, + "population": 539344.8345100002 + }, + { + "district": "IL-08", + "average_household_income_change": 1492.6037455260212, + "relative_household_income_change": 0.8647602261811477, + "winner_percentage": 0.19806932299158597, + "loser_percentage": 0.741758214164136, + "no_change_percentage": 0.1973706976064603, + "population": 1242894.371215378 + }, + { + "district": "IL-09", + "average_household_income_change": -1957.9202231447507, + "relative_household_income_change": 0.5767955919563806, + "winner_percentage": 0.5049045593188333, + "loser_percentage": 0.627906677936699, + "no_change_percentage": 0.11768377169617017, + "population": 915472.239240144 + }, + { + "district": "IL-10", + "average_household_income_change": 1134.101038401237, + "relative_household_income_change": 0.37314553166486586, + "winner_percentage": 0.5989421207757561, + "loser_percentage": 0.8079306184127111, + "no_change_percentage": 0.7389160850591271, + "population": 609919.9286527971 + }, + { + "district": "IL-11", + "average_household_income_change": 1276.4461081683498, + "relative_household_income_change": -3.5e-9, + "winner_percentage": 0.722586100687897, + "loser_percentage": 0.4047369019257887, + "no_change_percentage": 0.4875187991267902, + "population": 736190.8603408891 + }, + { + "district": "IL-12", + "average_household_income_change": -532.8141313249755, + "relative_household_income_change": 0.7093294285856272, + "winner_percentage": 0.34796286831592704, + "loser_percentage": 0.8753306159584747, + "no_change_percentage": 0.012947354199790873, + "population": 1882250.0880713076 + }, + { + "district": "IL-13", + "average_household_income_change": 299.88269945536985, + "relative_household_income_change": 0.0, + "winner_percentage": 0.3439412827291133, + "loser_percentage": 0.5127197856449134, + "no_change_percentage": 0.1306229711870046, + "population": 1296650.8797191768 + }, + { + "district": "IL-14", + "average_household_income_change": 1131.5001533207214, + "relative_household_income_change": -0.0, + "winner_percentage": 0.14414609199940498, + "loser_percentage": 0.6757638724127316, + "no_change_percentage": 0.7381168627632002, + "population": 1569660.962972421 + }, + { + "district": "IL-15", + "average_household_income_change": 30.82038680684196, + "relative_household_income_change": -0.0, + "winner_percentage": 0.8985201664466087, + "loser_percentage": 0.7166345684965276, + "no_change_percentage": 0.2767519988734092, + "population": 814190.5964516615 + }, + { + "district": "IL-16", + "average_household_income_change": -1653.123022446867, + "relative_household_income_change": 0.22451665861812453, + "winner_percentage": 0.8656914299923075, + "loser_percentage": 0.843313160737658, + "no_change_percentage": 0.6805555743171952, + "population": 995973.5312472819 + }, + { + "district": "IL-17", + "average_household_income_change": 953.972640733002, + "relative_household_income_change": -3.5e-9, + "winner_percentage": 0.4786241894978204, + "loser_percentage": 0.9012826937760073, + "no_change_percentage": 0.3547081545876839, + "population": 1402391.0197606967 + }, + { + "district": "IN-01", + "average_household_income_change": 70.96249182250335, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.5604255503804655, + "loser_percentage": 0.15983701084647672, + "no_change_percentage": 0.8607033798105205, + "population": 859789.5127165096 + }, + { + "district": "IN-02", + "average_household_income_change": 168.1599924637851, + "relative_household_income_change": -0.0, + "winner_percentage": 0.4693498350379831, + "loser_percentage": 0.8680105613452282, + "no_change_percentage": 0.5706545236591403, + "population": 767782.6765989842 + }, + { + "district": "IN-03", + "average_household_income_change": 1404.6936404954358, + "relative_household_income_change": 0.9259161295515774, + "winner_percentage": 0.4652944676602273, + "loser_percentage": 0.729817009920871, + "no_change_percentage": 0.9303847318216023, + "population": 1215597.6254804253 + }, + { + "district": "IN-04", + "average_household_income_change": 706.652772622924, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.5740192806288786, + "loser_percentage": 0.7826523228155402, + "no_change_percentage": 0.954839434574745, + "population": 242552.16058150108 + }, + { + "district": "IN-05", + "average_household_income_change": 1045.6028209384463, + "relative_household_income_change": -3.5e-9, + "winner_percentage": 0.38949969665516526, + "loser_percentage": 0.6257720740999431, + "no_change_percentage": 0.9185202262992922, + "population": 1414403.4565510713 + }, + { + "district": "IN-06", + "average_household_income_change": -1680.3948280650854, + "relative_household_income_change": -0.0, + "winner_percentage": 0.5152840905248333, + "loser_percentage": 0.682781489402838, + "no_change_percentage": 0.9056795948117755, + "population": 1328114.3576752637 + }, + { + "district": "IN-07", + "average_household_income_change": -1593.6092126578392, + "relative_household_income_change": 0.9300165882962277, + "winner_percentage": 0.8071593733641752, + "loser_percentage": 0.900119994221593, + "no_change_percentage": 0.8354954367787131, + "population": 1367430.5327072756 + }, + { + "district": "IN-08", + "average_household_income_change": 1068.5852631784965, + "relative_household_income_change": 0.0, + "winner_percentage": 0.8204132946245839, + "loser_percentage": 0.3608426792138256, + "no_change_percentage": 0.18788889430727695, + "population": 21498.863981323782 + }, + { + "district": "IN-09", + "average_household_income_change": 776.9347282683157, + "relative_household_income_change": 0.0, + "winner_percentage": 0.6616872981421206, + "loser_percentage": 0.030077650802229683, + "no_change_percentage": 0.34472141995243333, + "population": 1302732.5334541004 + }, + { + "district": "IA-01", + "average_household_income_change": -172.90289721353201, + "relative_household_income_change": -3.5e-9, + "winner_percentage": 0.9984860116826633, + "loser_percentage": 0.4338107893045394, + "no_change_percentage": 0.8739248717621387, + "population": 503227.16508634866 + }, + { + "district": "IA-02", + "average_household_income_change": -1394.6923023364013, + "relative_household_income_change": -3.5e-9, + "winner_percentage": 0.8106361295631114, + "loser_percentage": 0.626002225091513, + "no_change_percentage": 0.8134850179621343, + "population": 784835.4653311565 + }, + { + "district": "IA-03", + "average_household_income_change": 1713.4816470394996, + "relative_household_income_change": -0.0, + "winner_percentage": 0.9076181488172578, + "loser_percentage": 0.36436919530845213, + "no_change_percentage": 0.33861984777998977, + "population": 1784915.3228063858 + }, + { + "district": "IA-04", + "average_household_income_change": 1302.92709206923, + "relative_household_income_change": 0.5909766192015912, + "winner_percentage": 0.6048621685192132, + "loser_percentage": 0.37038998722410765, + "no_change_percentage": 0.21580580665448057, + "population": 521908.5145946276 + }, + { + "district": "KS-01", + "average_household_income_change": -801.536463991424, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.15779600302905106, + "loser_percentage": 0.3275096345694931, + "no_change_percentage": 0.7700970063040022, + "population": 1158917.6367092847 + }, + { + "district": "KS-02", + "average_household_income_change": -1467.5486906880017, + "relative_household_income_change": 0.0, + "winner_percentage": 0.07794971326549949, + "loser_percentage": 0.3659647085800364, + "no_change_percentage": 0.6697767196678369, + "population": 1180315.3254442988 + }, + { + "district": "KS-03", + "average_household_income_change": -998.5389142285652, + "relative_household_income_change": 0.96644400131702, + "winner_percentage": 0.2199866045393546, + "loser_percentage": 0.7212089046789031, + "no_change_percentage": 0.5273740102688681, + "population": 1300551.5281737293 + }, + { + "district": "KS-04", + "average_household_income_change": 59.76139904572708, + "relative_household_income_change": 0.0731691308450253, + "winner_percentage": 0.4230926063914482, + "loser_percentage": 0.5564120081519053, + "no_change_percentage": 0.16805565313238235, + "population": 1825669.2040313217 + }, + { + "district": "KY-01", + "average_household_income_change": -439.46558083917967, + "relative_household_income_change": 0.0, + "winner_percentage": 0.5315916588112487, + "loser_percentage": 0.4297116811134062, + "no_change_percentage": 0.7779802329532324, + "population": 1241387.4136178733 + }, + { + "district": "KY-02", + "average_household_income_change": -1958.2920564168428, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.3102185117449269, + "loser_percentage": 0.2601416687778113, + "no_change_percentage": 0.7174637011128064, + "population": 103222.15098348679 + }, + { + "district": "KY-03", + "average_household_income_change": 1577.5956112680167, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.5509390406133198, + "loser_percentage": 0.41939119315240914, + "no_change_percentage": 0.40112867829271226, + "population": 1293036.2265681778 + }, + { + "district": "KY-04", + "average_household_income_change": 597.7932019967614, + "relative_household_income_change": 0.0, + "winner_percentage": 0.5566798264100037, + "loser_percentage": 0.49443671187899363, + "no_change_percentage": 0.8664142094952593, + "population": 159073.7403591771 + }, + { + "district": "KY-05", + "average_household_income_change": -627.7167955459339, + "relative_household_income_change": 0.0, + "winner_percentage": 0.0639402084248164, + "loser_percentage": 0.44643648536776714, + "no_change_percentage": 0.9930082783315363, + "population": 1958931.4244845738 + }, + { + "district": "KY-06", + "average_household_income_change": -727.5992738181895, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.5726424832986132, + "loser_percentage": 0.862548842259578, + "no_change_percentage": 0.7502947980563558, + "population": 949144.9444322865 + }, + { + "district": "LA-01", + "average_household_income_change": -1364.3590971359308, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.476438483581604, + "loser_percentage": 0.9005795074767224, + "no_change_percentage": 0.7464015955534695, + "population": 345043.6507790921 + }, + { + "district": "LA-02", + "average_household_income_change": -1903.5085270057257, + "relative_household_income_change": 0.1703089988165779, + "winner_percentage": 0.7175414719440296, + "loser_percentage": 0.23317379559193963, + "no_change_percentage": 0.3609540565462225, + "population": 1383561.5821714178 + }, + { + "district": "LA-03", + "average_household_income_change": -1629.2180327406131, + "relative_household_income_change": -3.5e-9, + "winner_percentage": 0.22703210958810316, + "loser_percentage": 0.7907577314390017, + "no_change_percentage": 0.2606935385885101, + "population": 729464.6838370862 + }, + { + "district": "LA-04", + "average_household_income_change": -383.22317966654043, + "relative_household_income_change": 0.0, + "winner_percentage": 0.18074902751456967, + "loser_percentage": 0.2926629118216396, + "no_change_percentage": 0.7159850595200199, + "population": 400149.26426947257 + }, + { + "district": "LA-05", + "average_household_income_change": 313.5519251237011, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.6867985570598312, + "loser_percentage": 0.14598790261955452, + "no_change_percentage": 0.19367174558790679, + "population": 1818327.8344902145 + }, + { + "district": "LA-06", + "average_household_income_change": -1122.701598229701, + "relative_household_income_change": 0.0, + "winner_percentage": 0.41670316989239153, + "loser_percentage": 0.5276358782343809, + "no_change_percentage": 0.10157188800946892, + "population": 1340155.2865167146 + }, + { + "district": "ME-01", + "average_household_income_change": 1921.3484261844283, + "relative_household_income_change": 0.15347762030365875, + "winner_percentage": 0.4775584954966925, + "loser_percentage": 0.5635039159944188, + "no_change_percentage": 0.9200100413801342, + "population": 1005730.3873189946 + }, + { + "district": "ME-02", + "average_household_income_change": 1198.2131676192255, + "relative_household_income_change": 0.8484137820647389, + "winner_percentage": 0.9766204344664193, + "loser_percentage": 0.2650886493790763, + "no_change_percentage": 0.10344663845239477, + "population": 1863014.0881681717 + }, + { + "district": "MD-01", + "average_household_income_change": 1702.901383133684, + "relative_household_income_change": 0.2143028894383544, + "winner_percentage": 0.18688458854843337, + "loser_percentage": 0.5461223819936809, + "no_change_percentage": 0.34596273557092383, + "population": 844926.0891118036 + }, + { + "district": "MD-02", + "average_household_income_change": -446.36186571537183, + "relative_household_income_change": 0.0, + "winner_percentage": 0.49660729888128285, + "loser_percentage": 0.862475039076589, + "no_change_percentage": 0.4454012730312159, + "population": 542673.1678530314 + }, + { + "district": "MD-03", + "average_household_income_change": -426.33497306834033, + "relative_household_income_change": -3.5e-9, + "winner_percentage": 0.7712136782106079, + "loser_percentage": 0.4604555382163549, + "no_change_percentage": 0.6293759911041594, + "population": 1388690.6206276682 + }, + { + "district": "MD-04", + "average_household_income_change": -1285.7942373542714, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.6450332932660897, + "loser_percentage": 0.10992059831565892, + "no_change_percentage": 0.10908133197881842, + "population": 1617344.7215995933 + }, + { + "district": "MD-05", + "average_household_income_change": 829.1519073807833, + "relative_household_income_change": 0.6244743874457772, + "winner_percentage": 0.11104437970100578, + "loser_percentage": 0.6871799963497981, + "no_change_percentage": 0.10347992565513853, + "population": 34837.83938187687 + }, + { + "district": "MD-06", + "average_household_income_change": -1250.5060513492663, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.2945014209753922, + "loser_percentage": 0.28703695418546127, + "no_change_percentage": 0.5723026316816926, + "population": 1279464.5968338784 + }, + { + "district": "MD-07", + "average_household_income_change": -1173.7953960926784, + "relative_household_income_change": -3.5e-9, + "winner_percentage": 0.3077889316540633, + "loser_percentage": 0.14604870787099422, + "no_change_percentage": 0.5784019372409128, + "population": 835102.5847782891 + }, + { + "district": "MD-08", + "average_household_income_change": 958.4059995627747, + "relative_household_income_change": 0.1797136586040724, + "winner_percentage": 0.5783591341667679, + "loser_percentage": 0.877472856433452, + "no_change_percentage": 0.5081306575888774, + "population": 908920.711186995 + }, + { + "district": "MA-01", + "average_household_income_change": 1416.8346562987865, + "relative_household_income_change": 0.0, + "winner_percentage": 0.3141124548700813, + "loser_percentage": 0.5490960771595501, + "no_change_percentage": 0.1370813477802525, + "population": 1269028.186098155 + }, + { + "district": "MA-02", + "average_household_income_change": -503.1472085947617, + "relative_household_income_change": -3.5e-9, + "winner_percentage": 0.741863264029681, + "loser_percentage": 0.4452677828502838, + "no_change_percentage": 0.25980312603028133, + "population": 1019406.9456735733 + }, + { + "district": "MA-03", + "average_household_income_change": 593.7196781514027, + "relative_household_income_change": 0.0, + "winner_percentage": 0.0010621942626991565, + "loser_percentage": 0.1586070962209688, + "no_change_percentage": 0.9960816450557308, + "population": 1092970.6778509466 + }, + { + "district": "MA-04", + "average_household_income_change": 54.53362383745875, + "relative_household_income_change": -3.5e-9, + "winner_percentage": 0.8263750701371254, + "loser_percentage": 0.31033436314622787, + "no_change_percentage": 0.27119567144427503, + "population": 146002.38956846413 + }, + { + "district": "MA-05", + "average_household_income_change": -775.4813945067278, + "relative_household_income_change": -3.5e-9, + "winner_percentage": 0.17269551015352502, + "loser_percentage": 0.33134070111743685, + "no_change_percentage": 0.6644311862866258, + "population": 1296533.775787876 + }, + { + "district": "MA-06", + "average_household_income_change": -1221.0022519637093, + "relative_household_income_change": -3.5e-9, + "winner_percentage": 0.13285402478580643, + "loser_percentage": 0.1485201336102424, + "no_change_percentage": 0.6721815076145037, + "population": 100614.97459270433 + }, + { + "district": "MA-07", + "average_household_income_change": -87.21918760309944, + "relative_household_income_change": 0.863282508684126, + "winner_percentage": 0.6083553079922789, + "loser_percentage": 0.5994646976434661, + "no_change_percentage": 0.12318961270575113, + "population": 1981178.1976581682 + }, + { + "district": "MA-08", + "average_household_income_change": 1861.3530810064406, + "relative_household_income_change": -0.0, + "winner_percentage": 0.8005235502084675, + "loser_percentage": 0.051754679795765646, + "no_change_percentage": 0.806748361608218, + "population": 485845.9904615471 + }, + { + "district": "MA-09", + "average_household_income_change": -1493.1860660360483, + "relative_household_income_change": -3.5e-9, + "winner_percentage": 0.19562419841567757, + "loser_percentage": 0.5421273722207332, + "no_change_percentage": 0.378957135325633, + "population": 223702.1652700539 + }, + { + "district": "MI-01", + "average_household_income_change": 747.6924636515037, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.332978525789828, + "loser_percentage": 0.02250058685817169, + "no_change_percentage": 0.0699379879127281, + "population": 1069746.452205889 + }, + { + "district": "MI-02", + "average_household_income_change": -582.2341453743993, + "relative_household_income_change": -3.5e-9, + "winner_percentage": 0.809417093226375, + "loser_percentage": 0.9572113987884276, + "no_change_percentage": 0.7663004546750843, + "population": 304063.51036169555 + }, + { + "district": "MI-03", + "average_household_income_change": 539.0419864831002, + "relative_household_income_change": -0.0, + "winner_percentage": 0.44319499146694996, + "loser_percentage": 0.7559869300969424, + "no_change_percentage": 0.6467521336418156, + "population": 555912.7641956314 + }, + { + "district": "MI-04", + "average_household_income_change": -598.8011472955503, + "relative_household_income_change": 0.0, + "winner_percentage": 0.5453152034206704, + "loser_percentage": 0.9099431686557429, + "no_change_percentage": 0.6870091744991247, + "population": 1388686.9483119224 + }, + { + "district": "MI-05", + "average_household_income_change": 1688.969341646402, + "relative_household_income_change": 0.012013326021297233, + "winner_percentage": 0.738762866655325, + "loser_percentage": 0.06721378517513077, + "no_change_percentage": 0.6932132528410323, + "population": 751136.6903781283 + }, + { + "district": "MI-06", + "average_household_income_change": -1481.2829169075976, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.3439870287900032, + "loser_percentage": 0.11495835563060186, + "no_change_percentage": 0.1642953836325286, + "population": 1410030.2948224256 + }, + { + "district": "MI-07", + "average_household_income_change": 1298.3306232899383, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.7475569280994253, + "loser_percentage": 0.1522308590335446, + "no_change_percentage": 0.2738319866907999, + "population": 1661527.2188666146 + }, + { + "district": "MI-08", + "average_household_income_change": 98.35919936821958, + "relative_household_income_change": -3.5e-9, + "winner_percentage": 0.8087863580886516, + "loser_percentage": 0.17937380845130346, + "no_change_percentage": 0.6067885223130947, + "population": 878.3177274980117 + }, + { + "district": "MI-09", + "average_household_income_change": -1161.4298905365165, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.6298236728074138, + "loser_percentage": 0.6801065870092902, + "no_change_percentage": 0.2817643398509323, + "population": 753184.912590639 + }, + { + "district": "MI-10", + "average_household_income_change": 1558.124809115705, + "relative_household_income_change": 0.2627878996555487, + "winner_percentage": 0.5572251010462818, + "loser_percentage": 0.17597908543615892, + "no_change_percentage": 0.5817198682065653, + "population": 1091698.9193075108 + }, + { + "district": "MI-11", + "average_household_income_change": 599.9241748259441, + "relative_household_income_change": -3.5e-9, + "winner_percentage": 0.08410093298080046, + "loser_percentage": 0.9434356805492797, + "no_change_percentage": 0.8972368101002257, + "population": 1529510.4841412515 + }, + { + "district": "MI-12", + "average_household_income_change": 43.70565216707334, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.7824540201953049, + "loser_percentage": 0.5640828896294948, + "no_change_percentage": 0.6404440150803293, + "population": 556875.7039056781 + }, + { + "district": "MI-13", + "average_household_income_change": -430.5457952783849, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.21234343940768685, + "loser_percentage": 0.4275690963090871, + "no_change_percentage": 0.2916862542675427, + "population": 1179000.7744625115 + }, + { + "district": "MN-01", + "average_household_income_change": -1049.7138824796225, + "relative_household_income_change": 0.3727512718102719, + "winner_percentage": 0.4770714577747178, + "loser_percentage": 0.3914468962844778, + "no_change_percentage": 0.1778027569550269, + "population": 1330527.5413455432 + }, + { + "district": "MN-02", + "average_household_income_change": -1474.8076265750228, + "relative_household_income_change": 0.9289048142758826, + "winner_percentage": 0.13997488521748647, + "loser_percentage": 0.5799255484506891, + "no_change_percentage": 0.009217647181251842, + "population": 63614.29054890922 + }, + { + "district": "MN-03", + "average_household_income_change": 478.6972643757057, + "relative_household_income_change": -3.5e-9, + "winner_percentage": 0.8834709327868909, + "loser_percentage": 0.9764696126405257, + "no_change_percentage": 0.06808872782490405, + "population": 279478.5977209589 + }, + { + "district": "MN-04", + "average_household_income_change": -758.4000623220745, + "relative_household_income_change": 0.0, + "winner_percentage": 0.9793788964482745, + "loser_percentage": 0.9223794630483954, + "no_change_percentage": 0.9913210056905115, + "population": 1236882.1844880541 + }, + { + "district": "MN-05", + "average_household_income_change": -1276.0615571959931, + "relative_household_income_change": 0.0, + "winner_percentage": 0.4391093208196486, + "loser_percentage": 0.7049212714324123, + "no_change_percentage": 0.2091770500168495, + "population": 1138057.030369344 + }, + { + "district": "MN-06", + "average_household_income_change": 1419.3816667809144, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.14382038488848137, + "loser_percentage": 0.6655023332981367, + "no_change_percentage": 0.041662734674265844, + "population": 487674.8074334767 + }, + { + "district": "MN-07", + "average_household_income_change": -1712.1659206986233, + "relative_household_income_change": 0.19708362157980042, + "winner_percentage": 0.3506818697740155, + "loser_percentage": 0.323962746659895, + "no_change_percentage": 0.4885777377608531, + "population": 360611.0401030129 + }, + { + "district": "MN-08", + "average_household_income_change": -901.656897741046, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.66631940230475, + "loser_percentage": 0.7223543911582926, + "no_change_percentage": 0.27213596933584105, + "population": 561758.3054228415 + }, + { + "district": "MS-01", + "average_household_income_change": -255.90344511944662, + "relative_household_income_change": -0.0, + "winner_percentage": 0.8661702253422987, + "loser_percentage": 0.66118515674882, + "no_change_percentage": 0.048966995321201856, + "population": 1595101.0802975115 + }, + { + "district": "MS-02", + "average_household_income_change": 1072.3170739476213, + "relative_household_income_change": -0.0, + "winner_percentage": 0.734126910069098, + "loser_percentage": 0.2760096221893993, + "no_change_percentage": 0.68582587357717, + "population": 1936414.229907305 + }, + { + "district": "MS-03", + "average_household_income_change": 298.2937768552656, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.5634955646257539, + "loser_percentage": 0.2557204553896971, + "no_change_percentage": 0.5532640828786518, + "population": 852166.905599482 + }, + { + "district": "MS-04", + "average_household_income_change": -1123.6494666458668, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.4850530850613204, + "loser_percentage": 0.542074369202462, + "no_change_percentage": 0.70572458521411, + "population": 216115.7074154712 + }, + { + "district": "MO-01", + "average_household_income_change": 40.81526602761221, + "relative_household_income_change": -3.5e-9, + "winner_percentage": 0.07891563444520278, + "loser_percentage": 0.9464586690534529, + "no_change_percentage": 0.028449114629045757, + "population": 615711.0223877344 + }, + { + "district": "MO-02", + "average_household_income_change": -657.1049821804115, + "relative_household_income_change": 0.0, + "winner_percentage": 0.014130832310066177, + "loser_percentage": 0.5988327326146267, + "no_change_percentage": 0.2385767692206523, + "population": 1598205.7162534988 + }, + { + "district": "MO-03", + "average_household_income_change": -53.7815958697565, + "relative_household_income_change": 0.3229614670597981, + "winner_percentage": 0.36156747690200897, + "loser_percentage": 0.6781971292751447, + "no_change_percentage": 0.942078824705612, + "population": 1269408.8987946059 + }, + { + "district": "MO-04", + "average_household_income_change": -671.5295872504687, + "relative_household_income_change": 0.0, + "winner_percentage": 0.6979644825140945, + "loser_percentage": 0.601781099012347, + "no_change_percentage": 0.572364627309296, + "population": 907118.6239947318 + }, + { + "district": "MO-05", + "average_household_income_change": -530.1692420025117, + "relative_household_income_change": -0.0, + "winner_percentage": 0.23027025708676785, + "loser_percentage": 0.4051771799769186, + "no_change_percentage": 0.887996694797536, + "population": 49155.26876678865 + }, + { + "district": "MO-06", + "average_household_income_change": -586.0399057701087, + "relative_household_income_change": -3.5e-9, + "winner_percentage": 0.7738649989297562, + "loser_percentage": 0.8679764267682314, + "no_change_percentage": 0.7292179446919571, + "population": 1122912.1066235972 + }, + { + "district": "MO-07", + "average_household_income_change": 1964.898418684791, + "relative_household_income_change": 0.0, + "winner_percentage": 0.9042759026361998, + "loser_percentage": 0.36455736475779155, + "no_change_percentage": 0.8489084702077566, + "population": 379743.7160746093 + }, + { + "district": "MO-08", + "average_household_income_change": 336.5603570250859, + "relative_household_income_change": -0.0, + "winner_percentage": 0.18712335357307075, + "loser_percentage": 0.657845419356025, + "no_change_percentage": 0.7113805920262503, + "population": 1255582.067934901 + }, + { + "district": "MT-01", + "average_household_income_change": 983.512209057535, + "relative_household_income_change": -0.0, + "winner_percentage": 0.6886199078768173, + "loser_percentage": 0.25605725846858585, + "no_change_percentage": 0.09915451748889526, + "population": 719811.1730435372 + }, + { + "district": "MT-02", + "average_household_income_change": -1226.0794958019412, + "relative_household_income_change": 0.5612276116099638, + "winner_percentage": 0.28209905361394183, + "loser_percentage": 0.5945383380085424, + "no_change_percentage": 0.7352463894684987, + "population": 397016.73677204945 + }, + { + "district": "NE-01", + "average_household_income_change": -1178.9227940818466, + "relative_household_income_change": 0.0, + "winner_percentage": 0.7717445355667062, + "loser_percentage": 0.9548158300345837, + "no_change_percentage": 0.36881783488012165, + "population": 1458335.460089935 + }, + { + "district": "NE-02", + "average_household_income_change": 778.2964863920827, + "relative_household_income_change": -3.5e-9, + "winner_percentage": 0.4417767511041598, + "loser_percentage": 0.6507108550430083, + "no_change_percentage": 0.711661616417475, + "population": 967943.6800451052 + }, + { + "district": "NE-03", + "average_household_income_change": -922.672970623951, + "relative_household_income_change": 0.6319237715503292, + "winner_percentage": 0.09726516916592454, + "loser_percentage": 0.6428243489026462, + "no_change_percentage": 0.4190339797262024, + "population": 323762.0653781112 + }, + { + "district": "NV-01", + "average_household_income_change": -688.8600459298738, + "relative_household_income_change": 0.06928171539895811, + "winner_percentage": 0.5809572073479989, + "loser_percentage": 0.5315051068930021, + "no_change_percentage": 0.767522214563325, + "population": 910692.5784934496 + }, + { + "district": "NV-02", + "average_household_income_change": 1709.6034596338495, + "relative_household_income_change": 0.28167393496270166, + "winner_percentage": 0.23278075110677732, + "loser_percentage": 0.6063454319254328, + "no_change_percentage": 0.09937772231269837, + "population": 1597996.9889687065 + }, + { + "district": "NV-03", + "average_household_income_change": 1408.0974916503135, + "relative_household_income_change": 0.0, + "winner_percentage": 0.0941601815928258, + "loser_percentage": 0.14353136380653897, + "no_change_percentage": 0.5629582751261204, + "population": 477334.4048267159 + }, + { + "district": "NV-04", + "average_household_income_change": -427.9378679351966, + "relative_household_income_change": 0.0, + "winner_percentage": 0.775371200821322, + "loser_percentage": 0.8848608727622929, + "no_change_percentage": 0.2384576473390242, + "population": 520367.63519200013 + }, + { + "district": "NH-01", + "average_household_income_change": 1326.8209031397103, + "relative_household_income_change": 0.0, + "winner_percentage": 0.05550972747813998, + "loser_percentage": 0.34506329326687946, + "no_change_percentage": 0.4858060824382846, + "population": 1215752.0712104617 + }, + { + "district": "NH-02", + "average_household_income_change": -1941.5662836592323, + "relative_household_income_change": 0.0, + "winner_percentage": 0.8913316946883595, + "loser_percentage": 0.15248270653918305, + "no_change_percentage": 0.2127113800760161, + "population": 999683.2521774701 + }, + { + "district": "NJ-01", + "average_household_income_change": -1346.610051685778, + "relative_household_income_change": -3.5e-9, + "winner_percentage": 0.8705037018178549, + "loser_percentage": 0.9332653671497912, + "no_change_percentage": 0.0013087110055514106, + "population": 41657.1833312962 + }, + { + "district": "NJ-02", + "average_household_income_change": -1430.9975323618924, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.3961612522306085, + "loser_percentage": 0.5497374172842523, + "no_change_percentage": 0.9570351353602428, + "population": 988525.2115806546 + }, + { + "district": "NJ-03", + "average_household_income_change": -480.9490596831703, + "relative_household_income_change": 0.8715069679828527, + "winner_percentage": 0.4162030039946538, + "loser_percentage": 0.8147648361198342, + "no_change_percentage": 0.2477053114997656, + "population": 200620.21363778634 + }, + { + "district": "NJ-04", + "average_household_income_change": -1064.0883488234874, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.25384228249797125, + "loser_percentage": 0.07328308823761476, + "no_change_percentage": 0.10878178812122041, + "population": 1600451.562733883 + }, + { + "district": "NJ-05", + "average_household_income_change": 7.583440590375634, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.6524841274565424, + "loser_percentage": 0.5011181621406384, + "no_change_percentage": 0.4005971159936217, + "population": 642122.7083181444 + }, + { + "district": "NJ-06", + "average_household_income_change": 1847.4813653025826, + "relative_household_income_change": 0.2827700149160155, + "winner_percentage": 0.4871872762468712, + "loser_percentage": 0.09090848080435499, + "no_change_percentage": 0.8499029659176067, + "population": 1764753.0816979911 + }, + { + "district": "NJ-07", + "average_household_income_change": 297.92674740995295, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.3579658557678955, + "loser_percentage": 0.020493003160175216, + "no_change_percentage": 0.9566814801456087, + "population": 935278.8794728584 + }, + { + "district": "NJ-08", + "average_household_income_change": -644.7962448650793, + "relative_household_income_change": -3.5e-9, + "winner_percentage": 0.7972547616227862, + "loser_percentage": 0.22063907980487918, + "no_change_percentage": 0.8316761144777678, + "population": 1229915.3582338342 + }, + { + "district": "NJ-09", + "average_household_income_change": 1045.5579441464936, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.702622771047097, + "loser_percentage": 0.20381647945908887, + "no_change_percentage": 0.32418582253424266, + "population": 1564811.1773359927 + }, + { + "district": "NJ-10", + "average_household_income_change": -1692.9557828654338, + "relative_household_income_change": -3.5e-9, + "winner_percentage": 0.9267951257709088, + "loser_percentage": 0.8464769553409315, + "no_change_percentage": 0.5949924228024286, + "population": 803577.459125552 + }, + { + "district": "NJ-11", + "average_household_income_change": -1614.937124481708, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.3196812411637635, + "loser_percentage": 0.2890420591557624, + "no_change_percentage": 0.9655833503800089, + "population": 659520.9005394165 + }, + { + "district": "NJ-12", + "average_household_income_change": -1313.8963892744994, + "relative_household_income_change": -0.0, + "winner_percentage": 0.8108024249786424, + "loser_percentage": 0.2677947791608425, + "no_change_percentage": 0.6793089734463279, + "population": 1197655.9216551264 + }, + { + "district": "NM-01", + "average_household_income_change": 665.160281218299, + "relative_household_income_change": -0.0, + "winner_percentage": 0.10307122147386438, + "loser_percentage": 0.10536976699570999, + "no_change_percentage": 0.6019343481516051, + "population": 1805298.145269294 + }, + { + "district": "NM-02", + "average_household_income_change": 758.7531207589988, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.6688154452139765, + "loser_percentage": 0.9238301237088424, + "no_change_percentage": 0.970947528110894, + "population": 1674333.7811092706 + }, + { + "district": "NM-03", + "average_household_income_change": -1410.5419522807897, + "relative_household_income_change": -3.5e-9, + "winner_percentage": 0.5035464357324184, + "loser_percentage": 0.09269884575570186, + "no_change_percentage": 0.3889352298588644, + "population": 1264979.3720552137 + }, + { + "district": "NY-01", + "average_household_income_change": -1131.9068991340923, + "relative_household_income_change": 0.5124881192237833, + "winner_percentage": 0.043046256625358104, + "loser_percentage": 0.28712796446459776, + "no_change_percentage": 0.9838704782107919, + "population": 205012.35009282408 + }, + { + "district": "NY-02", + "average_household_income_change": -477.0191933506838, + "relative_household_income_change": 0.0, + "winner_percentage": 0.4581353685754621, + "loser_percentage": 0.867650173463171, + "no_change_percentage": 0.9665102631560167, + "population": 1767864.3394364882 + }, + { + "district": "NY-03", + "average_household_income_change": -757.0547505228901, + "relative_household_income_change": -3.5e-9, + "winner_percentage": 0.5814616489172288, + "loser_percentage": 0.35448345534666637, + "no_change_percentage": 0.02075688966386391, + "population": 1430049.911309068 + }, + { + "district": "NY-04", + "average_household_income_change": 30.62315461557752, + "relative_household_income_change": 0.0, + "winner_percentage": 0.28234767077960055, + "loser_percentage": 0.5712067988140119, + "no_change_percentage": 0.17006966026273418, + "population": 1147280.7963970727 + }, + { + "district": "NY-05", + "average_household_income_change": 1598.90583811054, + "relative_household_income_change": 0.0, + "winner_percentage": 0.662399958732312, + "loser_percentage": 0.4758014996172041, + "no_change_percentage": 0.9788769458498555, + "population": 209471.40409972053 + }, + { + "district": "NY-06", + "average_household_income_change": 504.5097612222769, + "relative_household_income_change": 0.0, + "winner_percentage": 0.6602851280753035, + "loser_percentage": 0.13842947192019328, + "no_change_percentage": 0.4769611571458495, + "population": 505524.22618424473 + }, + { + "district": "NY-07", + "average_household_income_change": 96.57497287162408, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.229946620086402, + "loser_percentage": 0.7237784986880081, + "no_change_percentage": 0.48589571188743963, + "population": 282855.9638871306 + }, + { + "district": "NY-08", + "average_household_income_change": -885.3169937163821, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.06829423577168159, + "loser_percentage": 0.045665461944919716, + "no_change_percentage": 0.09213515158018915, + "population": 1993094.250617465 + }, + { + "district": "NY-09", + "average_household_income_change": -9.819844727013916, + "relative_household_income_change": -0.0, + "winner_percentage": 0.49939512073940096, + "loser_percentage": 0.8090282530465259, + "no_change_percentage": 0.29321700485540136, + "population": 1681118.686924439 + }, + { + "district": "NY-10", + "average_household_income_change": -1643.0299274703914, + "relative_household_income_change": 0.0, + "winner_percentage": 0.8417835247167857, + "loser_percentage": 0.276875009337478, + "no_change_percentage": 0.8327242279468658, + "population": 164428.2753839366 + }, + { + "district": "NY-11", + "average_household_income_change": 208.95180757382238, + "relative_household_income_change": 0.0, + "winner_percentage": 0.6332524715018043, + "loser_percentage": 0.274690539324145, + "no_change_percentage": 0.06459456905720373, + "population": 1724656.115367233 + }, + { + "district": "NY-12", + "average_household_income_change": 1722.1994291750575, + "relative_household_income_change": 0.0, + "winner_percentage": 0.028903587133481956, + "loser_percentage": 0.3340357928932579, + "no_change_percentage": 0.1664276573795902, + "population": 261655.8073576924 + }, + { + "district": "NY-13", + "average_household_income_change": -1745.0492620231976, + "relative_household_income_change": 0.0, + "winner_percentage": 0.7205626808437235, + "loser_percentage": 0.6470267452056409, + "no_change_percentage": 0.16648296179389988, + "population": 1796774.8541061652 + }, + { + "district": "NY-14", + "average_household_income_change": -531.5544893596945, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.2280700295259258, + "loser_percentage": 0.4236858118644774, + "no_change_percentage": 0.26285857414761926, + "population": 949264.7736125515 + }, + { + "district": "NY-15", + "average_household_income_change": 1035.1640699670766, + "relative_household_income_change": -0.0, + "winner_percentage": 0.5029805375678822, + "loser_percentage": 0.849430602105124, + "no_change_percentage": 0.4518045751817217, + "population": 746851.0845919283 + }, + { + "district": "NY-16", + "average_household_income_change": 260.053738656719, + "relative_household_income_change": -0.0, + "winner_percentage": 0.11890264690165409, + "loser_percentage": 0.09255369884592246, + "no_change_percentage": 0.6021350418455398, + "population": 1139978.6944879943 + }, + { + "district": "NY-17", + "average_household_income_change": 551.1459088188273, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.2568565800548146, + "loser_percentage": 0.0658448817049383, + "no_change_percentage": 0.5905054752811186, + "population": 1769856.515164564 + }, + { + "district": "NY-18", + "average_household_income_change": 203.09432013447682, + "relative_household_income_change": -0.0, + "winner_percentage": 0.597936552673326, + "loser_percentage": 0.7150144141312778, + "no_change_percentage": 0.724789937585622, + "population": 520257.4395910977 + }, + { + "district": "NY-19", + "average_household_income_change": -1716.2211584708255, + "relative_household_income_change": -0.0, + "winner_percentage": 0.6519717033404463, + "loser_percentage": 0.7779712516376676, + "no_change_percentage": 0.17157435465193505, + "population": 1591882.803708056 + }, + { + "district": "NY-20", + "average_household_income_change": 1531.0381811405045, + "relative_household_income_change": -0.0, + "winner_percentage": 0.05659121270802303, + "loser_percentage": 0.11572867482718951, + "no_change_percentage": 0.41368525303321957, + "population": 798354.4591802023 + }, + { + "district": "NY-21", + "average_household_income_change": -1481.0177408200632, + "relative_household_income_change": -3.5e-9, + "winner_percentage": 0.6685485548771268, + "loser_percentage": 0.02926629431828265, + "no_change_percentage": 0.3220783749376873, + "population": 665986.4590287958 + }, + { + "district": "NY-22", + "average_household_income_change": 1110.8941560254143, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.4214323670077975, + "loser_percentage": 0.10234225456208867, + "no_change_percentage": 0.376245986759273, + "population": 544219.2144474802 + }, + { + "district": "NY-23", + "average_household_income_change": 684.7430799549437, + "relative_household_income_change": -0.0, + "winner_percentage": 0.3068240717924594, + "loser_percentage": 0.975577878932322, + "no_change_percentage": 0.781071020452218, + "population": 1175599.50257008 + }, + { + "district": "NY-24", + "average_household_income_change": -1120.5230243440383, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.24738329428120054, + "loser_percentage": 0.5051294587237802, + "no_change_percentage": 0.8702153105443287, + "population": 1007687.6809980447 + }, + { + "district": "NY-25", + "average_household_income_change": 1495.6211572010943, + "relative_household_income_change": 0.0, + "winner_percentage": 0.3327362674239437, + "loser_percentage": 0.3980352900226982, + "no_change_percentage": 0.6395244769245754, + "population": 309126.55115195736 + }, + { + "district": "NY-26", + "average_household_income_change": 1005.7524739921187, + "relative_household_income_change": 0.09384776304331244, + "winner_percentage": 0.5132535713329025, + "loser_percentage": 0.11991430122939095, + "no_change_percentage": 0.7204974469291235, + "population": 1780659.23172649 + }, + { + "district": "NC-01", + "average_household_income_change": 1905.7524663701408, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.8819134926398041, + "loser_percentage": 0.44699135441524274, + "no_change_percentage": 0.4400285541797978, + "population": 1801522.6923972447 + }, + { + "district": "NC-02", + "average_household_income_change": 812.7845438528553, + "relative_household_income_change": 0.13890439070678073, + "winner_percentage": 0.06797734049370718, + "loser_percentage": 0.745111961730822, + "no_change_percentage": 0.3039520706041381, + "population": 1010127.7867981759 + }, + { + "district": "NC-03", + "average_household_income_change": -1126.1533846759257, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.9059222479170311, + "loser_percentage": 0.6088042548949335, + "no_change_percentage": 0.8361479455723221, + "population": 1253346.8417832286 + }, + { + "district": "NC-04", + "average_household_income_change": 1588.7537548469916, + "relative_household_income_change": -0.0, + "winner_percentage": 0.12372180888852413, + "loser_percentage": 0.3926530286250651, + "no_change_percentage": 0.07132101791808032, + "population": 1999747.478495196 + }, + { + "district": "NC-05", + "average_household_income_change": 634.647556682796, + "relative_household_income_change": -3.5e-9, + "winner_percentage": 0.32064494301872304, + "loser_percentage": 0.6033236611754655, + "no_change_percentage": 0.7298074029257416, + "population": 1431115.4234459244 + }, + { + "district": "NC-06", + "average_household_income_change": 347.2242650809525, + "relative_household_income_change": -0.0, + "winner_percentage": 0.36731627649607035, + "loser_percentage": 0.8032802872387302, + "no_change_percentage": 0.746072309880131, + "population": 624814.0610123319 + }, + { + "district": "NC-07", + "average_household_income_change": 444.4180985521879, + "relative_household_income_change": -0.0, + "winner_percentage": 0.7289746258995076, + "loser_percentage": 0.3690668818213545, + "no_change_percentage": 0.37433748707080783, + "population": 1800904.0843756036 + }, + { + "district": "NC-08", + "average_household_income_change": 343.9543664215217, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.2889409643152038, + "loser_percentage": 0.29650633313595953, + "no_change_percentage": 0.11314476007451024, + "population": 582017.0773053442 + }, + { + "district": "NC-09", + "average_household_income_change": 847.1751648054621, + "relative_household_income_change": 0.06368776621470995, + "winner_percentage": 0.771368497288142, + "loser_percentage": 0.5813582055912243, + "no_change_percentage": 0.10983216055702494, + "population": 573445.3001250993 + }, + { + "district": "NC-10", + "average_household_income_change": -644.2881383254942, + "relative_household_income_change": -3.5e-9, + "winner_percentage": 0.23855349169819606, + "loser_percentage": 0.14772417607751975, + "no_change_percentage": 0.5789166367792238, + "population": 628706.4061903722 + }, + { + "district": "NC-11", + "average_household_income_change": 1798.3776681929794, + "relative_household_income_change": -0.0, + "winner_percentage": 0.6038503969417593, + "loser_percentage": 0.6954240140826077, + "no_change_percentage": 0.25102031418475945, + "population": 1036069.6351497878 + }, + { + "district": "NC-12", + "average_household_income_change": -1153.2334003615556, + "relative_household_income_change": -3.5e-9, + "winner_percentage": 0.6494020962773108, + "loser_percentage": 0.68112893847386, + "no_change_percentage": 0.7945625910754524, + "population": 453780.4738603879 + }, + { + "district": "NC-13", + "average_household_income_change": 861.2013752677723, + "relative_household_income_change": 0.0, + "winner_percentage": 0.2529435759627967, + "loser_percentage": 0.6842805912026738, + "no_change_percentage": 0.691510662077478, + "population": 681472.2032578625 + }, + { + "district": "NC-14", + "average_household_income_change": -843.4969218054666, + "relative_household_income_change": -0.0, + "winner_percentage": 0.17844476062520975, + "loser_percentage": 0.02440019156351525, + "no_change_percentage": 0.17493552120416667, + "population": 325878.15639773593 + }, + { + "district": "ND-01", + "average_household_income_change": -538.4817956617094, + "relative_household_income_change": 0.0, + "winner_percentage": 0.11051184383413304, + "loser_percentage": 0.41292386930040537, + "no_change_percentage": 0.06585623221099801, + "population": 390452.8819427029 + }, + { + "district": "OH-01", + "average_household_income_change": 1429.5334028291213, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.5278426955891395, + "loser_percentage": 0.6005590283137375, + "no_change_percentage": 0.15869088860396208, + "population": 82774.95630957745 + }, + { + "district": "OH-02", + "average_household_income_change": 247.34152192959513, + "relative_household_income_change": 0.0, + "winner_percentage": 0.7216089357104507, + "loser_percentage": 0.8680780650241383, + "no_change_percentage": 0.00885484187005492, + "population": 831747.4468137303 + }, + { + "district": "OH-03", + "average_household_income_change": 181.29081106309462, + "relative_household_income_change": -0.0, + "winner_percentage": 0.374288814448134, + "loser_percentage": 0.8938726257407104, + "no_change_percentage": 0.5813620810563472, + "population": 1804950.9344293228 + }, + { + "district": "OH-04", + "average_household_income_change": 800.7647640367987, + "relative_household_income_change": 0.8207485460353191, + "winner_percentage": 0.11277780936311466, + "loser_percentage": 0.25265940767418205, + "no_change_percentage": 0.9111574621350451, + "population": 1794784.9527226053 + }, + { + "district": "OH-05", + "average_household_income_change": -1562.6244364927354, + "relative_household_income_change": 0.0, + "winner_percentage": 0.9966657867352428, + "loser_percentage": 0.10886754706831803, + "no_change_percentage": 0.8545825291242566, + "population": 233265.7912630831 + }, + { + "district": "OH-06", + "average_household_income_change": -883.7521616253334, + "relative_household_income_change": 0.0, + "winner_percentage": 0.5164168845139231, + "loser_percentage": 0.027945412433999173, + "no_change_percentage": 0.21120343602251246, + "population": 177783.19323167205 + }, + { + "district": "OH-07", + "average_household_income_change": -188.90997633302487, + "relative_household_income_change": -3.5e-9, + "winner_percentage": 0.9380606200193555, + "loser_percentage": 0.34740716217814394, + "no_change_percentage": 0.8893278594350348, + "population": 964015.0225381623 + }, + { + "district": "OH-08", + "average_household_income_change": 222.99145786351636, + "relative_household_income_change": 0.2599862225866242, + "winner_percentage": 0.7865415348656284, + "loser_percentage": 0.5699768907923377, + "no_change_percentage": 0.7590644900019196, + "population": 898104.1320936508 + }, + { + "district": "OH-09", + "average_household_income_change": 933.2464358174275, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.5186146433595739, + "loser_percentage": 0.03456639265822781, + "no_change_percentage": 0.27847571623212297, + "population": 1678208.3304820228 + }, + { + "district": "OH-10", + "average_household_income_change": -1327.57201116124, + "relative_household_income_change": -0.0, + "winner_percentage": 0.2890878055085202, + "loser_percentage": 0.8531745179280665, + "no_change_percentage": 0.7718057506643415, + "population": 1838588.7533272905 + }, + { + "district": "OH-11", + "average_household_income_change": 1750.127418250961, + "relative_household_income_change": 0.0, + "winner_percentage": 0.4939449029501517, + "loser_percentage": 0.19558528920942286, + "no_change_percentage": 0.14683928808809676, + "population": 117625.8044139602 + }, + { + "district": "OH-12", + "average_household_income_change": 1111.884158618861, + "relative_household_income_change": -0.0, + "winner_percentage": 0.6528616464533499, + "loser_percentage": 0.021400312488671913, + "no_change_percentage": 0.030273923372256095, + "population": 234545.10408303817 + }, + { + "district": "OH-13", + "average_household_income_change": -687.0037649600005, + "relative_household_income_change": 0.0, + "winner_percentage": 0.17953726005725024, + "loser_percentage": 0.9367507607303269, + "no_change_percentage": 0.19810480784373719, + "population": 1608747.5418619215 + }, + { + "district": "OH-14", + "average_household_income_change": 1002.2901963771469, + "relative_household_income_change": 0.949115972430235, + "winner_percentage": 0.6452992282399889, + "loser_percentage": 0.6732223970621404, + "no_change_percentage": 0.8211002682278746, + "population": 1776435.5005847374 + }, + { + "district": "OH-15", + "average_household_income_change": -713.3260828235599, + "relative_household_income_change": 0.8153911026362762, + "winner_percentage": 0.9751500980329527, + "loser_percentage": 0.1837252033481077, + "no_change_percentage": 0.6880747422849436, + "population": 1904353.6250990205 + }, + { + "district": "OK-01", + "average_household_income_change": 1460.3826473514553, + "relative_household_income_change": -0.0, + "winner_percentage": 0.7070840854137713, + "loser_percentage": 0.30215987451830306, + "no_change_percentage": 0.5015683823012259, + "population": 1139495.53806115 + }, + { + "district": "OK-02", + "average_household_income_change": 1083.7770389931225, + "relative_household_income_change": -0.0, + "winner_percentage": 0.2890350001539308, + "loser_percentage": 0.9653428558779258, + "no_change_percentage": 0.19620231019756684, + "population": 162863.33019325696 + }, + { + "district": "OK-03", + "average_household_income_change": -937.8420013990443, + "relative_household_income_change": 0.4727799567491602, + "winner_percentage": 0.3201734466820204, + "loser_percentage": 0.022463908344121597, + "no_change_percentage": 0.35784388173343773, + "population": 1275767.40827854 + }, + { + "district": "OK-04", + "average_household_income_change": 1080.8028799910123, + "relative_household_income_change": 0.9267783457836459, + "winner_percentage": 0.9681426826536599, + "loser_percentage": 0.24653060984129416, + "no_change_percentage": 0.9900239027127675, + "population": 690757.1648270963 + }, + { + "district": "OK-05", + "average_household_income_change": -186.4124367820863, + "relative_household_income_change": -3.5e-9, + "winner_percentage": 0.38612199074311315, + "loser_percentage": 0.39905328159098163, + "no_change_percentage": 0.5755953780919827, + "population": 314083.9250144502 + }, + { + "district": "OR-01", + "average_household_income_change": 1215.0282215772452, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.6001265471383288, + "loser_percentage": 0.9671144958686907, + "no_change_percentage": 0.838732929258236, + "population": 313837.5584065651 + }, + { + "district": "OR-02", + "average_household_income_change": 704.6383715214604, + "relative_household_income_change": 0.7029758642693501, + "winner_percentage": 0.8293483474290964, + "loser_percentage": 0.5755792575435204, + "no_change_percentage": 0.9333065230896005, + "population": 1464348.4347723061 + }, + { + "district": "OR-03", + "average_household_income_change": -873.0524531996738, + "relative_household_income_change": 0.0, + "winner_percentage": 0.2377304067129462, + "loser_percentage": 0.16987010804218217, + "no_change_percentage": 0.19668375289592133, + "population": 1394621.2240415476 + }, + { + "district": "OR-04", + "average_household_income_change": 1899.8809389932742, + "relative_household_income_change": -0.0, + "winner_percentage": 0.2679186601454181, + "loser_percentage": 0.9327699126738945, + "no_change_percentage": 0.3492058947704546, + "population": 669531.8836256716 + }, + { + "district": "OR-05", + "average_household_income_change": -693.9948241065301, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.8890441269074849, + "loser_percentage": 0.004487024580698384, + "no_change_percentage": 0.42569268304669017, + "population": 1654538.1237349864 + }, + { + "district": "OR-06", + "average_household_income_change": 1963.1431541606328, + "relative_household_income_change": 0.0, + "winner_percentage": 0.8270559556960193, + "loser_percentage": 0.2337614248102322, + "no_change_percentage": 0.6327919707602321, + "population": 602386.5793205993 + }, + { + "district": "PA-01", + "average_household_income_change": -1724.7276769199145, + "relative_household_income_change": 0.0791408204484465, + "winner_percentage": 0.3384174936357105, + "loser_percentage": 0.28023895938453636, + "no_change_percentage": 0.15202515307938014, + "population": 1651262.3038585437 + }, + { + "district": "PA-02", + "average_household_income_change": 1089.8441601017366, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.7689888611451111, + "loser_percentage": 0.6930673921450239, + "no_change_percentage": 0.2060269791840018, + "population": 897542.4105421195 + }, + { + "district": "PA-03", + "average_household_income_change": -1969.1553365678662, + "relative_household_income_change": -0.0, + "winner_percentage": 0.05619416354044959, + "loser_percentage": 0.4384500983984615, + "no_change_percentage": 0.3180855632642814, + "population": 281678.32508080103 + }, + { + "district": "PA-04", + "average_household_income_change": 285.9503748558221, + "relative_household_income_change": 0.0, + "winner_percentage": 0.428737064786506, + "loser_percentage": 0.6940226808823239, + "no_change_percentage": 0.8569663707062056, + "population": 1721941.9270078402 + }, + { + "district": "PA-05", + "average_household_income_change": 997.6363395334391, + "relative_household_income_change": 0.9818112362598781, + "winner_percentage": 0.4502167723979821, + "loser_percentage": 0.12921709727170727, + "no_change_percentage": 0.12082370227430617, + "population": 295940.35761302616 + }, + { + "district": "PA-06", + "average_household_income_change": 665.1380166195513, + "relative_household_income_change": -3.5e-9, + "winner_percentage": 0.07783017425906258, + "loser_percentage": 0.9647536084038852, + "no_change_percentage": 0.4847236296018368, + "population": 1626059.0412948849 + }, + { + "district": "PA-07", + "average_household_income_change": -471.4252506002263, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.5757088097507093, + "loser_percentage": 0.603956925904559, + "no_change_percentage": 0.6430133895206961, + "population": 1973132.5320566306 + }, + { + "district": "PA-08", + "average_household_income_change": -925.3953112617737, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.9231177478320901, + "loser_percentage": 0.8934945233526166, + "no_change_percentage": 0.028048398007435416, + "population": 1427743.709207689 + }, + { + "district": "PA-09", + "average_household_income_change": 1941.9594629095197, + "relative_household_income_change": -3.5e-9, + "winner_percentage": 0.5663048289142881, + "loser_percentage": 0.9751785263409453, + "no_change_percentage": 0.5087186098095644, + "population": 1751731.1897622026 + }, + { + "district": "PA-10", + "average_household_income_change": -168.88982054250468, + "relative_household_income_change": 0.0557679908403409, + "winner_percentage": 0.7502997397542419, + "loser_percentage": 0.840708859748251, + "no_change_percentage": 0.4231543787214357, + "population": 330194.5655087655 + }, + { + "district": "PA-11", + "average_household_income_change": -142.78281027491778, + "relative_household_income_change": -3.5e-9, + "winner_percentage": 0.5385685110982603, + "loser_percentage": 0.9064943105743645, + "no_change_percentage": 0.40045233370041333, + "population": 1313346.120477421 + }, + { + "district": "PA-12", + "average_household_income_change": 729.1416517787517, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.2808591493475159, + "loser_percentage": 0.5302376654329679, + "no_change_percentage": 0.798006877012943, + "population": 1570502.0636920966 + }, + { + "district": "PA-13", + "average_household_income_change": -1010.1366291548954, + "relative_household_income_change": 0.9495430575625469, + "winner_percentage": 0.7609948129598099, + "loser_percentage": 0.05588084422096318, + "no_change_percentage": 0.2097914206301834, + "population": 212650.61445635825 + }, + { + "district": "PA-14", + "average_household_income_change": 193.65812691362328, + "relative_household_income_change": -0.0, + "winner_percentage": 0.3910458766204923, + "loser_percentage": 0.10675034109650516, + "no_change_percentage": 0.9594313286131515, + "population": 1751171.2271268014 + }, + { + "district": "PA-15", + "average_household_income_change": 1046.0629749759046, + "relative_household_income_change": 0.0, + "winner_percentage": 0.6325803240880272, + "loser_percentage": 0.493105175529035, + "no_change_percentage": 0.4439200089858375, + "population": 63941.620072624995 + }, + { + "district": "PA-16", + "average_household_income_change": 1008.7316836972371, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.6399996688075169, + "loser_percentage": 0.29180332739195713, + "no_change_percentage": 0.05235921925952458, + "population": 576947.4273465474 + }, + { + "district": "PA-17", + "average_household_income_change": -1717.8033293070962, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.1607192942837673, + "loser_percentage": 0.6626523627031539, + "no_change_percentage": 0.7392257404199818, + "population": 585286.8629265588 + }, + { + "district": "RI-01", + "average_household_income_change": -1550.5857205303325, + "relative_household_income_change": -3.5e-9, + "winner_percentage": 0.6313800843931212, + "loser_percentage": 0.08215021086848406, + "no_change_percentage": 0.6494960270009935, + "population": 150834.82240956987 + }, + { + "district": "RI-02", + "average_household_income_change": -1465.6676100434124, + "relative_household_income_change": 0.0, + "winner_percentage": 0.7130625752476205, + "loser_percentage": 0.17460034652050782, + "no_change_percentage": 0.31426725005408773, + "population": 656190.5805730725 + }, + { + "district": "SC-01", + "average_household_income_change": 1937.2605734310505, + "relative_household_income_change": 0.8527070615837832, + "winner_percentage": 0.6689396741212047, + "loser_percentage": 0.8519964791926429, + "no_change_percentage": 0.8147617722049865, + "population": 460259.70526279614 + }, + { + "district": "SC-02", + "average_household_income_change": -1649.4072107732266, + "relative_household_income_change": -3.5e-9, + "winner_percentage": 0.981992756769073, + "loser_percentage": 0.7032420090911612, + "no_change_percentage": 0.800160582343668, + "population": 296933.1304116682 + }, + { + "district": "SC-03", + "average_household_income_change": 1735.5185940756512, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.6806667209436814, + "loser_percentage": 0.5663093565909887, + "no_change_percentage": 0.3417763897456615, + "population": 1623962.9294941647 + }, + { + "district": "SC-04", + "average_household_income_change": 897.709921417864, + "relative_household_income_change": 0.7014147411138223, + "winner_percentage": 0.2848775149342192, + "loser_percentage": 0.3324586260623994, + "no_change_percentage": 0.8577746284838489, + "population": 1343769.0691192998 + }, + { + "district": "SC-05", + "average_household_income_change": 931.9711004520146, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.9517118339588264, + "loser_percentage": 0.21759914654466395, + "no_change_percentage": 0.5180028856504914, + "population": 1009850.8155595793 + }, + { + "district": "SC-06", + "average_household_income_change": 1795.8222332940825, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.852897153549233, + "loser_percentage": 0.8048781565393026, + "no_change_percentage": 0.16201608908649556, + "population": 49066.04191148456 + }, + { + "district": "SC-07", + "average_household_income_change": 1857.6974684671775, + "relative_household_income_change": -0.0, + "winner_percentage": 0.6818888391172473, + "loser_percentage": 0.10539479653499773, + "no_change_percentage": 0.10947920866386618, + "population": 1474599.5751547609 + }, + { + "district": "SD-01", + "average_household_income_change": -185.12946706296242, + "relative_household_income_change": -0.0, + "winner_percentage": 0.9583114599271013, + "loser_percentage": 0.8566897788956356, + "no_change_percentage": 0.49133982229752937, + "population": 1025155.0366304349 + }, + { + "district": "TN-01", + "average_household_income_change": 1990.8502151773625, + "relative_household_income_change": 0.08071195025176936, + "winner_percentage": 0.1424522722051551, + "loser_percentage": 0.2501611832548506, + "no_change_percentage": 0.7393905997045908, + "population": 509389.427303286 + }, + { + "district": "TN-02", + "average_household_income_change": 971.2647989363505, + "relative_household_income_change": 0.0, + "winner_percentage": 0.8322193743039388, + "loser_percentage": 0.7729427687676738, + "no_change_percentage": 0.6847091596468332, + "population": 44818.485711245215 + }, + { + "district": "TN-03", + "average_household_income_change": 211.71389701787734, + "relative_household_income_change": -3.5e-9, + "winner_percentage": 0.4102747777269825, + "loser_percentage": 0.1076519599220832, + "no_change_percentage": 0.4359652614253863, + "population": 612016.9535068158 + }, + { + "district": "TN-04", + "average_household_income_change": -1166.3652707529218, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.6121302979479828, + "loser_percentage": 0.4740172036626341, + "no_change_percentage": 0.31505716327074385, + "population": 1814735.1803401406 + }, + { + "district": "TN-05", + "average_household_income_change": -1710.819262182215, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.38390327544462677, + "loser_percentage": 0.3353685612318471, + "no_change_percentage": 0.004715856283499242, + "population": 190008.9265465967 + }, + { + "district": "TN-06", + "average_household_income_change": 197.01400925287825, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.7802816388354746, + "loser_percentage": 0.7305906386275102, + "no_change_percentage": 0.29038385863341176, + "population": 1900723.3659439501 + }, + { + "district": "TN-07", + "average_household_income_change": 211.41923929555918, + "relative_household_income_change": 0.0015568199371647218, + "winner_percentage": 0.20229323028117163, + "loser_percentage": 0.022150695649819307, + "no_change_percentage": 0.8006018451087608, + "population": 184644.49612084823 + }, + { + "district": "TN-08", + "average_household_income_change": 1328.484630047538, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.818603043336867, + "loser_percentage": 0.9312811484394016, + "no_change_percentage": 0.4553042462854815, + "population": 236288.20602635806 + }, + { + "district": "TN-09", + "average_household_income_change": 855.8315869415694, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.5605413938252272, + "loser_percentage": 0.47705405595659556, + "no_change_percentage": 0.630088073594293, + "population": 1413809.7312156651 + }, + { + "district": "TX-01", + "average_household_income_change": 1771.1915705224733, + "relative_household_income_change": -3.5e-9, + "winner_percentage": 0.8751630156858404, + "loser_percentage": 0.9114745108775637, + "no_change_percentage": 0.3566363032064842, + "population": 1142428.890069966 + }, + { + "district": "TX-02", + "average_household_income_change": -1920.1601722975875, + "relative_household_income_change": 0.12208181487092995, + "winner_percentage": 0.4552730089959446, + "loser_percentage": 0.13482867731225923, + "no_change_percentage": 0.27201447248401667, + "population": 979537.4973681483 + }, + { + "district": "TX-03", + "average_household_income_change": 1016.9133388870835, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.9864993640141612, + "loser_percentage": 0.32025950019262006, + "no_change_percentage": 0.3573404493437041, + "population": 137241.399852384 + }, + { + "district": "TX-04", + "average_household_income_change": 1892.9127819556993, + "relative_household_income_change": -3.5e-9, + "winner_percentage": 0.8989800061359351, + "loser_percentage": 0.6689276605507882, + "no_change_percentage": 0.8953958061825441, + "population": 829341.8250034208 + }, + { + "district": "TX-05", + "average_household_income_change": 1897.0403281518222, + "relative_household_income_change": 0.7958420854245689, + "winner_percentage": 0.25572293996702045, + "loser_percentage": 0.41508734432727257, + "no_change_percentage": 0.32680578798631954, + "population": 1246583.3372938028 + }, + { + "district": "TX-06", + "average_household_income_change": -1006.7452094515037, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.31716495088768626, + "loser_percentage": 0.41932200244509976, + "no_change_percentage": 0.5052989869058244, + "population": 114900.41963940545 + }, + { + "district": "TX-07", + "average_household_income_change": -986.750860859265, + "relative_household_income_change": -3.5e-9, + "winner_percentage": 0.057531609216056045, + "loser_percentage": 0.11214276134254297, + "no_change_percentage": 0.8670485270497249, + "population": 1189524.561694502 + }, + { + "district": "TX-08", + "average_household_income_change": 468.61581361870196, + "relative_household_income_change": -3.5e-9, + "winner_percentage": 0.15544793198009388, + "loser_percentage": 0.23765541453250072, + "no_change_percentage": 0.6203152864878174, + "population": 1553341.3028538858 + }, + { + "district": "TX-09", + "average_household_income_change": 592.3138853555479, + "relative_household_income_change": -3.5e-9, + "winner_percentage": 0.09526139620272689, + "loser_percentage": 0.6789476722459857, + "no_change_percentage": 0.8930914340790302, + "population": 650602.021581664 + }, + { + "district": "TX-10", + "average_household_income_change": -771.8822058271178, + "relative_household_income_change": -3.5e-9, + "winner_percentage": 0.7667801354023313, + "loser_percentage": 0.4397946703112, + "no_change_percentage": 0.6944012866100824, + "population": 1514675.1003138293 + }, + { + "district": "TX-11", + "average_household_income_change": 445.10938641772714, + "relative_household_income_change": 0.7661649830512469, + "winner_percentage": 0.4350632876947641, + "loser_percentage": 0.9852093398616844, + "no_change_percentage": 0.02306253066745889, + "population": 536280.1697764277 + }, + { + "district": "TX-12", + "average_household_income_change": -1723.4154822526245, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.03244025476786705, + "loser_percentage": 0.9614424944997229, + "no_change_percentage": 0.4952649603765471, + "population": 1906516.5371909686 + }, + { + "district": "TX-13", + "average_household_income_change": 1812.3135179699345, + "relative_household_income_change": 0.9502675017988578, + "winner_percentage": 0.21105628812509547, + "loser_percentage": 0.31887128979074797, + "no_change_percentage": 0.4497497380723805, + "population": 562688.9379618007 + }, + { + "district": "TX-14", + "average_household_income_change": -862.4498626305681, + "relative_household_income_change": 0.0, + "winner_percentage": 0.5468959965169081, + "loser_percentage": 0.25935447600951667, + "no_change_percentage": 0.7624524603063794, + "population": 1249745.2596928063 + }, + { + "district": "TX-15", + "average_household_income_change": 1134.5925667142494, + "relative_household_income_change": -0.0, + "winner_percentage": 0.18858944824948876, + "loser_percentage": 0.6909012927595274, + "no_change_percentage": 0.79550145373388, + "population": 1284249.0165737546 + }, + { + "district": "TX-16", + "average_household_income_change": -94.51012579706753, + "relative_household_income_change": 0.0, + "winner_percentage": 0.0481356954979375, + "loser_percentage": 0.029640494303868503, + "no_change_percentage": 0.08919240436367959, + "population": 154477.28857511468 + }, + { + "district": "TX-17", + "average_household_income_change": 123.32877219063931, + "relative_household_income_change": -0.0, + "winner_percentage": 0.8167313479183358, + "loser_percentage": 0.4250737287064854, + "no_change_percentage": 0.6504954644323904, + "population": 1123673.307339278 + }, + { + "district": "TX-18", + "average_household_income_change": 1474.4750546742705, + "relative_household_income_change": -0.0, + "winner_percentage": 0.3096230476943209, + "loser_percentage": 0.6586386549698358, + "no_change_percentage": 0.10163494198560052, + "population": 36032.47793310054 + }, + { + "district": "TX-19", + "average_household_income_change": -36.34491580021493, + "relative_household_income_change": 0.0, + "winner_percentage": 0.17522246712590916, + "loser_percentage": 0.7155230138235702, + "no_change_percentage": 0.9265095903708955, + "population": 1892844.0312474421 + }, + { + "district": "TX-20", + "average_household_income_change": 482.6199015754944, + "relative_household_income_change": 0.0, + "winner_percentage": 0.04341115956437347, + "loser_percentage": 0.5589910741196304, + "no_change_percentage": 0.4497429279862738, + "population": 989503.7761538144 + }, + { + "district": "TX-21", + "average_household_income_change": -612.6131101039554, + "relative_household_income_change": 0.0, + "winner_percentage": 0.4466640199476205, + "loser_percentage": 0.9878969837278956, + "no_change_percentage": 0.8386056028138273, + "population": 222734.239231813 + }, + { + "district": "TX-22", + "average_household_income_change": 148.9376439441039, + "relative_household_income_change": 0.0, + "winner_percentage": 0.20146267050549793, + "loser_percentage": 0.8518191979985624, + "no_change_percentage": 0.38611458542964494, + "population": 1819989.6572932268 + }, + { + "district": "TX-23", + "average_household_income_change": -473.62444502771825, + "relative_household_income_change": -0.0, + "winner_percentage": 0.2441475454205131, + "loser_percentage": 0.9219497484248206, + "no_change_percentage": 0.5222034568292102, + "population": 10823.250447892933 + }, + { + "district": "TX-24", + "average_household_income_change": -1672.3682809212992, + "relative_household_income_change": 0.07985271423887697, + "winner_percentage": 0.5084063876062761, + "loser_percentage": 0.7220018931521209, + "no_change_percentage": 0.2215680200641278, + "population": 1595642.3387817296 + }, + { + "district": "TX-25", + "average_household_income_change": 1077.5688699725806, + "relative_household_income_change": -3.5e-9, + "winner_percentage": 0.24499324827021263, + "loser_percentage": 0.01432222664134064, + "no_change_percentage": 0.8939382050641294, + "population": 1787983.1005429467 + }, + { + "district": "TX-26", + "average_household_income_change": -1438.4307054370513, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.6198227349896034, + "loser_percentage": 0.11800847290362171, + "no_change_percentage": 0.009304095159581083, + "population": 876845.671226172 + }, + { + "district": "TX-27", + "average_household_income_change": 1340.9013998003868, + "relative_household_income_change": 0.3019592228300463, + "winner_percentage": 0.28964951902839375, + "loser_percentage": 0.7622993632880837, + "no_change_percentage": 0.614048893466411, + "population": 123347.98733697983 + }, + { + "district": "TX-28", + "average_household_income_change": 488.0047599682156, + "relative_household_income_change": -3.5e-9, + "winner_percentage": 0.9402775258918264, + "loser_percentage": 0.9393313495884833, + "no_change_percentage": 0.37357540068239203, + "population": 438695.46877367457 + }, + { + "district": "TX-29", + "average_household_income_change": 1036.8306845711284, + "relative_household_income_change": -3.5e-9, + "winner_percentage": 0.025297254401102753, + "loser_percentage": 0.7802251539465428, + "no_change_percentage": 0.6236464207364651, + "population": 1735638.9703092447 + }, + { + "district": "TX-30", + "average_household_income_change": -1816.620642287472, + "relative_household_income_change": 0.0, + "winner_percentage": 0.2371013107937745, + "loser_percentage": 0.611306274602615, + "no_change_percentage": 0.8355836741413932, + "population": 910562.3826486651 + }, + { + "district": "TX-31", + "average_household_income_change": 681.3583160127758, + "relative_household_income_change": 0.0, + "winner_percentage": 0.008027992944522722, + "loser_percentage": 0.5828667622610165, + "no_change_percentage": 0.024280868889418383, + "population": 616179.7522015433 + }, + { + "district": "TX-32", + "average_household_income_change": -785.7929442762619, + "relative_household_income_change": 0.0, + "winner_percentage": 0.6420402033057935, + "loser_percentage": 0.40296422224895634, + "no_change_percentage": 0.17046871016524834, + "population": 762591.0685096306 + }, + { + "district": "TX-33", + "average_household_income_change": 336.01806354446273, + "relative_household_income_change": 0.0, + "winner_percentage": 0.9774601220731014, + "loser_percentage": 0.5795747826478493, + "no_change_percentage": 0.06407656228653436, + "population": 1669168.5241341875 + }, + { + "district": "TX-34", + "average_household_income_change": -1683.0786772779436, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.8589802594733764, + "loser_percentage": 0.5004712894867026, + "no_change_percentage": 0.8681841973260737, + "population": 695506.4088603129 + }, + { + "district": "TX-35", + "average_household_income_change": -645.2997247970522, + "relative_household_income_change": -3.5e-9, + "winner_percentage": 0.037310115037405334, + "loser_percentage": 0.05650574967910238, + "no_change_percentage": 0.6290940416189846, + "population": 1123262.8945596083 + }, + { + "district": "TX-36", + "average_household_income_change": -1181.8042866717713, + "relative_household_income_change": 0.1539846603505851, + "winner_percentage": 0.8433985352622048, + "loser_percentage": 0.3449587698057731, + "no_change_percentage": 0.6164753452177081, + "population": 584047.538738149 + }, + { + "district": "TX-37", + "average_household_income_change": -773.9294231231523, + "relative_household_income_change": 0.0, + "winner_percentage": 0.43736613788104073, + "loser_percentage": 0.3930416960662526, + "no_change_percentage": 0.49201046742835874, + "population": 379840.7069587959 + }, + { + "district": "TX-38", + "average_household_income_change": 1856.1006064111475, + "relative_household_income_change": -0.0, + "winner_percentage": 0.1472091366732724, + "loser_percentage": 0.5111329976782713, + "no_change_percentage": 0.802506694325617, + "population": 1058823.7384297766 + }, + { + "district": "UT-01", + "average_household_income_change": 538.9230690131752, + "relative_household_income_change": -0.0, + "winner_percentage": 0.8078746504361951, + "loser_percentage": 0.9086907148230051, + "no_change_percentage": 0.41718805953400595, + "population": 744308.05743929 + }, + { + "district": "UT-02", + "average_household_income_change": 625.4079449694609, + "relative_household_income_change": -3.5e-9, + "winner_percentage": 0.9719555970079679, + "loser_percentage": 0.7046548863901538, + "no_change_percentage": 0.4750052548308249, + "population": 1194783.1107481858 + }, + { + "district": "UT-03", + "average_household_income_change": -1995.7045903511234, + "relative_household_income_change": -0.0, + "winner_percentage": 0.05076764633301312, + "loser_percentage": 0.9114782823193239, + "no_change_percentage": 0.4413152091515967, + "population": 362227.6352435327 + }, + { + "district": "UT-04", + "average_household_income_change": -677.9393110516531, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.37380705077204834, + "loser_percentage": 0.15795234703252115, + "no_change_percentage": 0.2040000223666747, + "population": 1494796.9803889361 + }, + { + "district": "VT-01", + "average_household_income_change": 353.4738828261714, + "relative_household_income_change": 0.0, + "winner_percentage": 0.8532040557443087, + "loser_percentage": 0.2235960450042347, + "no_change_percentage": 0.20134550743715096, + "population": 953075.3632854001 + }, + { + "district": "VA-01", + "average_household_income_change": 778.0368366974453, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.36308011279451313, + "loser_percentage": 0.15114920586672909, + "no_change_percentage": 0.8882407670893311, + "population": 1490063.1040169136 + }, + { + "district": "VA-02", + "average_household_income_change": -1010.0022195655356, + "relative_household_income_change": -0.0, + "winner_percentage": 0.399603834907748, + "loser_percentage": 0.9509916921568538, + "no_change_percentage": 0.9225239801101054, + "population": 684844.1720984051 + }, + { + "district": "VA-03", + "average_household_income_change": 1160.5277807052973, + "relative_household_income_change": 0.1768590513948327, + "winner_percentage": 0.9925433691281884, + "loser_percentage": 0.9119338074690182, + "no_change_percentage": 0.11498448813031215, + "population": 671222.2659518386 + }, + { + "district": "VA-04", + "average_household_income_change": 1075.5192645445359, + "relative_household_income_change": 0.0, + "winner_percentage": 0.3117099809717838, + "loser_percentage": 0.18532163428785997, + "no_change_percentage": 0.8815658664157163, + "population": 651704.0237652881 + }, + { + "district": "VA-05", + "average_household_income_change": -1592.2137507489542, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.05487263637982431, + "loser_percentage": 0.7545716977655509, + "no_change_percentage": 0.42546699188341486, + "population": 1960083.0280343024 + }, + { + "district": "VA-06", + "average_household_income_change": 173.80291494289946, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.32986302289622504, + "loser_percentage": 0.9004772463524898, + "no_change_percentage": 0.27213789635182417, + "population": 1104186.0216722307 + }, + { + "district": "VA-07", + "average_household_income_change": -1168.1843187495872, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.9468439755493232, + "loser_percentage": 0.6741460863894962, + "no_change_percentage": 0.22514942250463243, + "population": 1144019.3339419388 + }, + { + "district": "VA-08", + "average_household_income_change": 1871.03639237891, + "relative_household_income_change": -0.0, + "winner_percentage": 0.2178838122898782, + "loser_percentage": 0.5505946063075128, + "no_change_percentage": 0.061186857186479204, + "population": 333578.719343903 + }, + { + "district": "VA-09", + "average_household_income_change": -1811.655724093852, + "relative_household_income_change": -0.0, + "winner_percentage": 0.13689686569124193, + "loser_percentage": 0.6687216826093308, + "no_change_percentage": 0.497092817382386, + "population": 494593.77289942297 + }, + { + "district": "VA-10", + "average_household_income_change": -815.4371158922849, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.7856146432574787, + "loser_percentage": 0.940402140652285, + "no_change_percentage": 0.2895285985773879, + "population": 1214469.82023329 + }, + { + "district": "VA-11", + "average_household_income_change": -360.1121235607505, + "relative_household_income_change": -0.0, + "winner_percentage": 0.3753365275814715, + "loser_percentage": 0.6813036121555542, + "no_change_percentage": 0.8724926283246953, + "population": 707703.9404915355 + }, + { + "district": "WA-01", + "average_household_income_change": 105.63506368520504, + "relative_household_income_change": -0.0, + "winner_percentage": 0.43902152935839744, + "loser_percentage": 0.11987463568444745, + "no_change_percentage": 0.9262362054297277, + "population": 1268970.990725781 + }, + { + "district": "WA-02", + "average_household_income_change": 1691.1267713793006, + "relative_household_income_change": -0.0, + "winner_percentage": 0.8109962062353352, + "loser_percentage": 0.5735816744632423, + "no_change_percentage": 0.36983592279142374, + "population": 1370317.1348295836 + }, + { + "district": "WA-03", + "average_household_income_change": 40.5972770329508, + "relative_household_income_change": 0.9835896952422006, + "winner_percentage": 0.4652226252562398, + "loser_percentage": 0.7078615262701772, + "no_change_percentage": 0.8071584891291584, + "population": 872059.7943409345 + }, + { + "district": "WA-04", + "average_household_income_change": 1732.5251561029313, + "relative_household_income_change": -0.0, + "winner_percentage": 0.7946573412175163, + "loser_percentage": 0.9188465382642514, + "no_change_percentage": 0.5385030078329925, + "population": 1632884.0302181193 + }, + { + "district": "WA-05", + "average_household_income_change": 1202.1063187299212, + "relative_household_income_change": -3.5e-9, + "winner_percentage": 0.757030017005171, + "loser_percentage": 0.3806079639722343, + "no_change_percentage": 0.42515199640370005, + "population": 931161.6787912422 + }, + { + "district": "WA-06", + "average_household_income_change": -41.683066187413246, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.7419630561106269, + "loser_percentage": 0.7982884089457194, + "no_change_percentage": 0.5766984839678304, + "population": 1925306.5372831763 + }, + { + "district": "WA-07", + "average_household_income_change": -1038.8288175164387, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.7487836469612043, + "loser_percentage": 0.04627926690743911, + "no_change_percentage": 0.7637763617204205, + "population": 1394007.9334284214 + }, + { + "district": "WA-08", + "average_household_income_change": -113.39026359794602, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.14656233016666997, + "loser_percentage": 0.14227889496061186, + "no_change_percentage": 0.8942400203221307, + "population": 1159468.3679830425 + }, + { + "district": "WA-09", + "average_household_income_change": -1188.6320903149917, + "relative_household_income_change": -0.0, + "winner_percentage": 0.6848291117385173, + "loser_percentage": 0.7192944917615914, + "no_change_percentage": 0.47453869785998914, + "population": 1237632.7477468404 + }, + { + "district": "WA-10", + "average_household_income_change": -1918.8638263145253, + "relative_household_income_change": -0.0, + "winner_percentage": 0.9811299633185824, + "loser_percentage": 0.07117563047989073, + "no_change_percentage": 0.40085829518483473, + "population": 1658622.2639309997 + }, + { + "district": "WV-01", + "average_household_income_change": -1719.9286068807128, + "relative_household_income_change": -0.0, + "winner_percentage": 0.9148158153481513, + "loser_percentage": 0.08663114488601364, + "no_change_percentage": 0.4853402444158086, + "population": 1344776.2874544123 + }, + { + "district": "WV-02", + "average_household_income_change": -1825.9565032373657, + "relative_household_income_change": 0.0, + "winner_percentage": 0.9883328689997977, + "loser_percentage": 0.1932626210579047, + "no_change_percentage": 0.17022618841907056, + "population": 1867594.7605861642 + }, + { + "district": "WI-01", + "average_household_income_change": 1290.4459829291638, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.18361453960505825, + "loser_percentage": 0.5292730478053601, + "no_change_percentage": 0.25849761902750124, + "population": 1729840.943088221 + }, + { + "district": "WI-02", + "average_household_income_change": 1181.9427409174762, + "relative_household_income_change": 0.6753359662801989, + "winner_percentage": 0.9024734844569519, + "loser_percentage": 0.7123801306820899, + "no_change_percentage": 0.497654118406206, + "population": 212370.7586732047 + }, + { + "district": "WI-03", + "average_household_income_change": -1899.8950693658596, + "relative_household_income_change": -3.5e-9, + "winner_percentage": 0.6429595737137347, + "loser_percentage": 0.7202951055596833, + "no_change_percentage": 0.15965232924903816, + "population": 1248918.761505698 + }, + { + "district": "WI-04", + "average_household_income_change": -1923.8872113506757, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.7134800021365812, + "loser_percentage": 0.16077300392286054, + "no_change_percentage": 0.4204664571222778, + "population": 529063.6749248685 + }, + { + "district": "WI-05", + "average_household_income_change": -1150.9174218021424, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.2447208698368899, + "loser_percentage": 0.6477205033828267, + "no_change_percentage": 0.2917078822429261, + "population": 591469.1625126833 + }, + { + "district": "WI-06", + "average_household_income_change": 1122.465409431541, + "relative_household_income_change": -3.5e-9, + "winner_percentage": 0.030952864425620397, + "loser_percentage": 0.13790808032567214, + "no_change_percentage": 0.1335488088157848, + "population": 375057.91329466144 + }, + { + "district": "WI-07", + "average_household_income_change": 514.946210223933, + "relative_household_income_change": -3.5e-9, + "winner_percentage": 0.36936029678754523, + "loser_percentage": 0.3861623591027703, + "no_change_percentage": 0.6236829834736486, + "population": 441020.0640803472 + }, + { + "district": "WI-08", + "average_household_income_change": -1220.801385442289, + "relative_household_income_change": 0.13138239333980972, + "winner_percentage": 0.9148413673253681, + "loser_percentage": 0.2235683708974472, + "no_change_percentage": 0.1651680949063037, + "population": 320289.09370709525 + }, + { + "district": "WY-01", + "average_household_income_change": 541.4347808810725, + "relative_household_income_change": -3.5e-9, + "winner_percentage": 0.33422766415601324, + "loser_percentage": 0.7974131376543324, + "no_change_percentage": 0.10343429179638364, + "population": 547664.9796359495 + } + ] + }, + "cliff_impact": { + "baseline": { + "cliff_gap": 19000000000.0, + "cliff_share": 0.0712 + }, + "reform": { + "cliff_gap": 20500000000.0, + "cliff_share": 0.0698 + } + } +} diff --git a/libs/policyengine-simulation-persistence/tests/fixtures/economy_results/us_state_ca_2026.json b/libs/policyengine-simulation-persistence/tests/fixtures/economy_results/us_state_ca_2026.json new file mode 100644 index 000000000..bc742c76c --- /dev/null +++ b/libs/policyengine-simulation-persistence/tests/fixtures/economy_results/us_state_ca_2026.json @@ -0,0 +1,760 @@ +{ + "spm_provenance": { + "schema_version": "canonical-spm-comparison-v2", + "baseline": { + "receipt": { + "schema_version": "canonical-spm-provenance-v2", + "forecast_id": "spm-forecast-2022-2036", + "forecast_sha256": "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef", + "scenario": "central", + "geography_kind": "county", + "geography_id": null, + "county_vintage": "2020", + "as_of": null, + "years": [ + "2026" + ], + "runtime_versions": { + "policyengine": "6.10.0", + "policyengine-core": "3.20.0", + "policyengine-us": "1.715.2", + "spm-calculator": "0.4.1" + } + }, + "execution_count": 2 + }, + "reform": { + "receipt": { + "schema_version": "canonical-spm-provenance-v2", + "forecast_id": "spm-forecast-2022-2036", + "forecast_sha256": "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef", + "scenario": "central", + "geography_kind": "county", + "geography_id": null, + "county_vintage": "2020", + "as_of": null, + "years": [ + "2026" + ], + "runtime_versions": { + "policyengine": "6.10.0", + "policyengine-core": "3.20.0", + "policyengine-us": "1.715.2", + "spm-calculator": "0.4.1" + } + }, + "execution_count": 2 + } + }, + "model_version": "1.715.2", + "data_version": "1.115.5", + "budget": { + "tax_revenue_impact": 89565497411.86987, + "state_tax_revenue_impact": -886897264.5463827, + "benefit_spending_impact": -83025600968.21567, + "budgetary_impact": 91206854377.84988, + "households": 136709977.562589, + "baseline_net_income": 12471939978137.047 + }, + "detailed_budget": { + "income_tax": { + "baseline": 339460802.8804418, + "reform": -383727084.8217116, + "difference": 211888331.35692486 + }, + "snap": { + "baseline": 213603467.2816758, + "reform": 162408034.22400618, + "difference": -683234259.4903889 + }, + "eitc": { + "baseline": -138660719.4174627, + "reform": -212936359.58925727, + "difference": 446024162.4749317 + }, + "ctc": { + "baseline": 989639125.8994855, + "reform": 898790946.1864872, + "difference": 88354094.85864165 + }, + "ssi": { + "baseline": -110291622.54829283, + "reform": -463518516.70134383, + "difference": -928151341.2142848 + }, + "state_income_tax": { + "baseline": -945110285.818362, + "reform": -70212275.80537581, + "difference": -363069744.29264516 + } + }, + "decile": { + "average": { + "1": -719.9104685957303, + "2": 2350.7367469697247, + "3": 154.51661487616985, + "4": 363.06216615899325, + "5": -1583.2595573096276, + "6": -2856.8515251553067, + "7": -1049.1424274330398, + "8": -2179.8156420812, + "9": 61.34307502320691, + "10": 2992.101409155312 + }, + "relative": { + "1": -0.0, + "2": -3.5e-9, + "3": 0.7967599214216395, + "4": 1e-12, + "5": 1e-12, + "6": -3.5e-9, + "7": -3.5e-9, + "8": -3.5e-9, + "9": -0.0, + "10": -3.5e-9 + } + }, + "inequality": { + "gini": { + "baseline": 0.5008410626306549, + "reform": 0.8315244897918123 + }, + "top_10_pct_share": { + "baseline": 0.3539242048687159, + "reform": 0.8828509185812531 + }, + "top_1_pct_share": { + "baseline": 0.8997005887566257, + "reform": 0.46101216488163765 + } + }, + "poverty": { + "poverty": { + "child": { + "baseline": 0.5677050704202443, + "reform": 0.9203304391919288 + }, + "adult": { + "baseline": 0.7237729538720183, + "reform": 0.48660855486158505 + }, + "senior": { + "baseline": 0.22181101099101086, + "reform": 0.324667243768898 + }, + "all": { + "baseline": 0.6995716380702436, + "reform": 0.16606968549412615 + } + }, + "deep_poverty": { + "child": { + "baseline": 0.9079404966260946, + "reform": 0.26813751289981635 + }, + "adult": { + "baseline": 0.9113778358680468, + "reform": 0.3095631249494607 + }, + "senior": { + "baseline": 0.957361711556158, + "reform": 0.7062058063676047 + }, + "all": { + "baseline": 0.5042488169833176, + "reform": 0.5177477561485521 + } + } + }, + "poverty_by_gender": { + "poverty": { + "male": { + "baseline": 0.6514143989667908, + "reform": 0.5879447117944846 + }, + "female": { + "baseline": 0.3118443245510002, + "reform": 0.20781847453792723 + } + }, + "deep_poverty": { + "male": { + "baseline": 0.5118916583552825, + "reform": 0.9341543591337786 + }, + "female": { + "baseline": 0.6232650867258723, + "reform": 0.0753753690740454 + } + } + }, + "poverty_by_race": { + "poverty": { + "white": { + "baseline": 0.8203999947120169, + "reform": 0.7259492874772981 + }, + "black": { + "baseline": 0.9076536209513208, + "reform": 0.1914027333041175 + }, + "hispanic": { + "baseline": 0.7447827242773541, + "reform": 0.058758896398655724 + }, + "other": { + "baseline": 0.6529099274345497, + "reform": 0.27309973233714935 + } + } + }, + "intra_decile": { + "deciles": { + "Gain more than 5%": [ + 0.22661652924476305, + 0.8754911714482378, + 0.10626598264552489, + 0.52236266535893, + 0.853943007184872, + 0.2448319779690169, + 0.2104789386956465, + 0.8805817593662799, + 0.42291764838969603, + 0.7169610989049753 + ], + "Gain less than 5%": [ + 0.03187307012674512, + 0.36235691130324066, + 0.17188099212573238, + 0.6727654414135418, + 0.08290317740457553, + 0.9545621653457477, + 0.025344714826901038, + 0.7294235074418041, + 0.02114486972315066, + 0.2556900540574426 + ], + "No change": [ + 0.8133543874022758, + 0.1571182886867749, + 0.1837388092509762, + 0.6914954260135907, + 0.38556588135256054, + 0.043160995797499324, + 0.9900015462028011, + 0.15142010875655154, + 0.03626899424341401, + 0.34420100553679467 + ], + "Lose less than 5%": [ + 0.6152394833248576, + 0.7424596231257796, + 0.11311490301807692, + 0.33721377319664525, + 0.03081085762668856, + 0.448653262492294, + 0.7659699365880781, + 0.7399466637207005, + 0.9020201583500368, + 0.7556621536750643 + ], + "Lose more than 5%": [ + 0.8624457763254278, + 0.7053451400507655, + 0.4727795120983127, + 0.22552757034788762, + 0.6608284986570139, + 0.3163059267282592, + 0.10204910504969822, + 0.44782186141915115, + 0.8747630413479673, + 0.12753646461878787 + ] + }, + "all": { + "Gain more than 5%": 0.5849556981106074, + "Gain less than 5%": 0.3929525501051674, + "No change": 0.5148026967641771, + "Lose less than 5%": 0.14382946397694396, + "Lose more than 5%": 0.9597311864871608 + } + }, + "wealth_decile": null, + "intra_wealth_decile": null, + "labor_supply_response": null, + "constituency_impact": null, + "local_authority_impact": null, + "congressional_district_impact": { + "districts": [ + { + "district": "CA-01", + "average_household_income_change": -1340.202080667208, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.4791004720574512, + "loser_percentage": 0.21601434789390284, + "no_change_percentage": 0.7926333582002464, + "population": 1615708.6039068555 + }, + { + "district": "CA-02", + "average_household_income_change": 49.8249585503725, + "relative_household_income_change": -0.0, + "winner_percentage": 0.7884035185216414, + "loser_percentage": 0.014121348940183798, + "no_change_percentage": 0.9327781318527646, + "population": 856382.2369167916 + }, + { + "district": "CA-03", + "average_household_income_change": -1420.3115763142403, + "relative_household_income_change": -0.0, + "winner_percentage": 0.6939185190374807, + "loser_percentage": 0.43685591964096726, + "no_change_percentage": 0.9953730235896091, + "population": 1541402.9341196942 + }, + { + "district": "CA-04", + "average_household_income_change": -372.9236836466168, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.5401493571516298, + "loser_percentage": 0.6939154052422181, + "no_change_percentage": 0.6488161903021046, + "population": 1875821.4170999322 + }, + { + "district": "CA-05", + "average_household_income_change": -1907.1033848877832, + "relative_household_income_change": 0.0, + "winner_percentage": 0.1248771012471086, + "loser_percentage": 0.9279438631202989, + "no_change_percentage": 0.45312759400232583, + "population": 1104005.7499476979 + }, + { + "district": "CA-06", + "average_household_income_change": -628.3143043117749, + "relative_household_income_change": -0.0, + "winner_percentage": 0.6651080998565223, + "loser_percentage": 0.4699420173904715, + "no_change_percentage": 0.8201443868492999, + "population": 149246.67448191857 + }, + { + "district": "CA-07", + "average_household_income_change": -1210.490429146224, + "relative_household_income_change": 0.6737943587360455, + "winner_percentage": 0.988819150103311, + "loser_percentage": 0.07092682363448932, + "no_change_percentage": 0.5601229852164192, + "population": 1117885.1846906256 + }, + { + "district": "CA-08", + "average_household_income_change": -447.9625165140804, + "relative_household_income_change": -0.0, + "winner_percentage": 0.8875597159253288, + "loser_percentage": 0.40960169056048457, + "no_change_percentage": 0.3652205463834728, + "population": 902643.2559108599 + }, + { + "district": "CA-09", + "average_household_income_change": -456.8892622604417, + "relative_household_income_change": -3.5e-9, + "winner_percentage": 0.2657046394559417, + "loser_percentage": 0.8341206393633971, + "no_change_percentage": 0.15894373296270192, + "population": 1431995.9281805663 + }, + { + "district": "CA-10", + "average_household_income_change": 1929.5672028067936, + "relative_household_income_change": 0.0, + "winner_percentage": 0.5504308983637247, + "loser_percentage": 0.7481760198039773, + "no_change_percentage": 0.22203302064179198, + "population": 1217802.7826345137 + }, + { + "district": "CA-11", + "average_household_income_change": 225.94800531849612, + "relative_household_income_change": -0.0, + "winner_percentage": 0.6696762455261636, + "loser_percentage": 0.626497070105428, + "no_change_percentage": 0.8336585978200555, + "population": 664756.392637095 + }, + { + "district": "CA-12", + "average_household_income_change": 1047.4084793697762, + "relative_household_income_change": -0.0, + "winner_percentage": 0.10327322906771608, + "loser_percentage": 0.06564394327349787, + "no_change_percentage": 0.8136958418340839, + "population": 1554037.175010373 + }, + { + "district": "CA-13", + "average_household_income_change": -500.4977834258955, + "relative_household_income_change": 0.6833517926685315, + "winner_percentage": 0.8986976344732958, + "loser_percentage": 0.9582801181193664, + "no_change_percentage": 0.40701465992468444, + "population": 1978219.2582351891 + }, + { + "district": "CA-14", + "average_household_income_change": 1845.7190615493287, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.4909118600646697, + "loser_percentage": 0.37556014706891894, + "no_change_percentage": 0.24720779013847893, + "population": 1752289.2094533443 + }, + { + "district": "CA-15", + "average_household_income_change": -1350.8297335560103, + "relative_household_income_change": -3.5e-9, + "winner_percentage": 0.7739166225598225, + "loser_percentage": 0.48317292375438614, + "no_change_percentage": 0.8369988075493334, + "population": 104347.25662033516 + }, + { + "district": "CA-16", + "average_household_income_change": -968.0935544244576, + "relative_household_income_change": -3.5e-9, + "winner_percentage": 0.24859453119806696, + "loser_percentage": 0.39452527515181346, + "no_change_percentage": 0.8703856344378171, + "population": 1290870.9481231153 + }, + { + "district": "CA-17", + "average_household_income_change": -1415.5413513348383, + "relative_household_income_change": -3.5e-9, + "winner_percentage": 0.049402104707172434, + "loser_percentage": 0.13958869843838762, + "no_change_percentage": 0.6502503344835922, + "population": 1822890.3670401648 + }, + { + "district": "CA-18", + "average_household_income_change": -83.73355781139668, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.7952183049458383, + "loser_percentage": 0.8814528015908482, + "no_change_percentage": 0.6013557819482931, + "population": 852164.9909683842 + }, + { + "district": "CA-19", + "average_household_income_change": 324.5580465373026, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.13879509668301637, + "loser_percentage": 0.5884124731718138, + "no_change_percentage": 0.13931078291129895, + "population": 1441535.0110863678 + }, + { + "district": "CA-20", + "average_household_income_change": -470.5363903850697, + "relative_household_income_change": 0.0, + "winner_percentage": 0.2644210278517495, + "loser_percentage": 0.3261696595241047, + "no_change_percentage": 0.24976541736485114, + "population": 1911351.331835094 + }, + { + "district": "CA-21", + "average_household_income_change": -315.60128160724776, + "relative_household_income_change": -0.0, + "winner_percentage": 0.13353777782594412, + "loser_percentage": 0.09483912882924739, + "no_change_percentage": 0.09393882890552552, + "population": 50634.006287708646 + }, + { + "district": "CA-22", + "average_household_income_change": -212.57815402313707, + "relative_household_income_change": 0.0, + "winner_percentage": 0.6553232690791773, + "loser_percentage": 0.12652804183979316, + "no_change_percentage": 0.5386586184955431, + "population": 648553.7647646856 + }, + { + "district": "CA-23", + "average_household_income_change": -24.53294730317035, + "relative_household_income_change": -0.0, + "winner_percentage": 0.1815753145809701, + "loser_percentage": 0.857494044138571, + "no_change_percentage": 0.20162091933172333, + "population": 1488396.6527884605 + }, + { + "district": "CA-24", + "average_household_income_change": 1028.2245590144817, + "relative_household_income_change": 0.6038979940926733, + "winner_percentage": 0.8738689850685158, + "loser_percentage": 0.7742488313963415, + "no_change_percentage": 0.7907254914134034, + "population": 15645.68858814286 + }, + { + "district": "CA-25", + "average_household_income_change": -144.4811563353863, + "relative_household_income_change": 0.0634914219225714, + "winner_percentage": 0.17529714744120328, + "loser_percentage": 0.7114876004555625, + "no_change_percentage": 0.2529059496820111, + "population": 1393466.1836204943 + }, + { + "district": "CA-26", + "average_household_income_change": -745.5308811125443, + "relative_household_income_change": -3.5e-9, + "winner_percentage": 0.15617347739198484, + "loser_percentage": 0.726143113529342, + "no_change_percentage": 0.9904837928341851, + "population": 1635204.4120896044 + }, + { + "district": "CA-27", + "average_household_income_change": 1212.2940882841444, + "relative_household_income_change": 0.49005924871725615, + "winner_percentage": 0.09856340695484134, + "loser_percentage": 0.6011795331541527, + "no_change_percentage": 0.5082125559059094, + "population": 1469145.2283251747 + }, + { + "district": "CA-28", + "average_household_income_change": 1868.445322419666, + "relative_household_income_change": 0.31015720435692795, + "winner_percentage": 0.5257866588071927, + "loser_percentage": 0.5606768219884671, + "no_change_percentage": 0.06372394872053855, + "population": 1629376.6398093402 + }, + { + "district": "CA-29", + "average_household_income_change": 1907.390809098553, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.6579595952720738, + "loser_percentage": 0.42027314087455103, + "no_change_percentage": 0.8679698934861128, + "population": 1303425.8793790916 + }, + { + "district": "CA-30", + "average_household_income_change": 506.1883573034174, + "relative_household_income_change": -3.5e-9, + "winner_percentage": 0.5050432802840407, + "loser_percentage": 0.94705073550179, + "no_change_percentage": 0.6798941392052675, + "population": 1411300.6359731662 + }, + { + "district": "CA-31", + "average_household_income_change": -116.47956021349427, + "relative_household_income_change": -3.5e-9, + "winner_percentage": 0.07035418767844082, + "loser_percentage": 0.024948612219243826, + "no_change_percentage": 0.6615002783679655, + "population": 84079.98453165463 + }, + { + "district": "CA-32", + "average_household_income_change": -897.6705758518216, + "relative_household_income_change": -3.5e-9, + "winner_percentage": 0.7237596916187159, + "loser_percentage": 0.45599214581860004, + "no_change_percentage": 0.23643698095484955, + "population": 770813.9915391634 + }, + { + "district": "CA-33", + "average_household_income_change": -52.86141551185253, + "relative_household_income_change": 0.0, + "winner_percentage": 0.03743134796401293, + "loser_percentage": 0.1728476844123371, + "no_change_percentage": 0.37302769509832234, + "population": 1209181.9329632234 + }, + { + "district": "CA-34", + "average_household_income_change": -1136.3743609334404, + "relative_household_income_change": 0.44974025060838185, + "winner_percentage": 0.6680286879169739, + "loser_percentage": 0.8589059159576242, + "no_change_percentage": 0.699025972338484, + "population": 1365950.6330220753 + }, + { + "district": "CA-35", + "average_household_income_change": -1018.775031530851, + "relative_household_income_change": -3.5e-9, + "winner_percentage": 0.305951912810726, + "loser_percentage": 0.3818494888010229, + "no_change_percentage": 0.524231157926504, + "population": 1422756.954866777 + }, + { + "district": "CA-36", + "average_household_income_change": 1636.3690795417276, + "relative_household_income_change": -0.0, + "winner_percentage": 0.31173263397561823, + "loser_percentage": 0.39122298893643304, + "no_change_percentage": 0.14542152800186026, + "population": 1106487.3959916614 + }, + { + "district": "CA-37", + "average_household_income_change": -1681.9329702146072, + "relative_household_income_change": -3.5e-9, + "winner_percentage": 0.7423554937763153, + "loser_percentage": 0.46234896766399936, + "no_change_percentage": 0.1082182749423255, + "population": 1912003.3408171246 + }, + { + "district": "CA-38", + "average_household_income_change": 815.8015737913117, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.3719751435635782, + "loser_percentage": 0.5816750130178863, + "no_change_percentage": 0.18881197468094058, + "population": 163990.98860082752 + }, + { + "district": "CA-39", + "average_household_income_change": -1885.6368564930008, + "relative_household_income_change": -0.0, + "winner_percentage": 0.8997208675828816, + "loser_percentage": 0.5070490702977853, + "no_change_percentage": 0.23838487713015877, + "population": 1376329.3814273335 + }, + { + "district": "CA-40", + "average_household_income_change": 864.7549563346893, + "relative_household_income_change": -3.5e-9, + "winner_percentage": 0.4669656708961981, + "loser_percentage": 0.4368809942954668, + "no_change_percentage": 0.6170923684966161, + "population": 561254.8689483237 + }, + { + "district": "CA-41", + "average_household_income_change": -1302.6132980683976, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.09895846388084228, + "loser_percentage": 0.9751742106734704, + "no_change_percentage": 0.21518936033827352, + "population": 701197.8299980335 + }, + { + "district": "CA-42", + "average_household_income_change": 517.8454200848881, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.018987857363210625, + "loser_percentage": 0.5012020362915018, + "no_change_percentage": 0.03926851151996702, + "population": 1215724.072474778 + }, + { + "district": "CA-43", + "average_household_income_change": 801.631195832408, + "relative_household_income_change": 0.0, + "winner_percentage": 0.9415549378425223, + "loser_percentage": 0.14788159798472278, + "no_change_percentage": 0.9728397004974083, + "population": 380605.45107877883 + }, + { + "district": "CA-44", + "average_household_income_change": -517.7072914107455, + "relative_household_income_change": -0.0, + "winner_percentage": 0.1349522811977817, + "loser_percentage": 0.7917141311763941, + "no_change_percentage": 0.8223465638768986, + "population": 1058831.0784220085 + }, + { + "district": "CA-45", + "average_household_income_change": -1803.3634630249749, + "relative_household_income_change": -3.5e-9, + "winner_percentage": 0.8825392168156697, + "loser_percentage": 0.24432321805596258, + "no_change_percentage": 0.5748886823831034, + "population": 1647570.443801504 + }, + { + "district": "CA-46", + "average_household_income_change": 338.45063820962815, + "relative_household_income_change": 0.0, + "winner_percentage": 0.6587134494041641, + "loser_percentage": 0.07301193535656736, + "no_change_percentage": 0.43578737154362135, + "population": 1665433.0603320487 + }, + { + "district": "CA-47", + "average_household_income_change": 1956.4619290612816, + "relative_household_income_change": -0.0, + "winner_percentage": 0.0596454627614903, + "loser_percentage": 0.8152030671131772, + "no_change_percentage": 0.6065200458135751, + "population": 1240564.5324497477 + }, + { + "district": "CA-48", + "average_household_income_change": -115.56590559409318, + "relative_household_income_change": 1e-12, + "winner_percentage": 0.1527065431306417, + "loser_percentage": 0.1534710999811163, + "no_change_percentage": 0.28797260893872434, + "population": 1279944.9805484125 + }, + { + "district": "CA-49", + "average_household_income_change": -1963.029387886932, + "relative_household_income_change": 0.0, + "winner_percentage": 0.1863473319393073, + "loser_percentage": 0.09815282134718561, + "no_change_percentage": 0.8283105804754989, + "population": 720381.8897881922 + }, + { + "district": "CA-50", + "average_household_income_change": -590.5154925954253, + "relative_household_income_change": 0.1620999651934779, + "winner_percentage": 0.4950585460308846, + "loser_percentage": 0.680757133582871, + "no_change_percentage": 0.653173233564723, + "population": 316374.24278914207 + }, + { + "district": "CA-51", + "average_household_income_change": -1583.5641255176856, + "relative_household_income_change": 0.9308651041879465, + "winner_percentage": 0.2504366070659293, + "loser_percentage": 0.1989707551215727, + "no_change_percentage": 0.19353466278177012, + "population": 1908012.2191396358 + }, + { + "district": "CA-52", + "average_household_income_change": -306.0961640384328, + "relative_household_income_change": -0.0, + "winner_percentage": 0.2137151770500293, + "loser_percentage": 0.04047780281107205, + "no_change_percentage": 0.35227293973175733, + "population": 1065100.5898863673 + } + ] + }, + "cliff_impact": null +} diff --git a/libs/policyengine-simulation-persistence/tests/result_support.py b/libs/policyengine-simulation-persistence/tests/result_support.py new file mode 100644 index 000000000..1fec3bed9 --- /dev/null +++ b/libs/policyengine-simulation-persistence/tests/result_support.py @@ -0,0 +1,111 @@ +"""Samples and builders for the result table tests. + +The sample under ``fixtures/economy_results`` holds one complete economy +result per case the plan names: US national, state and congressional district; +UK national, nation, constituency and local authority; and a budget-window +year. Each is generated, sized like a production result, with values of +varied sign and magnitude (negative zero included), because no stored real +results could be read without starting new production calculations. An +exported real result can replace any file without a code change. +""" + +from __future__ import annotations + +import json +from pathlib import Path +from typing import TYPE_CHECKING + +from policyengine_simulation_contract.macro_output import SingleYearMacroOutput +from policyengine_simulation_persistence import ( + EconomyResultLabels, + GeographyLabel, + NewReportRun, + RunTrigger, +) +from report_support import economy_report, report_store +from run_support import economy_run +from simulation_support import economy_simulation, simulation_store +from transition_support import clocked_stores + +if TYPE_CHECKING: + from policyengine_simulation_persistence import ReportRunRecord + +SAMPLE_DIRECTORY = Path(__file__).parent / "fixtures" / "economy_results" +SAMPLE_NAMES = sorted(path.stem for path in SAMPLE_DIRECTORY.glob("*.json")) + + +def load_sample(name: str) -> SingleYearMacroOutput: + """Return one sample result, validated.""" + return SingleYearMacroOutput.model_validate( + json.loads((SAMPLE_DIRECTORY / f"{name}.json").read_text(encoding="utf-8")) + ) + + +def labels_for(result: SingleYearMacroOutput) -> EconomyResultLabels: + """Return the region catalog's labels for a result, taken from the result.""" + + def labels(records, code_field: str, name_field: str): + return { + getattr(record, code_field): GeographyLabel( + name=getattr(record, name_field), x=record.x, y=record.y + ) + for record in (records.root if records is not None else []) + } + + return EconomyResultLabels( + model_version=result.model_version, + data_version=result.data_version, + constituencies=labels( + result.constituency_impact, "constituency_code", "constituency_name" + ), + local_authorities=labels( + result.local_authority_impact, + "local_authority_code", + "local_authority_name", + ), + ) + + +def comparison_ready(stores, database, rows, *, baseline=None) -> ReportRunRecord: + """Return an economy report run whose comparison step is running. + + Both simulation runs have succeeded. Pass ``baseline`` to reuse an + existing current-law simulation, as a second report on it would. + """ + simulations = simulation_store(database) + baseline = baseline or simulations.create(economy_simulation(rows, policy_id=None)) + reform = simulations.create(economy_simulation(rows)) + report = report_store(database).create(economy_report(baseline, reform)) + runs = [ + stores.runs.start_simulation_run(economy_run(simulation, rows)).run + for simulation in (baseline, reform) + ] + for run in runs: + if run.status.value == "succeeded": + continue + call_id = f"fc-{run.id}" + stores.transitions.claim_simulation_dispatch([run.id]) + stores.transitions.record_simulation_dispatched( + [run.id], modal_call_id=call_id, first_check_at=stores.clock() + ) + stores.transitions.complete_simulation_call(call_id, lambda *_: None) + report_run = stores.runs.create_report_run( + NewReportRun( + report_id=report.id, + baseline_simulation_run_id=runs[0].id, + reform_simulation_run_id=runs[1].id, + trigger=RunTrigger.INITIAL, + ) + ) + stores.transitions.claim_comparison_dispatch(report_run.id) + stores.transitions.record_comparison_dispatched( + report_run.id, + modal_call_id=f"fc-comparison-{report_run.id}", + first_check_at=stores.clock(), + ) + return report_run + + +def result_stores(database): + """Return the run store and transitions every result test uses.""" + return clocked_stores(database) diff --git a/libs/policyengine-simulation-persistence/tests/test_economy_results.py b/libs/policyengine-simulation-persistence/tests/test_economy_results.py new file mode 100644 index 000000000..80b7c8118 --- /dev/null +++ b/libs/policyengine-simulation-persistence/tests/test_economy_results.py @@ -0,0 +1,163 @@ +"""Economy results stored as rows and rebuilt exactly.""" + +from __future__ import annotations + +import pytest +from policyengine_simulation_persistence import ( + EconomyComparisonRecorder, + EconomyResultLabels, + check_storable, + create_simulation_engine, + read_economy_comparison, +) +from pydantic import ValidationError +from result_support import ( + SAMPLE_NAMES, + comparison_ready, + labels_for, + load_sample, + result_stores, +) +from simulation_support import simulation_store + +pytestmark = pytest.mark.postgres + +RECORDER = EconomyComparisonRecorder() + + +def _write(stores, report_run, result) -> None: + assert stores.transitions.complete_comparison( + report_run.id, + lambda connection, record: RECORDER.write(connection, record, result), + ) + + +def _read(database, report_run_id, labels): + engine = create_simulation_engine(database.runtime_url) + try: + with engine.connect() as connection: + return read_economy_comparison(connection, report_run_id, labels) + finally: + engine.dispose() + + +def test_the_sample_covers_every_case_the_plan_names() -> None: + assert SAMPLE_NAMES == [ + "uk_constituency_2026", + "uk_local_authority_2026", + "uk_nation_scotland_2026", + "uk_national_2026", + "us_budget_window_year_2030", + "us_congressional_district_ca_12_2026", + "us_national_2026", + "us_state_ca_2026", + ] + + +@pytest.mark.parametrize("sample_name", SAMPLE_NAMES) +def test_a_stored_result_is_rebuilt_exactly( + migrated_database, public_api_rows, sample_name +) -> None: + result = load_sample(sample_name) + stores = result_stores(migrated_database) + report_run = comparison_ready(stores, migrated_database, public_api_rows) + + _write(stores, report_run, RECORDER.validate(result.model_dump(mode="json"))) + + rebuilt = _read(migrated_database, report_run.id, labels_for(result)) + assert rebuilt.model_dump_json() == result.model_dump_json() + assert rebuilt == result + + +def test_a_reused_baseline_keeps_its_figures_once( + migrated_database, public_api_rows +) -> None: + first = load_sample("us_state_ca_2026") + second = first.model_copy( + update={"budget": first.budget.model_copy(update={"budgetary_impact": 1.5})} + ) + stores = result_stores(migrated_database) + first_run = comparison_ready(stores, migrated_database, public_api_rows) + _write(stores, first_run, first) + baseline = stores.runs.get_simulation_run(first_run.baseline_simulation_run_id) + second_run = comparison_ready( + stores, + migrated_database, + public_api_rows, + baseline=simulation_store(migrated_database).get(baseline.simulation_id), + ) + assert second_run.baseline_simulation_run_id == first_run.baseline_simulation_run_id + + _write(stores, second_run, second) + + labels = labels_for(first) + assert _read(migrated_database, first_run.id, labels) == first + assert _read(migrated_database, second_run.id, labels) == second + + +def test_reading_needs_a_succeeded_comparison( + migrated_database, public_api_rows +) -> None: + stores = result_stores(migrated_database) + report_run = comparison_ready(stores, migrated_database, public_api_rows) + + with pytest.raises(LookupError, match="no succeeded economy comparison"): + _read( + migrated_database, + report_run.id, + EconomyResultLabels(model_version="1", data_version="1"), + ) + + +def test_reading_needs_a_label_for_every_geography( + migrated_database, public_api_rows +) -> None: + result = load_sample("uk_nation_scotland_2026") + stores = result_stores(migrated_database) + report_run = comparison_ready(stores, migrated_database, public_api_rows) + _write(stores, report_run, result) + labels = labels_for(result) + missing = EconomyResultLabels( + model_version=labels.model_version, + data_version=labels.data_version, + constituencies=dict(list(labels.constituencies.items())[1:]), + local_authorities=labels.local_authorities, + ) + + with pytest.raises(LookupError, match="no label for S14"): + _read(migrated_database, report_run.id, missing) + + +def _with(result, **sections): + return result.model_copy(update=sections) + + +def test_results_the_tables_cannot_hold_exactly_are_refused() -> None: + result = load_sample("uk_national_2026") + reordered = result.decile.model_copy( + update={"relative": dict(reversed(result.decile.relative.items()))} + ) + no_shares = result.intra_decile.model_copy( + update={"deciles": {**result.intra_decile.deciles, "No change": []}} + ) + mixed = result.constituency_impact.model_copy( + update={ + "root": [ + *result.constituency_impact.root, + result.local_authority_impact.root[0], + ] + } + ) + + for refused, message in ( + (_with(result, decile=reordered), "decile"), + (_with(result, intra_decile=no_shares), "intra_decile"), + (_with(result, constituency_impact=mixed), "constituency_impact"), + ): + with pytest.raises(ValueError, match=message): + check_storable(refused) + + +def test_the_recorder_refuses_output_that_is_not_a_result() -> None: + with pytest.raises(ValidationError): + RECORDER.validate({"budget": {"budgetary_impact": "much"}}) diff --git a/libs/policyengine-simulation-persistence/tests/test_schema.py b/libs/policyengine-simulation-persistence/tests/test_schema.py index 4a6f42383..40b498110 100644 --- a/libs/policyengine-simulation-persistence/tests/test_schema.py +++ b/libs/policyengine-simulation-persistence/tests/test_schema.py @@ -121,4 +121,7 @@ def test_importing_the_package_registers_every_table() -> None: "simulation.reports", "simulation.simulation_runs", "simulation.report_runs", + "simulation.poverty_rates", + "simulation.budget_impacts", + "simulation.local_authority_impacts", } <= package_tables diff --git a/libs/policyengine-simulation-persistence/uv.lock b/libs/policyengine-simulation-persistence/uv.lock index b007a60ff..f19c0f00e 100644 --- a/libs/policyengine-simulation-persistence/uv.lock +++ b/libs/policyengine-simulation-persistence/uv.lock @@ -16,6 +16,117 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/3f/27/78a89b55b0904d222183164e079b4ca56208e94eff1d35ad1f1ad5be9b06/alembic-1.20.0-py3-none-any.whl", hash = "sha256:77eb101048d95f982c0353e9233404889dcd7a6fc244c107836c0e2fc9cf7d9d", size = 268719, upload-time = "2026-09-11T19:09:12.88Z" }, ] +[[package]] +name = "annotated-doc" +version = "0.0.5" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/5a/8e/38aa427ed5402449e226975b649c5dc73ccadfefeb95e6aecb8f8ea4b6b6/annotated_doc-0.0.5.tar.gz", hash = "sha256:c7e58ce09192557605d8bbd92836d7e1d520ac9580096042c0bfd197efacf1bb", size = 10758, upload-time = "2026-07-28T13:50:58.129Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3e/30/e900b21425a860e195f32e37657aa1f7c7f2b1bfb26f03ca209b90933c06/annotated_doc-0.0.5-py3-none-any.whl", hash = "sha256:117bac03a25ede5df5440e855b32d556049ca169ead221505badf432fed4b101", size = 5302, upload-time = "2026-07-28T13:50:57.239Z" }, +] + +[[package]] +name = "annotated-types" +version = "0.8.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/5f/56/a8120250d128bed162cd73c76d45f6ef9991f3e068f62a8ee060afa3104a/annotated_types-0.8.0.tar.gz", hash = "sha256:13b2beaad985e05e2d6407ee4c4f35590b11f8d693a258a561055cac8f64cab7", size = 15893, upload-time = "2026-07-23T20:16:13.995Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/99/91/8acff4f5e50511b911bbccb72b8628a49c68ce14148cd9f6431094859a90/annotated_types-0.8.0-py3-none-any.whl", hash = "sha256:f072f4d804ea359e4eaf198b1af7a8b0943881a87f31bb764f8bf219bb9419e0", size = 13427, upload-time = "2026-07-23T20:16:12.938Z" }, +] + +[[package]] +name = "anyio" +version = "4.15.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "idna" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/a9/d2/f4d173e22df740bc37b1db102b386ba719b66e95b0f0d751f556b387e6d2/anyio-4.15.1.tar.gz", hash = "sha256:9f28306018cbd6d329e64a36d58256edff76dd996fe423bc957326e578b82a94", size = 276966, upload-time = "2026-09-05T10:42:39.44Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/12/b8/4bd346e22b28902df4d651910f5242c28d84e4a5c2435ca5c3f797ed7e2e/anyio-4.15.1-py3-none-any.whl", hash = "sha256:6152fdbbf9a77fdec97731721bebf7c4c44f7c29b424b0065826173efc7ed101", size = 132079, upload-time = "2026-09-05T10:42:37.923Z" }, +] + +[[package]] +name = "certifi" +version = "2026.10.19" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a6/bd/1436c50cc46699de0230fbaacc1d1de7bfec413176099949e9d5112e88f2/certifi-2026.10.19.tar.gz", hash = "sha256:035c1e85572b141bf1c3a3eff0e33a8eb74917522f2559075ff8d2fea780a1ae", size = 137598, upload-time = "2026-10-20T02:24:16.604Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c4/51/29046e48f693c54e5b7412216d447a1d8362c9653148d98c02cdf65fa733/certifi-2026.10.19-py3-none-any.whl", hash = "sha256:42d35340cc5b9ba78e818ddbff0c5b1c2b779de448a340fd1b989f5fa8670e1b", size = 136464, upload-time = "2026-10-20T02:24:15.072Z" }, +] + +[[package]] +name = "cffi" +version = "2.1.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pycparser", marker = "implementation_name != 'PyPy'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/9e/ef/008a1939e372c06329a3fce4279c02f328488f3526744906eeec3da7ad5f/cffi-2.1.1.tar.gz", hash = "sha256:dd31f52ea1086513bb9df30f8fcee9b8918323ae067a3d5b78bc826a000712be", size = 530807, upload-time = "2026-08-03T21:21:18.939Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9d/f4/035513d4117049066b4779dc3b7c0c0fdad175fa13731c9f4003f1cd1478/cffi-2.1.1-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:b5bdfd1c873d4e093aabc0ca84c4ca6dbc4f752afb5c86f146d9742580c9da2e", size = 194248, upload-time = "2026-08-03T21:19:59.399Z" }, + { url = "https://files.pythonhosted.org/packages/76/af/2aeb4dbb5fc41a04161ae9ff1518de7cec08e164f44a8ce6a4cf7fd2cd1d/cffi-2.1.1-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:31348097ff5bbe827ccc41795d4dd099d9f0625e7def00ee653c137a490c2a6c", size = 196908, upload-time = "2026-08-03T21:20:00.746Z" }, + { url = "https://files.pythonhosted.org/packages/a7/46/2e5fdde8555706dd98139a910ca11be02809f3f605ce956f655d0214e100/cffi-2.1.1-cp313-cp313-macosx_10_15_x86_64.whl", hash = "sha256:9d2055050ea716bd38b7f7f1579c275386646b4894c155a3e2f3cd62ed41b7c6", size = 184805, upload-time = "2026-08-03T21:20:02.02Z" }, + { url = "https://files.pythonhosted.org/packages/55/41/4c7042f317b9217502988f0873af87e16ad606dc20f84e546e3e6ce9764c/cffi-2.1.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:19ee6127ee34de7d83ce3d371ebc5ed91addbdcc39f9ab15ce4eb35a4e534971", size = 184764, upload-time = "2026-08-03T21:20:03.141Z" }, + { url = "https://files.pythonhosted.org/packages/43/1f/1c3d90d91811c8f86ced9ed637956c54bfe5b79ca98fe976d7f8c8979f6b/cffi-2.1.1-cp313-cp313-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:6a8dddef476fab96d066d578fc88526767b836ab5ab21754e1d5bf3879c31c7c", size = 214722, upload-time = "2026-08-03T21:20:04.377Z" }, + { url = "https://files.pythonhosted.org/packages/37/6f/3b5ce4c3b2192d250f04908f2bfd91ef34552ec8f7716a5d4abdb8d67bb2/cffi-2.1.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:f16c709686a78c727bbbf059f92b0bf41c6fc60deec706d2dc19f529175a6125", size = 222369, upload-time = "2026-08-03T21:20:05.544Z" }, + { url = "https://files.pythonhosted.org/packages/02/10/4b3c75dde3d9663c9e02ba05c2668b954f671d4bbe346413ca8c696b295a/cffi-2.1.1-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:fcd22650c908d7b7da162bbfaab594a1227a15d1643a98c68b122ac642fa2264", size = 210175, upload-time = "2026-08-03T21:20:06.75Z" }, + { url = "https://files.pythonhosted.org/packages/df/62/14f74b9543e605d17701dc797b815958b8bb70b7624ce1b832ddad48ed6c/cffi-2.1.1-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:aa9511c62d14da7aacc9b4bf51f3f697a621e83b2d6919008243c3aad168eea3", size = 208670, upload-time = "2026-08-03T21:20:08.04Z" }, + { url = "https://files.pythonhosted.org/packages/95/95/86342356ff5953b3fb06f7ef7c5bee212d45e770abc7218d451b9148313c/cffi-2.1.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:a931079504ecc49efed7744c476a5c343a92fabf66dec2db95edb1b2fdc770e2", size = 221824, upload-time = "2026-08-03T21:20:09.274Z" }, + { url = "https://files.pythonhosted.org/packages/eb/ff/7b3429ff53aafe931ed8a5fc69f481bbef7ba6de87ddcbb63d08f483f613/cffi-2.1.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a2d7755bef5a12ed488f4ef1f1b69ee9191d7396083b755a5d2295f6edb4768b", size = 225148, upload-time = "2026-08-03T21:20:10.7Z" }, + { url = "https://files.pythonhosted.org/packages/34/34/a95870b9221e09cf4f2ce3178b1a210abdfe63a1bd357da940418d7b8d15/cffi-2.1.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e0bcb7e0f677f543555d2adff3bf19c05f66cdb4796e5ff602442ab2fe3c4ef7", size = 223564, upload-time = "2026-08-03T21:20:12.165Z" }, + { url = "https://files.pythonhosted.org/packages/70/ea/839b50531021a647fb5e929f72cf97bc1ff702b5472166164b5b6e76b851/cffi-2.1.1-cp313-cp313-win32.whl", hash = "sha256:334644fbac4eff73d985a17a91226df55d0f394160c4cfb880e084c8f7161cac", size = 175263, upload-time = "2026-08-03T21:20:13.559Z" }, + { url = "https://files.pythonhosted.org/packages/60/a6/8b149b2c3f2e11aaa1618ef64500b45f50f22c57a977a4dff1aff1f91042/cffi-2.1.1-cp313-cp313-win_amd64.whl", hash = "sha256:1aa5645c30469b09530c4ebca77ebf8f17618293c58f8549cb1a543a50236e7d", size = 185688, upload-time = "2026-08-03T21:20:14.69Z" }, + { url = "https://files.pythonhosted.org/packages/01/9a/11f687cb39d6a3504060d5242f04f48c735afb4d3d533958a20594890cb2/cffi-2.1.1-cp313-cp313-win_arm64.whl", hash = "sha256:63bbfd5ded17c4840ac07cd8f1c21ba9d9708141f840b324f422f41b207e3973", size = 180078, upload-time = "2026-08-03T21:20:15.917Z" }, +] + +[[package]] +name = "charset-normalizer" +version = "3.5.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/33/1c/f41d4e74c28ab327ff3acd36053f7ea506c55872d7a90b0fa71aa3ab0c89/charset_normalizer-3.5.2.tar.gz", hash = "sha256:39de2a259fc954455c57274dc94c79d5842774e1247a016aff30bc0efed0f4ef", size = 172659, upload-time = "2026-09-30T04:39:23.398Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c5/34/68292d68512768591aaff07c59bb53ee31341c87759433a859c4641a50c2/charset_normalizer-3.5.2-cp313-cp313-android_24_arm64_v8a.whl", hash = "sha256:ed905975ab14056a2e5eb1c376cb2e1ebc5396baf84163939c518556fccde9f5", size = 225946, upload-time = "2026-09-30T04:35:55.313Z" }, + { url = "https://files.pythonhosted.org/packages/e3/80/bee0b01b90ccd5322ae1d0abb33fab1bd95b7c2eadaf02aeccf22e04ee83/charset_normalizer-3.5.2-cp313-cp313-android_24_x86_64.whl", hash = "sha256:a66c3bc5ab1f0ff2164fc9965ddd611ff0802173f4b9d24554c563f6ab7e1d6e", size = 238619, upload-time = "2026-09-30T04:35:56.863Z" }, + { url = "https://files.pythonhosted.org/packages/78/6e/60ce52a85a7fd631ae8482ae6d74521014ca2f255892679484dc04d7ef56/charset_normalizer-3.5.2-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:d2374b62878abb00cd8309b32af6c0b715cd02dec0ca74ef12e5069bdc64144a", size = 206701, upload-time = "2026-09-30T04:35:58.639Z" }, + { url = "https://files.pythonhosted.org/packages/36/8c/71aafad23f971afc84c2b295bc0c560739ce1dac558aad9fec22e39f3639/charset_normalizer-3.5.2-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:d376bbd28b3a8999db1a103b3b388aee6f1ddeb3e51bc2172993efdcd86e064d", size = 210506, upload-time = "2026-09-30T04:36:00.147Z" }, + { url = "https://files.pythonhosted.org/packages/91/da/3c5a7798c046df7d2d68ad653cf5b6c5a8bfee225055a843c6f2f42aac1a/charset_normalizer-3.5.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:6045373d5a89a5ec71afde535db987ca28e76dfa276c2d4c818265b375d4b055", size = 366626, upload-time = "2026-09-30T04:36:01.77Z" }, + { url = "https://files.pythonhosted.org/packages/e1/16/710ac3de2ee354e2bd1a9c94efe45a2d27b5c6ad39b2d6a905be2c094b6c/charset_normalizer-3.5.2-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:849df64e889b2e17230d58410a03dba311a65b163508fd33679b2b737d4b7858", size = 244624, upload-time = "2026-09-30T04:36:03.389Z" }, + { url = "https://files.pythonhosted.org/packages/d6/39/45c7439f5b63d24f7d5b2a1d760f34af7628782d7144b4cc8ded45c2d4bc/charset_normalizer-3.5.2-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:15c44f7edfd477b06f517a5cc317fc1707edb9de2c865f43d4b6513907473234", size = 235731, upload-time = "2026-09-30T04:36:04.987Z" }, + { url = "https://files.pythonhosted.org/packages/4d/34/38f3154785ce92e9f56eb226f4d35bdfae6b008480dd055f58837a89c810/charset_normalizer-3.5.2-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a89012d6d5476ee112d20d998570ed58df2260a852afb1758809cd6900411d21", size = 270352, upload-time = "2026-09-30T04:36:06.412Z" }, + { url = "https://files.pythonhosted.org/packages/04/f3/859f74e7babc977705026b30593b3be04049632a522fb7000f83c033d747/charset_normalizer-3.5.2-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:0c951d5e6dd9c2ff60609476752bee49da4206adde960ebc247766937f72e718", size = 267393, upload-time = "2026-09-30T04:36:07.865Z" }, + { url = "https://files.pythonhosted.org/packages/4b/85/41d27f234b82e47c167a5f6c0f62501dc0c640585ff4aba79e08a390336a/charset_normalizer-3.5.2-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7218e8f32b0956cfcd048fd42d9d5779809745ca1d86113ca56f66e7ae1549c4", size = 254660, upload-time = "2026-09-30T04:36:09.248Z" }, + { url = "https://files.pythonhosted.org/packages/58/ca/5d1a997587febe5b26d8daffe363b5c1a091cece19828eec6502fd09c5ef/charset_normalizer-3.5.2-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:a19a731138fc27d5682277d3b9df22855cea1239bce7fcec5f78f42ef2d1f3c3", size = 249996, upload-time = "2026-09-30T04:36:10.73Z" }, + { url = "https://files.pythonhosted.org/packages/b3/1f/d1e78246f7ed60c8c8d606b4ac27f66ce49cc3e95f24893ccbeba9f77302/charset_normalizer-3.5.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:62603db9a7caa0802eaa28c1c46fecd7b3a263a774069c24c3c28c302448721c", size = 247028, upload-time = "2026-09-30T04:36:12.294Z" }, + { url = "https://files.pythonhosted.org/packages/8e/37/eba316edd4f0c4d3a5d945924c4eeeae59abac4056aa815d8a4268f863a2/charset_normalizer-3.5.2-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:b6856554c4f44d79fc2307d5768854310a8f0096e501c75637542c82292b0429", size = 240562, upload-time = "2026-09-30T04:36:13.887Z" }, + { url = "https://files.pythonhosted.org/packages/c8/8e/aaa037d40ca9ef045977f1a661048b1aa33f223adfce3452fe9be9f79d14/charset_normalizer-3.5.2-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:1bc0baf5ef96b6ede57d47f4b8fe4d9d84019c3bfcbeb20a41edc6a6ee341f1f", size = 271699, upload-time = "2026-09-30T04:36:15.41Z" }, + { url = "https://files.pythonhosted.org/packages/26/19/1c1c9f75974adf523b87f34b8a2adc5a435cd65916812bcbd0dfa45f9a29/charset_normalizer-3.5.2-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:56bc200a365efb37383b7852e4cc5898d3b2da5987289b543956cf8cad71018a", size = 252030, upload-time = "2026-09-30T04:36:16.839Z" }, + { url = "https://files.pythonhosted.org/packages/bc/90/0660ef18e18df0a4d2a1a0edff7dfbba42d4e50ef2425557a5bb7051f77b/charset_normalizer-3.5.2-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:2c9ad19a6cfcd5ea5c0d41161d22f9df1dcc277e9bef2751391334546a314c00", size = 268565, upload-time = "2026-09-30T04:36:18.468Z" }, + { url = "https://files.pythonhosted.org/packages/79/ba/57adc269824e8658f1a0f97a9e514c247445a9632b3419b97e0ba37f16dc/charset_normalizer-3.5.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e243bd13217235fc7290c621941c3f5cc8b66e4872495be821d7436ba2fb838d", size = 257627, upload-time = "2026-09-30T04:36:19.938Z" }, + { url = "https://files.pythonhosted.org/packages/9a/85/33abd4315c052d3d4f54c92b1ee49bfbc0dc7115a981e462a793b6d2ab87/charset_normalizer-3.5.2-cp313-cp313-pyemscripten_2025_0_wasm32.whl", hash = "sha256:a090bb2c68df85450502e3e20d665e3a5af9c65a84d6508ed477badd49166fd3", size = 143407, upload-time = "2026-09-30T04:36:21.376Z" }, + { url = "https://files.pythonhosted.org/packages/4f/de/6435e18d1aaa5d910b896d551411c96af1f42a0c56c29afc2016c61ccc2e/charset_normalizer-3.5.2-cp313-cp313-win32.whl", hash = "sha256:2b7b3bbfb4fe8ef40600792d762fbaa9057559f9d3fad209525b7a22b99e91fd", size = 183207, upload-time = "2026-09-30T04:36:22.776Z" }, + { url = "https://files.pythonhosted.org/packages/9c/76/b8ec57f4e9ee3253541abf95e4a462c0175fe8032dcd070f1f2421240942/charset_normalizer-3.5.2-cp313-cp313-win_amd64.whl", hash = "sha256:78456a747de8dc58360ffa581f30a002baf5aa28cb262536545e91f113ed7639", size = 206489, upload-time = "2026-09-30T04:36:24.306Z" }, + { url = "https://files.pythonhosted.org/packages/3e/60/c647c6ae47480221e875ea5d743ff94946f7416e3c69415ab772928e8d32/charset_normalizer-3.5.2-cp313-cp313-win_arm64.whl", hash = "sha256:11912e4bb14baae7c5d8791aa55ba0a3a03ec6729073307b0f57270abaa713d3", size = 195501, upload-time = "2026-09-30T04:36:25.846Z" }, + { url = "https://files.pythonhosted.org/packages/8c/ab/176fbfd5b64939c55d652366aa5b9ef1d767af207a3aa6ebeb0d226c484d/charset_normalizer-3.5.2-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:4275811936e2f06feff5e598fb42a1b7ae852da8e39605211892b56b81a34efd", size = 331815, upload-time = "2026-09-30T04:38:26.216Z" }, + { url = "https://files.pythonhosted.org/packages/7e/84/371eac6b30bdbcbf2d632a1a01809103459216fcaae61b8b8d922c1bfb8a/charset_normalizer-3.5.2-cp37-abi3-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:1c50fe28bbc2ced33386f298650d91218076c05420e6cbd790b913adc41659e7", size = 253276, upload-time = "2026-09-30T04:38:28.032Z" }, + { url = "https://files.pythonhosted.org/packages/43/6f/c4fbae58febff71709c51bc7e18fdfa55341dc382704740f9f0cbf03817b/charset_normalizer-3.5.2-cp37-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d19fbd981a488e22cd04883659ca6b08f50b5974f9fd7c95655ef6a043e5893f", size = 241239, upload-time = "2026-09-30T04:38:29.732Z" }, + { url = "https://files.pythonhosted.org/packages/61/71/458c3f42164a07d0c5210798e9e704b39e540a6793b05aba67f3a35243a9/charset_normalizer-3.5.2-cp37-abi3-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:0fed1d06615f022ee3b13caf5e8b180cfea32bb2c5aded8a9d44277afc040f93", size = 231121, upload-time = "2026-09-30T04:38:31.462Z" }, + { url = "https://files.pythonhosted.org/packages/09/54/ab9e89367076f6331bb6c65c4bf14a5361fa5191cb6561bf534f18504e1b/charset_normalizer-3.5.2-cp37-abi3-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:838dcc90063569a0448120554591a1d6c4a4ffe11babf048908793154ab86ade", size = 260350, upload-time = "2026-09-30T04:38:33.239Z" }, + { url = "https://files.pythonhosted.org/packages/7c/c1/061431ecc688d9d76602502cb57cc01e691e682c18f1beb45f9673b5bbd2/charset_normalizer-3.5.2-cp37-abi3-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:2ce45c6627b22c47e390bc91a41c3d13032192e699fa0bea96e9671b373d69b0", size = 255430, upload-time = "2026-09-30T04:38:34.865Z" }, + { url = "https://files.pythonhosted.org/packages/8d/1f/20c8949f0676f7ab811abdeb7f4d7f1cbc6e61ff20bef08b44edeb092bc8/charset_normalizer-3.5.2-cp37-abi3-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:0774bf9bf620249fee3e0b8b9fd3065de213be30f3aa94ce2494b3b638949e26", size = 250612, upload-time = "2026-09-30T04:38:36.649Z" }, + { url = "https://files.pythonhosted.org/packages/2b/9e/46f2fa4c431fc98c4ae76a8cb5bdca54e0341e3cfc3fcfd8e82740250818/charset_normalizer-3.5.2-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:1db38f4c5496827c1a501846d64d14c3b80c7e6714e406cd7dc36a9899fa1011", size = 242083, upload-time = "2026-09-30T04:38:38.26Z" }, + { url = "https://files.pythonhosted.org/packages/bd/39/559be29a0c0f086e0bba6922babd38916cc5e0b58ced4de13ee01ea05508/charset_normalizer-3.5.2-cp37-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:304d8e4d493af723536393eee0c689eb7813f4a474c8b479dee63f1fdd98f621", size = 232738, upload-time = "2026-09-30T04:38:39.81Z" }, + { url = "https://files.pythonhosted.org/packages/ff/6c/387b0e4f756a282831c1d9fc6aeb6c51ca4507ca202767c8de15ce9b12e2/charset_normalizer-3.5.2-cp37-abi3-musllinux_1_2_ppc64le.whl", hash = "sha256:9b7f416ff0978e2f2249330527f0ad6fa02f4932e6199692d3b52da2048c19e4", size = 260703, upload-time = "2026-09-30T04:38:41.346Z" }, + { url = "https://files.pythonhosted.org/packages/96/92/1fdf015f09ef449f50d3ac4b67c90887c9c318b727daa95cc4f866e6521d/charset_normalizer-3.5.2-cp37-abi3-musllinux_1_2_riscv64.whl", hash = "sha256:01077390b03f7988f11d700a2194e69b119741a86b1a638b1db88891e3eced8e", size = 247622, upload-time = "2026-09-30T04:38:42.937Z" }, + { url = "https://files.pythonhosted.org/packages/dc/3c/8e7b8a5671ad5d433669fb2a76f1a0164df2d9b1718b0206bc2a16d840cc/charset_normalizer-3.5.2-cp37-abi3-musllinux_1_2_s390x.whl", hash = "sha256:7e841fb9010836c992c9f12fcbd43a831de93a5f726fc1ccd8ca1d0268c5014c", size = 257500, upload-time = "2026-09-30T04:38:44.604Z" }, + { url = "https://files.pythonhosted.org/packages/b4/f0/45b579df5cabc1d5d53ea1cc35e8437d3ca768c0acccc7041517cb6fbb32/charset_normalizer-3.5.2-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:9cae88599c7219005d879f98e5ed53341e9a122af585e1091200358a3003d2a0", size = 255100, upload-time = "2026-09-30T04:38:46.289Z" }, + { url = "https://files.pythonhosted.org/packages/31/68/fdec18a343f5fb3f310588dd478b09ac4799e0b187dbade3a8cd776f03ef/charset_normalizer-3.5.2-cp37-abi3-win32.whl", hash = "sha256:01b0c0d2262a9e28e8484a278c7e1b5d650e3ac8cf2683d2967e25899f208bdf", size = 174499, upload-time = "2026-09-30T04:38:47.999Z" }, + { url = "https://files.pythonhosted.org/packages/9d/8a/b618149cc5207943a0242068d7a27897f56a62947b5a039085f2a22029f8/charset_normalizer-3.5.2-cp37-abi3-win_amd64.whl", hash = "sha256:9f56f72050826f63dcee7a7f55b0a77168cb3bfc553fd405e7f8f9ece75a4036", size = 200092, upload-time = "2026-09-30T04:38:49.707Z" }, + { url = "https://files.pythonhosted.org/packages/03/cf/4c66866fa9e2b1c78e3c911516d1de497a677b7ac60f1eceda74ce777ca3/charset_normalizer-3.5.2-cp37-abi3-win_arm64.whl", hash = "sha256:40ab6bffa02ae10a0581e6c198be7d2d8ca5c2a0c64e4ed3465d766df457573e", size = 294363, upload-time = "2026-09-30T04:38:51.312Z" }, + { url = "https://files.pythonhosted.org/packages/fc/ad/d07d7862a62ffa6d79d68074d14823243dd235a77c45262acbf6adeb28bf/charset_normalizer-3.5.2-py3-none-any.whl", hash = "sha256:b6b751274acb69d77b3323d6b7dbaa3c7fdfc1eb829b7eb61d262f32e1af9685", size = 68872, upload-time = "2026-09-30T04:39:21.828Z" }, +] + [[package]] name = "colorama" version = "0.4.6" @@ -49,6 +160,247 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/3f/0c/7a64e1ac90541a8edf50daef0914848011fb057a5bf55284a4811e21939a/coverage-7.16.2-py3-none-any.whl", hash = "sha256:11d28e9123a9156cb405d8d27b44256c9a58fb5decc2073a8f17862057e3aa0f", size = 215754, upload-time = "2026-09-27T12:28:59.075Z" }, ] +[[package]] +name = "cryptography" +version = "50.0.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "cffi", marker = "platform_python_implementation != 'PyPy'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/9d/af/182eb91b0df3fe75c4d9f26fe70684569566745f6ba7e5c9c73a862c5252/cryptography-50.0.2.tar.gz", hash = "sha256:7b46165bb56eb4704e2eaaf86f3c940d19154535d9b0ca7d6d590b04060e00d5", size = 880623, upload-time = "2026-09-30T15:30:04.884Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e5/56/d194340cc4a57535e82e1bee9e89667ac4b7c13b5d3f59686deae3094dd5/cryptography-50.0.2-cp311-abi3-macosx_11_0_arm64.whl", hash = "sha256:fa8f5efb344d6908a1ce62f4a24e2e5780f825d6f53f5f50ec5ffacac72936cb", size = 3914904, upload-time = "2026-09-30T14:43:44.339Z" }, + { url = "https://files.pythonhosted.org/packages/d9/69/c9bd862c3bf43d6399c433caf002df16e2dffd4be49bdf515cda38038711/cryptography-50.0.2-cp311-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:79def8d059362e7831389ed3be0ecdf58a89386e1271e35dd9f5af84e81bffd0", size = 4731146, upload-time = "2026-09-30T14:43:47.113Z" }, + { url = "https://files.pythonhosted.org/packages/21/69/64cef1f702bf6657e0cc186ed1a2891d50d29fb41586b254e1c07adea261/cryptography-50.0.2-cp311-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:630ebfea3bf689d075f82316324ff7433dc447fe6bc1bfc76524b74b4a9567d2", size = 4719841, upload-time = "2026-09-30T14:43:49.01Z" }, + { url = "https://files.pythonhosted.org/packages/38/6b/61a3f8d8c5e1e49a6cddccafc4015cc1c0021360ab0acb4080e7a423644a/cryptography-50.0.2-cp311-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:f9f6143a8c75945eb960d9eb98905a441394abfa24afaae239d514ffb2586480", size = 4738340, upload-time = "2026-09-30T14:43:50.932Z" }, + { url = "https://files.pythonhosted.org/packages/7b/2e/7212ca32fd43dc91f2f41db20160b268098874b4c9a0e7be94d6835f5b2e/cryptography-50.0.2-cp311-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:a582ab2ae1d34f67112cadc86702774c9ea4374df6bca6afe672817203c99134", size = 5367029, upload-time = "2026-09-30T14:43:52.911Z" }, + { url = "https://files.pythonhosted.org/packages/1a/f1/b474e930c4d910328780e3940da76f5aa5cbc48ce1fc14e44d239d9ea9db/cryptography-50.0.2-cp311-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:4061c0079120205fb760c58acab6443e217307dcf05e3702cf970e0689972856", size = 4753050, upload-time = "2026-09-30T14:43:55.272Z" }, + { url = "https://files.pythonhosted.org/packages/7c/52/9af10e80ac16b0fcc2123f9cbd5e7afbd0fd5075bb7a607c592258a39cda/cryptography-50.0.2-cp311-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:ac9ed99d81760c62fe89d5f0815cdfa1ba9a35141cf30f1c2d044f04b4803d2e", size = 4376724, upload-time = "2026-09-30T14:43:57.24Z" }, + { url = "https://files.pythonhosted.org/packages/71/37/6202e488cc1eb625ea110c292c6bda92823176e023f427d8d5660ce8d632/cryptography-50.0.2-cp311-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:87e9ce85beb6b328ba370cc6e6aea483c92617b4c95b1d33a49297eb662bfb04", size = 4737859, upload-time = "2026-09-30T14:43:59.541Z" }, + { url = "https://files.pythonhosted.org/packages/8f/30/e86d7d518489b0ae2497091a35287abcb1a2ce4037837a34afbe9b1d6964/cryptography-50.0.2-cp311-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:f265528741e048bce55c3463ed721fb0aa45a5888d8add8cfeccb3035451bbdc", size = 5324103, upload-time = "2026-09-30T14:44:01.901Z" }, + { url = "https://files.pythonhosted.org/packages/d3/69/2c833a049475e0a3444e94c7d0aca0aa51d166374a449b09e92ac98138de/cryptography-50.0.2-cp311-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:9dab55f57c74c3cad24c323bacbbd04be4705ba6eb0d92e920b1fc4837ed5079", size = 4752576, upload-time = "2026-09-30T14:44:04.545Z" }, + { url = "https://files.pythonhosted.org/packages/6c/5d/906970b83bbfc1f5bbfb677a143c181f2801f23b6a7204a3b47c42c97e65/cryptography-50.0.2-cp311-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:25784ce8b9621c90c643efb9e1e2162ab3b0224cae446ad5e70e7fcb1ce18b51", size = 4870819, upload-time = "2026-09-30T14:44:06.884Z" }, + { url = "https://files.pythonhosted.org/packages/68/e3/f2298d3bb55e0c4a91841ec4d01b3f020ba8c5fbf15ccdcc6dcf03f97025/cryptography-50.0.2-cp311-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:85d0d9a31b9098e98534226d5686b47264b95e62ce459dc2e62fdfc809f9fe93", size = 5030152, upload-time = "2026-09-30T14:44:09.443Z" }, + { url = "https://files.pythonhosted.org/packages/9a/4f/adfc442765721292fff86d314ce385d3249d22db42295c0dd057727b60f3/cryptography-50.0.2-cp311-abi3-win_amd64.whl", hash = "sha256:7afa5a6602a9f29af1f3a2965f831bae7c9d5d597b7cbb716d41ab3b7d89879c", size = 3824692, upload-time = "2026-09-30T14:44:11.671Z" }, + { url = "https://files.pythonhosted.org/packages/2d/49/93f6a6e7a87c9aa68d44d3e1cdb5fe8f60c90d5d2f46acae9a56892816b8/cryptography-50.0.2-cp315-abi3.abi3t-macosx_11_0_arm64.whl", hash = "sha256:edc3342adf8f697fc5f59c887a304356f147b397809440ed64e2fa6af2f50f37", size = 4133708, upload-time = "2026-09-30T14:44:41.807Z" }, + { url = "https://files.pythonhosted.org/packages/8c/75/32ac2a56243d778805c16ca6a32b8f74fb757df7e28d7ecb560afafb59cf/cryptography-50.0.2-cp315-abi3.abi3t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d370b8d1dfcdf7130178137f6fbee6140774a1acc6cacefc4b42643ec11d0a3a", size = 4956267, upload-time = "2026-09-30T14:44:43.693Z" }, + { url = "https://files.pythonhosted.org/packages/aa/a4/2c8d734e43d97f0842ee9f1b7b4bfb3d0cf5e19edebf43c2afe6675c2320/cryptography-50.0.2-cp315-abi3.abi3t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:f2f9bd7f90c64fe89253f0a2c05e3c4856072660429ce8831b4235bf29403a67", size = 4966465, upload-time = "2026-09-30T14:44:45.769Z" }, + { url = "https://files.pythonhosted.org/packages/c2/58/ee288c829a6f41f6235ae9dd33d82fd19b45442b65b4c8a3da36963d9f7a/cryptography-50.0.2-cp315-abi3.abi3t-manylinux_2_28_aarch64.whl", hash = "sha256:e275096ea1e60cc595cda2836fd4a6c725d1125108b868be17f53684d164e2cc", size = 4959356, upload-time = "2026-09-30T14:44:48.211Z" }, + { url = "https://files.pythonhosted.org/packages/92/20/9ded6d51ddd9897f6b6e81fb9ebea7951d7cc5d6c890b0ed8abf77a51a80/cryptography-50.0.2-cp315-abi3.abi3t-manylinux_2_28_ppc64le.whl", hash = "sha256:b13478603dcd0a2479ff8e87e2c19a7d525734686fe3c49542472293a204212d", size = 5548822, upload-time = "2026-09-30T14:44:50.86Z" }, + { url = "https://files.pythonhosted.org/packages/02/a8/8df951850d6b31d2a00218f19e2b3f999523437ed7a819df7fa427942fca/cryptography-50.0.2-cp315-abi3.abi3t-manylinux_2_28_x86_64.whl", hash = "sha256:58a0c478eeca76fe5e07993c5a0703def34a6dc6a0cda4f5564639b33112ffe7", size = 5001199, upload-time = "2026-09-30T14:44:53.379Z" }, + { url = "https://files.pythonhosted.org/packages/8b/f9/36b3022218ce75b7cdf068fb95f809f9bd0d820e4955ef43b90c255cc7ac/cryptography-50.0.2-cp315-abi3.abi3t-manylinux_2_31_armv7l.whl", hash = "sha256:d38cdff612d06fa6a32840d5e1b1f7a27cee4a349aa9085d94a67789d6bfd408", size = 4629333, upload-time = "2026-09-30T14:44:55.635Z" }, + { url = "https://files.pythonhosted.org/packages/8c/72/20f99a219f6af47cdd1cbd978c243b92d71496e168a746138af44ded4f29/cryptography-50.0.2-cp315-abi3.abi3t-manylinux_2_34_aarch64.whl", hash = "sha256:fdd28f912fccfec1846a94e2e1e8f9b0012f557f0c46fe4f3eb0d7a87afcf90b", size = 4958822, upload-time = "2026-09-30T14:44:59.639Z" }, + { url = "https://files.pythonhosted.org/packages/f2/20/196f112617fb08eb4d608a2a6c422373d46f9cc2857f38fc0667033c0899/cryptography-50.0.2-cp315-abi3.abi3t-manylinux_2_34_ppc64le.whl", hash = "sha256:cbc8738fd8526d80f35cb3a40d41f41a2e7030bb3b18b09a6778ef63d291c2fd", size = 5506351, upload-time = "2026-09-30T14:45:02.267Z" }, + { url = "https://files.pythonhosted.org/packages/24/95/83378121ef3eaaaf71d4b781577ff794acb39b9e1b87a3f156898c8497ed/cryptography-50.0.2-cp315-abi3.abi3t-manylinux_2_34_x86_64.whl", hash = "sha256:e105ab60406787da31fccc883fc0f733af1efd78f0136a4599692c4083a73d0c", size = 5000859, upload-time = "2026-09-30T14:45:05.009Z" }, + { url = "https://files.pythonhosted.org/packages/22/f7/70fd7ae4d1dbfa7ba29b02e1b9068771519a86027756510b700ce81086a8/cryptography-50.0.2-cp315-abi3.abi3t-musllinux_1_2_aarch64.whl", hash = "sha256:6f8700550aa1474a91e5dc07049c46f98b423b5b1ddd0483e0b51362eeeaf5be", size = 5092151, upload-time = "2026-09-30T15:29:15.932Z" }, + { url = "https://files.pythonhosted.org/packages/d4/be/688367b74de86984bd58d8efacfc7c9e68b89a6a22ced0fb4f38db50254a/cryptography-50.0.2-cp315-abi3.abi3t-musllinux_1_2_x86_64.whl", hash = "sha256:c71be1cbfa5cd9a41ee452acf1eccd82b2c05950358b106ec8ceb83411d1a020", size = 5286120, upload-time = "2026-09-30T15:29:18.309Z" }, + { url = "https://files.pythonhosted.org/packages/39/d1/55f8a3f2ef5d1529e16835ef10cf0fe3d559ce237b46dddc440c0bba3649/cryptography-50.0.2-cp315-abi3.abi3t-win_amd64.whl", hash = "sha256:c423ab384a46c4dff7217b2ea5ba2e11cffdeab6441acd04cf65a369caf0366c", size = 4111557, upload-time = "2026-09-30T15:29:20.155Z" }, + { url = "https://files.pythonhosted.org/packages/23/ad/ac987755d00e1e64273760228d2635ae38dae2be83e3c6e0d3289d91dec3/cryptography-50.0.2-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:0ec5f09541743261e66e291b4a0cbf0fb2997aeaab6d9e9c740b9dba1b58d1c2", size = 3943588, upload-time = "2026-09-30T15:29:22.265Z" }, + { url = "https://files.pythonhosted.org/packages/d5/8d/6d585339bedf85d45044c85d8412dac53f2bb6f918e8b7777efba1787844/cryptography-50.0.2-cp39-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:c5e67125c7dca78d199ec4e116aa93dbb83494808ecbb8211a2cb09b1bf41dbd", size = 4756166, upload-time = "2026-09-30T15:29:24.58Z" }, + { url = "https://files.pythonhosted.org/packages/bf/f1/1c1f6874e8550cfddd4b688ceb38cefb6ed15ceed224d56f133f3d88c214/cryptography-50.0.2-cp39-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:ee247f5c245c9a2fe7c8e2214e295918838e44e00a45a6718451e4004219e767", size = 4749145, upload-time = "2026-09-30T15:29:26.807Z" }, + { url = "https://files.pythonhosted.org/packages/c1/63/61b15dc1a8de03fe0adbe3fd7608b3ad5c73bf50993bbcb1faaa930afe33/cryptography-50.0.2-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:dfe9763530994147d9af1def057a5b9658b00e8f8fe8743d144d1e0911c2e454", size = 4763638, upload-time = "2026-09-30T15:29:28.588Z" }, + { url = "https://files.pythonhosted.org/packages/fc/35/b345bdfa40c9126df1a9d33236aa98418367931b8725f84fc3ae2b98dc59/cryptography-50.0.2-cp39-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:58ddb5a8e3179d12f19e4ea34d2d32e9d63a4baa142c875c1eb59f41b7243acd", size = 5382217, upload-time = "2026-09-30T15:29:30.589Z" }, + { url = "https://files.pythonhosted.org/packages/4f/87/ef344a9e616871f2519c22d6afcda79ddd5d35e9592d95eb6e677608d055/cryptography-50.0.2-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:f21e8a22c8605750c7af886bab299a363721264061b4ac0a30efb73cfd58efc5", size = 4781387, upload-time = "2026-09-30T15:29:32.605Z" }, + { url = "https://files.pythonhosted.org/packages/90/5b/f2fdb13cd0b96f6f932c8627bb292a45f11c64d21620a8e120aee9a3b848/cryptography-50.0.2-cp39-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:9c8402a82ea0dc4ceeab793db05f0fafa8ca139ca34fcde5df0f596103c74107", size = 4403790, upload-time = "2026-09-30T15:29:34.374Z" }, + { url = "https://files.pythonhosted.org/packages/bc/ce/7e4f662b1e3c393513569e402cfc85ac7da0bd3d5435e122a3140219eb2d/cryptography-50.0.2-cp39-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:0ddc924c04591c2811ca024d62ecad4f7f6f08af8939c211438f48a16bd23602", size = 4764319, upload-time = "2026-09-30T15:29:36.149Z" }, + { url = "https://files.pythonhosted.org/packages/3c/3f/86ff33ce34cc0de6847fb96e035a1a760d81652e38643f617c02ad32ef7a/cryptography-50.0.2-cp39-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:a6557e5f38e065ca9fbdaf7cfc7435ecb1d113aa81a022d1b51921ee7432e227", size = 5338560, upload-time = "2026-09-30T15:29:39.053Z" }, + { url = "https://files.pythonhosted.org/packages/40/cf/6b5c8e2fd9202d98988ab7cb5cc5c991704c4ad55f492ff408e4969f83f1/cryptography-50.0.2-cp39-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:1981f1db4630889b9ef7803fadef12b056f428cb6b85c27ba57b774793b6093c", size = 4780973, upload-time = "2026-09-30T15:29:41.251Z" }, + { url = "https://files.pythonhosted.org/packages/10/bf/8d6ebc7dded797bd0f0160d52188021211f011a2b164ef0ae1dac4587465/cryptography-50.0.2-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:7a8701d6b584d76e909e3d305b7d126b41439876a5aaf76cddc67fc230eafa2e", size = 4897738, upload-time = "2026-09-30T15:29:43.106Z" }, + { url = "https://files.pythonhosted.org/packages/d4/aa/f3f6e0de7e6253b8baa8b2d8fb9d50924fa75cee3d4624bd4bc1208ee923/cryptography-50.0.2-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:ce47f66801c20ec6c6632453bb5960fe38939e9306970b48b3a5a26de7745d94", size = 5058280, upload-time = "2026-09-30T15:29:44.827Z" }, + { url = "https://files.pythonhosted.org/packages/f6/b6/a1faf3a27ae9405fb34b1713cc73b2d8a26b04d5c561578fa2e6ef3e5bb9/cryptography-50.0.2-cp39-abi3-win_amd64.whl", hash = "sha256:4e81d95e5bafc2d6e34e4bed780e53e4d5b9a2f928573428aa4d35fbec1eb0de", size = 3854095, upload-time = "2026-09-30T15:29:46.782Z" }, +] + +[[package]] +name = "fastapi" +version = "0.159.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "annotated-doc" }, + { name = "opentelemetry-api" }, + { name = "pydantic" }, + { name = "starlette" }, + { name = "typing-extensions" }, + { name = "typing-inspection" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/9a/40/a212bffb9809afb9a94b250f11e0c29fd8b2589ec92e4bedd1cc7adf9938/fastapi-0.159.1.tar.gz", hash = "sha256:b45b1ec57f3aa4d2f80f09bfbcf068b46764a2ee892e56753f35bb3d9d845ce2", size = 522004, upload-time = "2026-10-21T20:59:29.054Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8d/35/b03b5df04a1a8ee400c9df4b1795af84370b2bb6f1cc4be57c0b79688d00/fastapi-0.159.1-py3-none-any.whl", hash = "sha256:49b94c29afec2fca1390e9c39be202c59755d5cda8e4f1148a133761e4313e7e", size = 149604, upload-time = "2026-10-21T20:59:27.58Z" }, +] + +[[package]] +name = "google-api-core" +version = "2.42.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "google-auth" }, + { name = "googleapis-common-protos" }, + { name = "opentelemetry-api" }, + { name = "proto-plus" }, + { name = "protobuf" }, + { name = "requests" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ac/aa/2aa84799e6920216f8aa2866d3b43daa20f7060dcb6efc8f0449e8be0ab0/google_api_core-2.42.0.tar.gz", hash = "sha256:82cf5daa2ef1b456d4e29ff1de1a5c2995c7be3ccf4fc608184326e03390c1ee", size = 273100, upload-time = "2026-10-08T18:12:37.477Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/28/ca/fb2a5b38366bcb12990c80384b920f04b968fd834cf98be67d306c374612/google_api_core-2.42.0-py3-none-any.whl", hash = "sha256:b1bdf4f72dc4f910736ce4ba49038352effbbc309579215107649b22973a1317", size = 221364, upload-time = "2026-10-08T18:12:04.618Z" }, +] + +[package.optional-dependencies] +grpc = [ + { name = "grpcio" }, + { name = "grpcio-status" }, +] + +[[package]] +name = "google-auth" +version = "2.62.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "cryptography" }, + { name = "pyasn1-modules" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/f5/b9/4b2528f30114b106e3c3a7298ba38d85e682fd1f83fe7c4a5b77c7677082/google_auth-2.62.0.tar.gz", hash = "sha256:0bef0ce54bdf9ce226c5d66e4264413bd918141c31bbe49fb52eac882f513d69", size = 398180, upload-time = "2026-10-12T19:20:48.328Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/eb/a3/87fe9b7203ec2e56ea6a57c75e6d632eaf9487c7f7978cdad1d801bee0af/google_auth-2.62.0-py3-none-any.whl", hash = "sha256:4ff4319aeb4ad128409759d397a9fcafad126d0031d241cc0dd6b9a00b43e3f3", size = 267911, upload-time = "2026-10-12T19:20:46.355Z" }, +] + +[[package]] +name = "google-cloud-appengine-logging" +version = "1.11.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "google-api-core", extra = ["grpc"] }, + { name = "google-auth" }, + { name = "grpcio" }, + { name = "proto-plus" }, + { name = "protobuf" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ac/34/aec7eca310c84a106a22dfaad076766c2e2ebe0389bdb88270a22c807f9d/google_cloud_appengine_logging-1.11.0.tar.gz", hash = "sha256:ce053792df98fde4790c5f070176088c9ebf0e55a37c754c8f8e11b28ddb4d73", size = 21678, upload-time = "2026-10-01T18:14:43.6Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2f/a8/da5d9865b0e1ce53194eb1052484303f86e94cd87f3b6d49511690f70ea6/google_cloud_appengine_logging-1.11.0-py3-none-any.whl", hash = "sha256:4d70953a0f35d0295256d977e7e3962242674d64c72fcb3e48b10a1cbf4f9b54", size = 20251, upload-time = "2026-10-01T18:08:00.913Z" }, +] + +[[package]] +name = "google-cloud-audit-log" +version = "0.6.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "googleapis-common-protos" }, + { name = "protobuf" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/69/91/e2a4ed95e790564b807a61fd54d90aa6bf2d3a9474bc5197651acf0cad13/google_cloud_audit_log-0.6.2.tar.gz", hash = "sha256:ea5dc892b1858d345aef0c5563a728534fa875bd0388765391574d3c57fd8f0e", size = 41010, upload-time = "2026-08-25T19:18:29.397Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7d/f3/f24fba2cb01ad41615d55335306642e3ddf3a5c3cdda6b44754d37bd650e/google_cloud_audit_log-0.6.2-py3-none-any.whl", hash = "sha256:1f19bdf2586cfdb72054eec769ede153a037988b73a7d3b6d266f672ab426c00", size = 40382, upload-time = "2026-08-24T21:55:11.849Z" }, +] + +[[package]] +name = "google-cloud-core" +version = "2.8.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "google-api-core" }, + { name = "google-auth" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/55/71/d6081acadf55d4233271c39860f0d140ef61fbdb4bceb2075e9c2905d947/google_cloud_core-2.8.0.tar.gz", hash = "sha256:365f8e4518ae81c8101b8dea5fc1c32a960badedb8b511f19db2843cbbd285d2", size = 36605, upload-time = "2026-09-29T19:25:59.275Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/12/ed/1b09640a565e5d34d4e517463f65a67a11f9dcdeb6b6e8220f2d06aaf489/google_cloud_core-2.8.0-py3-none-any.whl", hash = "sha256:e235b0952f7ffe7b9c71a4cf96b506d9cfb557e22557c412f0df9b7068b5d007", size = 31048, upload-time = "2026-09-29T19:25:35.361Z" }, +] + +[[package]] +name = "google-cloud-logging" +version = "3.17.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "google-api-core", extra = ["grpc"] }, + { name = "google-auth" }, + { name = "google-cloud-appengine-logging" }, + { name = "google-cloud-audit-log" }, + { name = "google-cloud-core" }, + { name = "grpc-google-iam-v1" }, + { name = "grpcio" }, + { name = "opentelemetry-api" }, + { name = "proto-plus" }, + { name = "protobuf" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/e1/5b/fbb367f8bb05b3e968048686f440181765a8681c3a07cfa901814f9280e1/google_cloud_logging-3.17.0.tar.gz", hash = "sha256:d7343f2b82b4f9e9244bfc8aba7ad034c415f9bbb405ed28d1125aa37d270b72", size = 292071, upload-time = "2026-10-01T18:17:01.302Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/35/53/911cbf97517123350292ac6edba7d130ee44acccfd3e2a36f6807f32da14/google_cloud_logging-3.17.0-py3-none-any.whl", hash = "sha256:da2819da683a5135e21c2853ff2c86040786cd5521c3f71424755c110cf36fe2", size = 234020, upload-time = "2026-10-01T18:10:50.73Z" }, +] + +[[package]] +name = "googleapis-common-protos" +version = "1.75.5" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "protobuf" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/8d/2b/6ce81972d5c8cab9705fddce3153be63222d9e12fd96f8baba5038a744dd/googleapis_common_protos-1.75.5.tar.gz", hash = "sha256:c7a866fc34ed29a3b10af627a4b9b1dc2433313ca6e959f0ae4feb132047ed72", size = 156513, upload-time = "2026-09-29T19:26:14.863Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/65/b9/6b29500a1c581ff4d77fd83c6568d068bee06f1b139fb6eb0a4f2d4bce8a/googleapis_common_protos-1.75.5-py3-none-any.whl", hash = "sha256:d7285525c23039db98f2463e6d5a4f9b958b94d497f03a844ece3259c4e72d5d", size = 307737, upload-time = "2026-09-29T19:25:48.735Z" }, +] + +[package.optional-dependencies] +grpc = [ + { name = "grpcio" }, +] + +[[package]] +name = "grpc-google-iam-v1" +version = "0.14.5" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "googleapis-common-protos", extra = ["grpc"] }, + { name = "grpcio" }, + { name = "protobuf" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/d2/d0/fa5bdd5f3f421bb68dc6dc162e9caaf942897ca41ce7255b524723c80f0b/grpc_google_iam_v1-0.14.5.tar.gz", hash = "sha256:07fd3a9fafb586588e771831fbfc8f6597050181d0c3b45e039d18b8fdc1aab5", size = 23736, upload-time = "2026-08-06T06:24:54.489Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/84/ab/be3ad0d46cffe35fd1e7cc3f9947edd6cb3c552229de3be2742f15f7ea47/grpc_google_iam_v1-0.14.5-py3-none-any.whl", hash = "sha256:0f5e680b20aa0a9441e68c769da04d94d70fca4e43751a82d8abb8aa6a7181ca", size = 32674, upload-time = "2026-08-06T06:23:49.467Z" }, +] + +[[package]] +name = "grpcio" +version = "1.84.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/3f/4f/4435c0aae54657258d9cfcba78598f3d9e5fe4c82ff18d78558567b90faf/grpcio-1.84.0.tar.gz", hash = "sha256:19aaf172fc2edbefccce3f6e92c5150975dbe56c45744e9e87cf72ebdf85bfbe", size = 13493876, upload-time = "2026-09-14T06:59:33.291Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5d/51/40f99701adb01d4e5316a2aaf13838da1a24d5c879cd8c95156d7c364454/grpcio-1.84.0-cp313-cp313-linux_armv7l.whl", hash = "sha256:209414080da8c20af94df1395b635da52dd57b5edc9e917e1deca0dc1c4bb55e", size = 6427619, upload-time = "2026-09-14T06:58:06.025Z" }, + { url = "https://files.pythonhosted.org/packages/c5/4b/ed8e22a1237e6b2be6ef4f221d074a5b0e0dd8a0da8c944c04aea731f0eb/grpcio-1.84.0-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:e41c3993eee896c617dbd8a505085d28b6e84a0445ed9a1f40f95808473cf678", size = 12336549, upload-time = "2026-09-14T06:58:08.583Z" }, + { url = "https://files.pythonhosted.org/packages/d3/50/00165b05cd73f45996748ea67ce9e55d08936f2fea94a7fd8541cc2d0e54/grpcio-1.84.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:fff5ef3fe1bba7d6147e5f19e01e5e122ac2c076486887ddcb8d42e663400fbe", size = 6989458, upload-time = "2026-09-14T06:58:11.884Z" }, + { url = "https://files.pythonhosted.org/packages/26/38/d0486230e684d916f97429a53041db88410e662a38f2a8d09e2d90375840/grpcio-1.84.0-cp313-cp313-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:b8c62888c3e49debf37ad9773e3c02f77b0c1e811f8fb0962f2b6c3bbab5b97a", size = 7757778, upload-time = "2026-09-14T06:58:14.849Z" }, + { url = "https://files.pythonhosted.org/packages/da/56/548a643decb059ca244499c675ae2c13a15f523ba94592c2774bd80a13c1/grpcio-1.84.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:986e9751d416d7a6eaa2fecdac38da63153d63a4b340ba7d624889c490451500", size = 7159572, upload-time = "2026-09-14T06:58:17.87Z" }, + { url = "https://files.pythonhosted.org/packages/db/f5/42caac81a79ec680f1f7a8eaf7ca90d2f93936ce0c3a073141ba96757f77/grpcio-1.84.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:5933a052946873d01a42119a05420d669bdca436aeba2d1851988ccb12b421c0", size = 7710547, upload-time = "2026-09-14T06:58:20.607Z" }, + { url = "https://files.pythonhosted.org/packages/57/a4/828ad990b2410fee0a55cc73aa1bf98eb5b911c54847374ef4f24b9e877b/grpcio-1.84.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:e094dd21f077af8194923fc263cad872eaa1802bb0156fd7e5ae18e99cd86715", size = 8761519, upload-time = "2026-09-14T06:58:23.875Z" }, + { url = "https://files.pythonhosted.org/packages/d5/a5/1f91af098919eaf5d80d5a61126ad9fae074e5190c25a3014ce1d8d0d890/grpcio-1.84.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:08735e3d08d24ab3132cf87e2e5dea8746cabcc7d676c2b0b7362f195feef9d9", size = 8121424, upload-time = "2026-09-14T06:58:27.006Z" }, + { url = "https://files.pythonhosted.org/packages/8c/8f/77fd4a7a913b636785479922349c4cb98d94d05d15652e556b3ca0df6663/grpcio-1.84.0-cp313-cp313-win32.whl", hash = "sha256:70bb4ce8be0c5606bec259cbd7152374470396413b7863a658a08c849e6b29ff", size = 4477974, upload-time = "2026-09-14T06:58:29.528Z" }, + { url = "https://files.pythonhosted.org/packages/d0/9a/1fa59ddbfc8898e5518d1447e46f771f387f0ed6132ad531395338e51a5c/grpcio-1.84.0-cp313-cp313-win_amd64.whl", hash = "sha256:b61692f0069b3eee2fc8a3a1b7f6c044df9e03fede6ce69b3ca832e1c39f26c5", size = 5255326, upload-time = "2026-09-14T06:58:31.781Z" }, +] + +[[package]] +name = "grpcio-status" +version = "1.84.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "googleapis-common-protos" }, + { name = "grpcio" }, + { name = "protobuf" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/52/45/f80309cdb6a7dbf8f65e2082dd2ddc9797ba7180516a73c54d966ba632c4/grpcio_status-1.84.0.tar.gz", hash = "sha256:5caf28ba7184b81f618b5f7f094859fd2541bf429d2189bbbcd715c9c2cdcee2", size = 14015, upload-time = "2026-09-14T07:10:29.402Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/71/c4/3a77e4273e866b1b0c412afd80882e95941a37170032b5109d847c501124/grpcio_status-1.84.0-py3-none-any.whl", hash = "sha256:0c182ca0d6e60acbfd0e14499cf39a155e4827a1c3fd9f7638e49af15a74c30a", size = 14639, upload-time = "2026-09-14T07:10:15.175Z" }, +] + +[[package]] +name = "idna" +version = "3.20" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f5/08/8eea9d4b8302028f3abb2c0813953f7aec26d33b7a8960ed760e65ff29fa/idna-3.20.tar.gz", hash = "sha256:a7db850025b95ded1eae8a46181a1a6c56c92c96f0e2b005d9ff8dc0210cab44", size = 216463, upload-time = "2026-09-17T14:11:04.752Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/58/a2/bb081bab032533a855d44de1d56f8e8426114ff1ba5d1f07a438a0a654f8/idna-3.20-py3-none-any.whl", hash = "sha256:ab7ae7122974553370f0bdb919e1a960b2cd1bc1ef0276416d896db81c14582c", size = 69583, upload-time = "2026-09-17T14:11:03.168Z" }, +] + [[package]] name = "iniconfig" version = "2.3.1" @@ -107,6 +459,100 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/54/c8/12811c9b48fde162bb72b6f2e78fada9a247a09d7bb5be2050a5d099c77b/nodeenv-1.11.0-py2.py3-none-any.whl", hash = "sha256:edaa16e6c14d7cf395d75d4bbd5a26390f4dc06501a33b4e76282b02cc688a25", size = 34277, upload-time = "2026-09-26T11:29:19.933Z" }, ] +[[package]] +name = "opentelemetry-api" +version = "1.45.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/2e/02/6e0ae9cc61bd3169d401077b507b3ebc344745171e1051ab430be012dcd9/opentelemetry_api-1.45.1.tar.gz", hash = "sha256:aa38ed19bcc084ba42782a73255b3582283eced7ad6dddbd6695189e69adfb75", size = 72804, upload-time = "2026-10-06T17:32:58.133Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1e/41/f7dcf80b81ee8e71c1a2b59f14208bc723edbd89ed027a73b175abf6348e/opentelemetry_api-1.45.1-py3-none-any.whl", hash = "sha256:b31553efa588ae44bc306f863c785c5333a9ecc091248c6ee68b4b6c87fdedfb", size = 60256, upload-time = "2026-10-06T17:32:33.506Z" }, +] + +[[package]] +name = "opentelemetry-exporter-otlp-common" +version = "0.66b1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "opentelemetry-sdk" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/cb/19/41de712173f43057e4532d42ece7d0c6d4210d353e5752433cb14987643f/opentelemetry_exporter_otlp_common-0.66b1.tar.gz", hash = "sha256:6b1403487a2185ac1feb45fd5546fdf8630ce71c36bcefaadf51e2130e9e23f9", size = 14325, upload-time = "2026-10-06T17:33:01.725Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fc/39/8c23d67665c762aa51840fa06f86e902e8f6f1693bc8d7e3d98cd6e2f753/opentelemetry_exporter_otlp_common-0.66b1-py3-none-any.whl", hash = "sha256:00ff8592c3a7cb729ff3fdc7ffa12372c243bdf2163e80c180994d0c7bd83ee9", size = 12385, upload-time = "2026-10-06T17:32:38.177Z" }, +] + +[[package]] +name = "opentelemetry-exporter-otlp-proto-common" +version = "1.45.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "opentelemetry-proto" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c1/8e/65e85e5137991a3c493b11682151d198638a5bc1dd4b4c5f67e013c57d7c/opentelemetry_exporter_otlp_proto_common-1.45.1.tar.gz", hash = "sha256:2e4adcc3a67bcf57804fc49514f0ef64974ca7590aa3491da389852b4a0628f6", size = 18873, upload-time = "2026-10-06T17:33:04.471Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/84/aa/92f225d353904e7f70b8b3e3c1b02db0cf56f744c2e83c581dc372e78873/opentelemetry_exporter_otlp_proto_common-1.45.1-py3-none-any.whl", hash = "sha256:2f446183ae7047b036226f1d846c41a834b0e8755ad13b51a51dd38952eb466c", size = 15393, upload-time = "2026-10-06T17:32:41.911Z" }, +] + +[[package]] +name = "opentelemetry-exporter-otlp-proto-grpc" +version = "1.45.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "googleapis-common-protos" }, + { name = "grpcio" }, + { name = "opentelemetry-api" }, + { name = "opentelemetry-exporter-otlp-common" }, + { name = "opentelemetry-exporter-otlp-proto-common" }, + { name = "opentelemetry-proto" }, + { name = "opentelemetry-sdk" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/d6/00/a82af0be959dc58495740b169c6669a86e0811f6cd353a01eda34d255db3/opentelemetry_exporter_otlp_proto_grpc-1.45.1.tar.gz", hash = "sha256:3b3dcfbfdcb4e35149fcf309972282054b45228f5c10547d0095d6578510a9a0", size = 25997, upload-time = "2026-10-06T17:33:05.114Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4d/46/2d1da202f1e17c81aae7efcf702898d524b46709e4d3e2bf1f7f8ca8fbc6/opentelemetry_exporter_otlp_proto_grpc-1.45.1-py3-none-any.whl", hash = "sha256:e42ecb789d2fc5d8145e3dadc3e2991c9f18cd166d7c7514e234702540274b76", size = 19492, upload-time = "2026-10-06T17:32:42.838Z" }, +] + +[[package]] +name = "opentelemetry-proto" +version = "1.45.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "protobuf" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/4b/7f/15f014fb195da6c2dbb6c71399b8e76824878718e94de6454038488eed28/opentelemetry_proto-1.45.1.tar.gz", hash = "sha256:79e0fb95e4616691a469439238aa9224d75779b3e108e895d1aa125ab29ca77c", size = 46488, upload-time = "2026-10-06T17:33:11.49Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ab/9a/42ec8180a769516ae757e893b69736826efceac7332553915b4528a91c6d/opentelemetry_proto-1.45.1-py3-none-any.whl", hash = "sha256:f38e2a8413053c180cd3d2637fbb279673ec2f6a6e09c995aafa2f452c52b46e", size = 72488, upload-time = "2026-10-06T17:32:53.057Z" }, +] + +[[package]] +name = "opentelemetry-sdk" +version = "1.45.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "opentelemetry-api" }, + { name = "opentelemetry-semantic-conventions" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/a1/79/7392e21a1c8f0c61d90b223e31c7e48cb9d452e91a6b820ad24cca5f23c4/opentelemetry_sdk-1.45.1.tar.gz", hash = "sha256:63d24a6ca645019a631e6a51999c73e93adcac1196ca640b8ae78a7cc4762bf3", size = 218324, upload-time = "2026-10-06T17:33:13.26Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/95/3c/87c42b4bd6dd297536f04cd9383d212ac557ecd49f2cbdcd46da1c9ef5c8/opentelemetry_sdk-1.45.1-py3-none-any.whl", hash = "sha256:c604c11dc429810812348989115fa44bd558772a3d7442afc43d024f2c250ca4", size = 140063, upload-time = "2026-10-06T17:32:55.04Z" }, +] + +[[package]] +name = "opentelemetry-semantic-conventions" +version = "0.66b1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "opentelemetry-api" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/46/e4/dbbfb2a010c4db2224a5114638acede6fe563d33cc20fb1752cebcbe6298/opentelemetry_semantic_conventions-0.66b1.tar.gz", hash = "sha256:497ca63bf383723411e8eaf60c8779e9877633c936bb641080adab59d0eb6ec8", size = 150250, upload-time = "2026-10-06T17:33:14.073Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/bc/14/67f8aa798857f8cf686f515bf93d9bb877ce952ddc8efae0fa25b45ce0d6/opentelemetry_semantic_conventions-0.66b1-py3-none-any.whl", hash = "sha256:d4cddeb4315490b35213f55e2bdc9ac54bb1e4d318927475bed62b35545e581b", size = 206279, upload-time = "2026-10-06T17:32:56.103Z" }, +] + [[package]] name = "packaging" version = "26.3" @@ -125,11 +571,84 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/40/9e/2b38731e0fc536806f16490e1a12d7f0dc2a1235aa8cc07bcc75416a7daa/pluggy-1.7.0-py3-none-any.whl", hash = "sha256:7dd7b0d8832ba3cb632c306926ded123429211b83641b35dc5c41ad2d34f9bec", size = 27082, upload-time = "2026-10-15T09:50:56.808Z" }, ] +[[package]] +name = "policyengine-observability" +version = "3.0.5" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/22/d4/9c85331075d61e4eec1c7aec905aee6221006c5bd81474ebb66f1c7d9a8d/policyengine_observability-3.0.5.tar.gz", hash = "sha256:de70cb5cbb6944cbad40eaa566c0fab661b2dc4747c9b3f874d7a096eedf7363", size = 129269, upload-time = "2026-10-27T20:37:05.035Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ba/c9/e6da2a9c35a6cd533708ad282091d57212fd8784d4c668102727f23b8d50/policyengine_observability-3.0.5-py3-none-any.whl", hash = "sha256:ff566284f3a742bcafd2f1738dd8de54990f125c591e3dab351750982eab79dc", size = 42574, upload-time = "2026-10-27T20:37:03.684Z" }, +] + +[package.optional-dependencies] +fastapi = [ + { name = "fastapi" }, +] +google = [ + { name = "google-auth" }, + { name = "google-cloud-logging" }, +] +otlp-grpc = [ + { name = "opentelemetry-api" }, + { name = "opentelemetry-exporter-otlp-proto-grpc" }, + { name = "opentelemetry-sdk" }, +] + +[[package]] +name = "policyengine-simulation-contract" +version = "0.1.0" +source = { editable = "../policyengine-simulation-contract" } +dependencies = [ + { name = "packaging" }, + { name = "policyengine-simulation-observability" }, + { name = "pydantic" }, +] + +[package.metadata] +requires-dist = [ + { name = "black", marker = "extra == 'build'", specifier = ">=25.1.0" }, + { name = "modal", marker = "extra == 'modal'", specifier = ">=1.4,<2" }, + { name = "modal", marker = "extra == 'test'", specifier = ">=1.4,<2" }, + { name = "packaging", specifier = ">=24" }, + { name = "policyengine-simulation-observability", editable = "../policyengine-simulation-observability" }, + { name = "pydantic", specifier = ">=2.0" }, + { name = "pyright", marker = "extra == 'build'", specifier = ">=1.1.401" }, + { name = "pytest", marker = "extra == 'test'", specifier = ">=8.3.4" }, + { name = "pytest-asyncio", marker = "extra == 'test'", specifier = ">=0.25.3" }, + { name = "pytest-cov", marker = "extra == 'test'", specifier = ">=6.1.1" }, +] +provides-extras = ["modal", "test", "build"] + +[[package]] +name = "policyengine-simulation-observability" +version = "0.1.0" +source = { editable = "../policyengine-simulation-observability" } +dependencies = [ + { name = "fastapi" }, + { name = "policyengine-observability", extra = ["fastapi", "google", "otlp-grpc"] }, + { name = "pydantic" }, +] + +[package.metadata] +requires-dist = [ + { name = "black", marker = "extra == 'build'", specifier = ">=25.1.0" }, + { name = "fastapi", specifier = ">=0.115.0" }, + { name = "httpx2", marker = "extra == 'test'" }, + { name = "policyengine-observability", extras = ["fastapi", "google", "otlp-grpc"], specifier = ">=3.0.4,<4" }, + { name = "pydantic", specifier = ">=2.0" }, + { name = "pyright", marker = "extra == 'build'", specifier = ">=1.1.401" }, + { name = "pytest", marker = "extra == 'test'", specifier = ">=8.3.4" }, + { name = "pytest-asyncio", marker = "extra == 'test'", specifier = ">=0.25.3" }, + { name = "pytest-cov", marker = "extra == 'test'", specifier = ">=6.1.1" }, +] +provides-extras = ["test", "build"] + [[package]] name = "policyengine-simulation-persistence" version = "0.1.0" source = { editable = "." } dependencies = [ + { name = "policyengine-simulation-contract" }, { name = "psycopg", extra = ["binary"] }, { name = "sqlalchemy" }, ] @@ -152,6 +671,7 @@ test = [ requires-dist = [ { name = "alembic", marker = "extra == 'migrations'", specifier = ">=1.17.1,<2" }, { name = "alembic", marker = "extra == 'test'", specifier = ">=1.17.1,<2" }, + { name = "policyengine-simulation-contract", editable = "../policyengine-simulation-contract" }, { name = "psycopg", extras = ["binary"], specifier = ">=3.2,<4" }, { name = "pyright", marker = "extra == 'build'", specifier = ">=1.1.401" }, { name = "pytest", marker = "extra == 'test'", specifier = ">=8.3.4" }, @@ -161,6 +681,33 @@ requires-dist = [ ] provides-extras = ["migrations", "test", "build"] +[[package]] +name = "proto-plus" +version = "1.29.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "protobuf" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/46/70/783e33ffbb4466cc154a94f79b869b92a451e2bd45605054e68ff68b7af6/proto_plus-1.29.0.tar.gz", hash = "sha256:cfb4e62ad7e13dd18f346cabbda00cab39930d36a05791fd81ddb074d6ee884f", size = 58592, upload-time = "2026-09-29T19:26:15.963Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b1/05/a3ef5b1161498e7b5a2a60288a9cf41b9149e94555423a43ec536737ac1a/proto_plus-1.29.0-py3-none-any.whl", hash = "sha256:8acd070469a7aaf43f440b022ef9757c8cac1a9f866e933f59ae98669ddc6c8b", size = 50786, upload-time = "2026-09-29T19:25:50.409Z" }, +] + +[[package]] +name = "protobuf" +version = "7.36.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d9/89/5b8517baa72f84a67b8a307ba953c91057af618bf40bf676f3c03551f8f0/protobuf-7.36.2.tar.gz", hash = "sha256:497d0463ff3316681da6c0b9e8d06cb465d61abce00b613ab42226175644d1bb", size = 512737, upload-time = "2026-09-17T20:07:59.326Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/32/72/98342feb672507c8f3a69e34b4fa8961f608edba5c1a48a6f47156d92cb5/protobuf-7.36.2-cp310-abi3-macosx_10_9_universal2.whl", hash = "sha256:cbc70b17ee27e28894c7fee8bb04be1abead49e936bc70eb60052531eee2079e", size = 456039, upload-time = "2026-09-17T20:07:51.542Z" }, + { url = "https://files.pythonhosted.org/packages/b6/ea/91fdf7c2b8bbd49cde056f00a9df6773532987e1c00fe2830b895af95c7e/protobuf-7.36.2-cp310-abi3-manylinux2014_aarch64.whl", hash = "sha256:e11e1f0180583a2af89db6a2ecd9e8dc40aa6d2988ca175bfd0e6d12ea72d74e", size = 344219, upload-time = "2026-09-17T20:07:52.914Z" }, + { url = "https://files.pythonhosted.org/packages/17/ab/5fd5f8ece73fad885c5a09aa849b32d70472f954ba3a92d3bb5974ea953b/protobuf-7.36.2-cp310-abi3-manylinux2014_s390x.whl", hash = "sha256:f4fee11ec330d238b34a05c9b675f693c20415d1c5bd7d5320cc2f8a798eb9cf", size = 357223, upload-time = "2026-09-17T20:07:53.985Z" }, + { url = "https://files.pythonhosted.org/packages/db/f3/3996583dd2906297a637af12114deddf7658af6e683fedb83be061983fb5/protobuf-7.36.2-cp310-abi3-manylinux2014_x86_64.whl", hash = "sha256:89f23aa53c24553a2416fd4fd1ec06f74fa42b14b546d8883128813f775bbfd2", size = 343223, upload-time = "2026-09-17T20:07:54.931Z" }, + { url = "https://files.pythonhosted.org/packages/fc/1b/dcc64f358fcb51811b58ae40b3d28f820725f116d86487cc20bd4b130701/protobuf-7.36.2-cp310-abi3-win32.whl", hash = "sha256:912c1221170e16c08d1f086762f563dd61ff83c18b5fa6652952dfaded66f728", size = 442998, upload-time = "2026-09-17T20:07:55.826Z" }, + { url = "https://files.pythonhosted.org/packages/8a/55/b77bda4e5e5f5971fb51b07663694690e9afdb9402136c16a522bd621cad/protobuf-7.36.2-cp310-abi3-win_amd64.whl", hash = "sha256:a300819d441e078a5608c0d3c709796bb548136058fda017ae51d425b44fd353", size = 456514, upload-time = "2026-09-17T20:07:57.188Z" }, + { url = "https://files.pythonhosted.org/packages/e4/04/d52c7016b04b6c5108f26691f9d33ec82a9b65d041f1a9c771137693d618/protobuf-7.36.2-py3-none-any.whl", hash = "sha256:bdb3a345d48db958e6ce1f18e508beb0cc981d64f24088427549c866cd039f1e", size = 179806, upload-time = "2026-09-17T20:07:58.211Z" }, +] + [[package]] name = "psycopg" version = "3.3.6" @@ -196,6 +743,77 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/55/7f/e350e1cf498ba2565c3f87b12f429d2012eb86b76c2b3845a19ee5fbb4d6/psycopg_binary-3.3.6-cp313-cp313-win_amd64.whl", hash = "sha256:0ebfad5d131de9f892ae9e70cc7616207768b6714b66a52d4612b8ceaf78b372", size = 3658179, upload-time = "2026-09-18T13:20:22.691Z" }, ] +[[package]] +name = "pyasn1" +version = "0.6.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a4/9a/23310166d960def5897e91fe20e5b724601b02a22e84ba1f94232c0b7f67/pyasn1-0.6.4.tar.gz", hash = "sha256:9c447d8431c947fe4c8febc4ed9e760bc29011a5b01e5c74b67025bd9fb8ce81", size = 151262, upload-time = "2026-07-09T01:12:33.988Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9a/3b/6163796d69c3977d1e4287bea4a6979161cbbdd170ebb430511e8e1999ce/pyasn1-0.6.4-py3-none-any.whl", hash = "sha256:deda9277cfd454080ec40b207fb6df82206a3a2688735233cdcd8d3d565f088b", size = 84410, upload-time = "2026-07-09T01:12:32.92Z" }, +] + +[[package]] +name = "pyasn1-modules" +version = "0.4.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pyasn1" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/e9/e6/78ebbb10a8c8e4b61a59249394a4a594c1a7af95593dc933a349c8d00964/pyasn1_modules-0.4.2.tar.gz", hash = "sha256:677091de870a80aae844b1ca6134f54652fa2c8c5a52aa396440ac3106e941e6", size = 307892, upload-time = "2025-03-28T02:41:22.17Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/47/8d/d529b5d697919ba8c11ad626e835d4039be708a35b0d22de83a269a6682c/pyasn1_modules-0.4.2-py3-none-any.whl", hash = "sha256:29253a9207ce32b64c3ac6600edc75368f98473906e8fd1043bd6b5b1de2c14a", size = 181259, upload-time = "2025-03-28T02:41:19.028Z" }, +] + +[[package]] +name = "pycparser" +version = "3.12" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/cb/27/eeb9f307bf07060f3d9f9aa0fb8c15b01bdfded0a941e4b2719c7f94cacd/pycparser-3.12.tar.gz", hash = "sha256:f03387877eab82ce01bbdfd0ba7252ee55a90b1c708d5129e2ce915475cf1db6", size = 158785, upload-time = "2026-10-22T13:40:03.56Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b6/ae/315bbeee126a769cbde43cf4908acb4b40408d8bf8bbf334dd7368d8dadf/pycparser-3.12-py3-none-any.whl", hash = "sha256:a076f3f489b39b43ed13563a1dafe42447445bec2e294154ec5c57fcdda4c85e", size = 62600, upload-time = "2026-10-22T13:40:02.021Z" }, +] + +[[package]] +name = "pydantic" +version = "2.14.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "annotated-types" }, + { name = "pydantic-core" }, + { name = "typing-extensions" }, + { name = "typing-inspection" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/7c/0b/8e10b2e693af8ec54346a14caf36221334775975a747c9ceaa3f8371d96d/pydantic-2.14.1.tar.gz", hash = "sha256:94f478203dd03404682a1ada216965651dd74b1d2d5ffd62e00e0837caab5c26", size = 900362, upload-time = "2026-10-11T18:37:55.396Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/35/ea/a56b9fe5066f3537b7882f77e9c5dfb26d8c2eefdaed9b5fc73d57b4dc22/pydantic-2.14.1-py3-none-any.whl", hash = "sha256:9195d967ec791692a04438115466764fb8b9a27b31f14a760437694f40d6b454", size = 488106, upload-time = "2026-10-11T18:37:53.437Z" }, +] + +[[package]] +name = "pydantic-core" +version = "2.50.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/a6/24/af4ec4be49fbc810f35b0bdcacc3d433b56bbfa469fd3bfd4ae116cd9bf1/pydantic_core-2.50.1.tar.gz", hash = "sha256:e50d7b94baac6c7d09927fa5ca5800a0c7ee5015c7fcff65beb3a1931b5a6e09", size = 513515, upload-time = "2026-10-11T18:35:44.82Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ae/57/0e237d7091d2cd44a35d243b7344227f90440166860469cd036afc23a04d/pydantic_core-2.50.1-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:d5e062c01286d861fd6a1c4ff6e063547b3e713067f2df033c0ff97ac2ca006b", size = 2222774, upload-time = "2026-10-11T18:32:43.103Z" }, + { url = "https://files.pythonhosted.org/packages/f7/b9/c720e56858d4e1539503297ed37063e0c08e0f3541c41b777f6a800f75fa/pydantic_core-2.50.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0c003c3b7f49debb893d2d85ae099ac5959c9839e2f330fadb1fcdf7a6594482", size = 2024738, upload-time = "2026-10-11T18:32:44.587Z" }, + { url = "https://files.pythonhosted.org/packages/4d/b8/fbfc25875219cc060e613170ff10e850c6d8924beb4910da57c2ee3ba1d2/pydantic_core-2.50.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:409e0ea40ec30d9158f33574fd758e689f6045a0f2596701828c27816ca9687d", size = 2047049, upload-time = "2026-10-11T18:32:46.164Z" }, + { url = "https://files.pythonhosted.org/packages/d7/43/34210124d504c553688f2f04b48500b131237528ac545b445e0d6d30e0d5/pydantic_core-2.50.1-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:131059670f1d2444269b8585cb888963994871932447c08b39ac6a51fcfef658", size = 2173415, upload-time = "2026-10-11T18:32:47.722Z" }, + { url = "https://files.pythonhosted.org/packages/65/cf/6e178e8fdc11da5965bef980983bf46326a42f436871dd51ba0a57f39df1/pydantic_core-2.50.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6dbcbee53bf17196a7f745aa9bf5a9603953a1e365b1f020be3207c676a3e7c4", size = 2361719, upload-time = "2026-10-11T18:32:49.217Z" }, + { url = "https://files.pythonhosted.org/packages/11/14/bd5169d356aa91bf777e28ba0b281c192d286d03c2812c9c9db023a2f00e/pydantic_core-2.50.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:325c23f3e35cfbf0fe3486fa5f7260d1e45885173002d30a28ca019994124255", size = 2439803, upload-time = "2026-10-11T18:32:51.025Z" }, + { url = "https://files.pythonhosted.org/packages/1c/bc/d79d000e5203ebef39af839f2ce77a777fcad6e08ad26af9a2fcd114ffc8/pydantic_core-2.50.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:17e722e156d0444ecaefbe640bdb60928752bf2013e2b7a11cdb099aaae19bec", size = 2158402, upload-time = "2026-10-11T18:32:52.714Z" }, + { url = "https://files.pythonhosted.org/packages/1b/a5/4902cb5fd599422c130bd3124ab31ee8b771199bd56662702eed07d3fec7/pydantic_core-2.50.1-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:aa8224f10880d9bf1b5993988ba153d42a8b4f3f4f511f93b1f09c93ff613c72", size = 2229755, upload-time = "2026-10-11T18:32:54.126Z" }, + { url = "https://files.pythonhosted.org/packages/1a/f5/c1481f8669f6060d89110c9b1374173fc8767ca276b84f4870bd8acd5e3f/pydantic_core-2.50.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:41bc8237121bd8dc8d888dfd6279fc166ffc88c1f1bf3a8bf00869680533ca4c", size = 2242303, upload-time = "2026-10-11T18:32:55.641Z" }, + { url = "https://files.pythonhosted.org/packages/04/f9/77fc3c7653ba9b6e42049e17e96b25388187d4a7c274ab1cb07f58ac8419/pydantic_core-2.50.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:45c6266d071c241f2a168d45bf8c54344f0effce35e7e6b73afdec11f3687568", size = 2278345, upload-time = "2026-10-11T18:32:57.38Z" }, + { url = "https://files.pythonhosted.org/packages/95/9b/0579c5d12e7f2b16b27e6782427987341fcce07b0725e02ddb0b74add0c4/pydantic_core-2.50.1-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:1deeacb112d14d3f4fcb16b165f7dbaf76c70ba6e82f37ba042bdab51970a0b8", size = 2449947, upload-time = "2026-10-11T18:32:58.896Z" }, + { url = "https://files.pythonhosted.org/packages/a8/ac/1b677db91eba54cc5922f4de6edc46ba45c2bd712dfdc0130382d158e214/pydantic_core-2.50.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:1c96fd793b73d1b92e65570132505498fe7b21eaef73cdf74e67e5dfba7ac9e4", size = 2476889, upload-time = "2026-10-11T18:33:00.665Z" }, + { url = "https://files.pythonhosted.org/packages/4d/2a/3a9f6624ee3ea9ccba5249dde11418bb4c35780a7a92608f8768bd3fea39/pydantic_core-2.50.1-cp313-cp313-win32.whl", hash = "sha256:06ead20d39ffd6f2f6f2a8f8a6de67ff8bb1b4f14a8a30e058502514ee2ac685", size = 2101118, upload-time = "2026-10-11T18:33:02.329Z" }, + { url = "https://files.pythonhosted.org/packages/2d/1f/323f78ddd9d9938aac420c1abb4e8ba799fc8bdab0acc67c0593b837c979/pydantic_core-2.50.1-cp313-cp313-win_amd64.whl", hash = "sha256:7816e98acc08119dc0f340ab167048ecc54126316330c1f0caf7c6756c88e28f", size = 2170840, upload-time = "2026-10-11T18:33:03.919Z" }, + { url = "https://files.pythonhosted.org/packages/cb/09/8497c52a739ae425c3ac2f7f56414cbc711c67d374346174f40fe2062644/pydantic_core-2.50.1-cp313-cp313-win_arm64.whl", hash = "sha256:c17799a62c142d61b8a3c51752a7cbc87fe2ad4ccfab10e628a77b405075c662", size = 2161633, upload-time = "2026-10-11T18:33:05.518Z" }, +] + [[package]] name = "pygments" version = "2.21.0" @@ -266,6 +884,21 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/73/e8/2bdf3ca2090f68bb3d75b44da7bbc71843b19c9f2b9cb9b0f4ab7a5a4329/pyyaml-6.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:5498cd1645aa724a7c71c8f378eb29ebe23da2fc0d7a08071d89469bf1d2defb", size = 140246, upload-time = "2025-09-25T21:32:34.663Z" }, ] +[[package]] +name = "requests" +version = "2.34.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "certifi" }, + { name = "charset-normalizer" }, + { name = "idna" }, + { name = "urllib3" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ac/c3/e2a2b89f2d3e2179abd6d00ebd70bff6273f37fb3e0cc209f48b39d00cbf/requests-2.34.2.tar.gz", hash = "sha256:f288924cae4e29463698d6d60bc6a4da69c89185ad1e0bcc4104f584e960b9ed", size = 142856, upload-time = "2026-05-14T19:25:27.735Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a0/f4/c67b0b3f1b9245e8d266f0f112c500d50e5b4e83cb6f3b71b6528104182a/requests-2.34.2-py3-none-any.whl", hash = "sha256:2a0d60c172f83ac6ab31e4554906c0f3b3588d37b5cb939b1c061f4907e278e0", size = 73075, upload-time = "2026-05-14T19:25:26.443Z" }, +] + [[package]] name = "sqlalchemy" version = "2.1.6" @@ -288,6 +921,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/c1/69/c75534e336b06b3fd3f76de73d89736510800e60c77c58d4e4ce18389018/sqlalchemy-2.1.6-py3-none-any.whl", hash = "sha256:106878cf3795cd3d357e2e858609f9e44f20f19b2d8e48a3532bef3f90b03fbe", size = 2063055, upload-time = "2026-10-21T18:42:10.234Z" }, ] +[[package]] +name = "starlette" +version = "1.9.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ad/eb/4e197bf26b023abafc5e9043ec8710d7de0fcb032d0969045236d72aa0b1/starlette-1.9.0.tar.gz", hash = "sha256:3d931de246ed870e35ce605974440816ef895e592f255d1396cfdf191d4c4318", size = 2732466, upload-time = "2026-10-18T15:50:33.189Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f3/93/181df62699d9b5aca1d87e5cfda131dac87e3cdaebf668662f7206ca3470/starlette-1.9.0-py3-none-any.whl", hash = "sha256:fd3f159936e882d06c1108f84688f7cda2cf85fc6a592a50edbd175e882c2ddc", size = 80335, upload-time = "2026-10-18T15:50:31.526Z" }, +] + [[package]] name = "typing-extensions" version = "4.16.0" @@ -297,6 +942,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/49/d3/b8441a820a491ddfc024b0b0cf0393375b75ea13866d9c66727e54c2fc80/typing_extensions-4.16.0-py3-none-any.whl", hash = "sha256:481caa481374e813c1b176ada14e97f1f67a4539ce9cfeb3f350d78d6370c2e8", size = 45571, upload-time = "2026-07-02T08:40:04.659Z" }, ] +[[package]] +name = "typing-inspection" +version = "0.4.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/a3/26/b09b8010994eccc3c09092e6b34058f36a460eea2d4c3e8b910c695975a0/typing_inspection-0.4.4.tar.gz", hash = "sha256:547274fa6b0a561ccf549cc9524b999a578e737d015d8709d021f9d0d13bea47", size = 76928, upload-time = "2026-08-12T12:37:25.997Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/67/81/4add07e5172b7ac40d8ed5ff580409a7801a4fe26d529bdd915401dabfbe/typing_inspection-0.4.4-py3-none-any.whl", hash = "sha256:65b8397ba37ccbce054456aaccddfc91e6e3083c92824df348d96ca832f3f147", size = 14750, upload-time = "2026-08-12T12:37:24.648Z" }, +] + [[package]] name = "tzdata" version = "2026.5" @@ -305,3 +962,12 @@ sdist = { url = "https://files.pythonhosted.org/packages/d9/68/f1b440335057bfce7 wheels = [ { url = "https://files.pythonhosted.org/packages/94/21/1e5995a1c920cce14e4bffae20c665ec10e7ed03ab25e006cd741092b718/tzdata-2026.5-py2.py3-none-any.whl", hash = "sha256:b683bd1b6659ddcd810ff02ad09ba821d4bf1065072805063eb35c49617905ac", size = 347996, upload-time = "2026-10-03T09:23:12.535Z" }, ] + +[[package]] +name = "urllib3" +version = "2.8.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e3/05/b17359e1cefb4f909b5e40b1b90a496d987258916dbbf88e842c729f510e/urllib3-2.8.0.tar.gz", hash = "sha256:63bf2ead4c879426ebf22ef2a781eeb4aa3b4ae798a0435506f8687fd5bb9b63", size = 458972, upload-time = "2026-09-15T19:29:36.253Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/92/9d/c4e665119135114480843e7ab388fa94d8480650450e6f8e26b70d323a4c/urllib3-2.8.0-py3-none-any.whl", hash = "sha256:0cf3cae568d36aa9576b28dfb35f11328f1cb974ca7647d9475ebb86c75ac6e3", size = 135717, upload-time = "2026-09-15T19:29:34.577Z" }, +] diff --git a/migrations/versions/0004_economy_result_tables.py b/migrations/versions/0004_economy_result_tables.py new file mode 100644 index 000000000..6b490d218 --- /dev/null +++ b/migrations/versions/0004_economy_result_tables.py @@ -0,0 +1,383 @@ +"""Add the economy result tables. + +Every economy result is stored as rows, each section of today's result model +in its own table. A simulation's own figures (poverty rates, inequality, cliff +exposure) belong to its simulation run; the comparison of a baseline and a +reform (budget, programs, deciles, labour supply, geographies) belongs to the +report run. Each report run also records the optional sections its result +holds and its SPM provenance. Rows are written in the transaction that marks a +run succeeded; the default privileges let the runtime role read and insert +them. Nothing writes them yet. + +Revision ID: 0004 +Revises: 0003 +Create Date: 2026-10-22 +""" + +from __future__ import annotations + +import sqlalchemy as sa +from alembic import op +from sqlalchemy.dialects import postgresql + +revision = "0004" +down_revision = "0003" +branch_labels = None +depends_on = None + + +def upgrade() -> None: + """Create the result tables and the report run's result columns.""" + op.create_table( + "cliff_impacts", + sa.Column("simulation_run_id", sa.Uuid(), nullable=False), + sa.Column("cliff_gap", sa.Double(), nullable=False), + sa.Column("cliff_share", sa.Double(), nullable=False), + sa.ForeignKeyConstraint( + ["simulation_run_id"], + ["simulation.simulation_runs.id"], + name="fk_cliff_impacts_simulation_run", + ondelete="RESTRICT", + ), + sa.PrimaryKeyConstraint("simulation_run_id", name=op.f("pk_cliff_impacts")), + schema="simulation", + ) + op.create_table( + "inequality", + sa.Column("simulation_run_id", sa.Uuid(), nullable=False), + sa.Column("gini", sa.Double(), nullable=False), + sa.Column("top_10_pct_share", sa.Double(), nullable=False), + sa.Column("top_1_pct_share", sa.Double(), nullable=False), + sa.ForeignKeyConstraint( + ["simulation_run_id"], + ["simulation.simulation_runs.id"], + name="fk_inequality_simulation_run", + ondelete="RESTRICT", + ), + sa.PrimaryKeyConstraint("simulation_run_id", name=op.f("pk_inequality")), + schema="simulation", + ) + op.create_table( + "poverty_rates", + sa.Column("simulation_run_id", sa.Uuid(), nullable=False), + sa.Column("measure", sa.Text(), nullable=False), + sa.Column("group_dimension", sa.Text(), nullable=False), + sa.Column("group_value", sa.Text(), nullable=False), + sa.Column("rate", sa.Double(), nullable=False), + sa.CheckConstraint( + "(group_dimension = 'age' " + "AND group_value IN ('child', 'adult', 'senior', 'all')) " + "OR (group_dimension = 'gender' AND group_value IN ('male', 'female')) " + "OR (group_dimension = 'race' " + "AND group_value IN ('white', 'black', 'hispanic', 'other'))", + name=op.f("ck_poverty_rates_group"), + ), + sa.CheckConstraint( + "measure IN ('poverty', 'deep_poverty')", + name=op.f("ck_poverty_rates_measure"), + ), + sa.ForeignKeyConstraint( + ["simulation_run_id"], + ["simulation.simulation_runs.id"], + name="fk_poverty_rates_simulation_run", + ondelete="RESTRICT", + ), + sa.PrimaryKeyConstraint( + "simulation_run_id", + "measure", + "group_dimension", + "group_value", + name=op.f("pk_poverty_rates"), + ), + schema="simulation", + ) + op.create_table( + "budget_impacts", + sa.Column("report_run_id", sa.Uuid(), nullable=False), + sa.Column("budgetary_impact", sa.Double(), nullable=False), + sa.Column("tax_revenue_impact", sa.Double(), nullable=False), + sa.Column("state_tax_revenue_impact", sa.Double(), nullable=False), + sa.Column("benefit_spending_impact", sa.Double(), nullable=False), + sa.Column("households", sa.Double(), nullable=False), + sa.Column("baseline_net_income", sa.Double(), nullable=False), + sa.ForeignKeyConstraint( + ["report_run_id"], + ["simulation.report_runs.id"], + name="fk_budget_impacts_report_run", + ondelete="RESTRICT", + ), + sa.PrimaryKeyConstraint("report_run_id", name=op.f("pk_budget_impacts")), + schema="simulation", + ) + op.create_table( + "congressional_district_impacts", + sa.Column("report_run_id", sa.Uuid(), nullable=False), + sa.Column("district", sa.Text(), nullable=False), + sa.Column("position", sa.Integer(), nullable=False), + sa.Column("average_household_income_change", sa.Double(), nullable=False), + sa.Column("relative_household_income_change", sa.Double(), nullable=False), + sa.Column("winner_percentage", sa.Double(), nullable=False), + sa.Column("loser_percentage", sa.Double(), nullable=False), + sa.Column("no_change_percentage", sa.Double(), nullable=False), + sa.Column("population", sa.Double(), nullable=False), + sa.CheckConstraint( + "position >= 0", name=op.f("ck_congressional_district_impacts_position") + ), + sa.ForeignKeyConstraint( + ["report_run_id"], + ["simulation.report_runs.id"], + name="fk_congressional_district_impacts_report_run", + ondelete="RESTRICT", + ), + sa.PrimaryKeyConstraint( + "report_run_id", "district", name=op.f("pk_congressional_district_impacts") + ), + sa.UniqueConstraint( + "report_run_id", + "position", + name=op.f("uq_congressional_district_impacts_report_run_id_position"), + ), + schema="simulation", + ) + op.create_table( + "constituency_impacts", + sa.Column("report_run_id", sa.Uuid(), nullable=False), + sa.Column("constituency_code", sa.Text(), nullable=False), + sa.Column("position", sa.Integer(), nullable=False), + sa.Column("average_household_income_change", sa.Double(), nullable=False), + sa.Column("relative_household_income_change", sa.Double(), nullable=False), + sa.Column("population", sa.Double(), nullable=False), + sa.CheckConstraint( + "position >= 0", name=op.f("ck_constituency_impacts_position") + ), + sa.ForeignKeyConstraint( + ["report_run_id"], + ["simulation.report_runs.id"], + name="fk_constituency_impacts_report_run", + ondelete="RESTRICT", + ), + sa.PrimaryKeyConstraint( + "report_run_id", "constituency_code", name=op.f("pk_constituency_impacts") + ), + sa.UniqueConstraint( + "report_run_id", + "position", + name=op.f("uq_constituency_impacts_report_run_id_position"), + ), + schema="simulation", + ) + op.create_table( + "decile_impacts", + sa.Column("report_run_id", sa.Uuid(), nullable=False), + sa.Column("measure", sa.Text(), nullable=False), + sa.Column("decile", sa.Text(), nullable=False), + sa.Column("position", sa.Integer(), nullable=False), + sa.Column("average_change", sa.Double(), nullable=False), + sa.Column("relative_change", sa.Double(), nullable=False), + sa.CheckConstraint( + "measure IN ('income', 'wealth')", name=op.f("ck_decile_impacts_measure") + ), + sa.CheckConstraint("position >= 0", name=op.f("ck_decile_impacts_position")), + sa.ForeignKeyConstraint( + ["report_run_id"], + ["simulation.report_runs.id"], + name="fk_decile_impacts_report_run", + ondelete="RESTRICT", + ), + sa.PrimaryKeyConstraint( + "report_run_id", "measure", "decile", name=op.f("pk_decile_impacts") + ), + sa.UniqueConstraint( + "report_run_id", + "measure", + "position", + name=op.f("uq_decile_impacts_report_run_id_measure_position"), + ), + schema="simulation", + ) + op.create_table( + "intra_decile_impacts", + sa.Column("report_run_id", sa.Uuid(), nullable=False), + sa.Column("measure", sa.Text(), nullable=False), + sa.Column("outcome", sa.Text(), nullable=False), + sa.Column("outcome_position", sa.Integer(), nullable=False), + sa.Column("decile", sa.SmallInteger(), nullable=True), + sa.Column("share", sa.Double(), nullable=False), + sa.CheckConstraint( + "measure IN ('income', 'wealth')", + name=op.f("ck_intra_decile_impacts_measure"), + ), + sa.CheckConstraint( + "decile IS NULL OR decile >= 1", name=op.f("ck_intra_decile_impacts_decile") + ), + sa.CheckConstraint( + "outcome_position >= 0", + name=op.f("ck_intra_decile_impacts_outcome_position"), + ), + sa.ForeignKeyConstraint( + ["report_run_id"], + ["simulation.report_runs.id"], + name="fk_intra_decile_impacts_report_run", + ondelete="RESTRICT", + ), + sa.UniqueConstraint( + "report_run_id", + "measure", + "outcome", + "decile", + name=op.f("uq_intra_decile_impacts_report_run_id_measure_outcome_decile"), + postgresql_nulls_not_distinct=True, + ), + schema="simulation", + ) + op.create_table( + "labor_supply_decile_impacts", + sa.Column("report_run_id", sa.Uuid(), nullable=False), + sa.Column("decile", sa.Integer(), nullable=False), + sa.Column("position", sa.Integer(), nullable=False), + sa.Column("average_income_effect", sa.Double(), nullable=False), + sa.Column("average_substitution_effect", sa.Double(), nullable=False), + sa.Column("relative_income_effect", sa.Double(), nullable=False), + sa.Column("relative_substitution_effect", sa.Double(), nullable=False), + sa.CheckConstraint( + "position >= 0", name=op.f("ck_labor_supply_decile_impacts_position") + ), + sa.ForeignKeyConstraint( + ["report_run_id"], + ["simulation.report_runs.id"], + name="fk_labor_supply_decile_impacts_report_run", + ondelete="RESTRICT", + ), + sa.PrimaryKeyConstraint( + "report_run_id", "decile", name=op.f("pk_labor_supply_decile_impacts") + ), + sa.UniqueConstraint( + "report_run_id", + "position", + name=op.f("uq_labor_supply_decile_impacts_report_run_id_position"), + ), + schema="simulation", + ) + op.create_table( + "labor_supply_responses", + sa.Column("report_run_id", sa.Uuid(), nullable=False), + sa.Column("substitution_lsr", sa.Double(), nullable=False), + sa.Column("income_lsr", sa.Double(), nullable=False), + sa.Column("relative_income_response", sa.Double(), nullable=False), + sa.Column("relative_substitution_response", sa.Double(), nullable=False), + sa.Column("total_change", sa.Double(), nullable=False), + sa.Column("revenue_change", sa.Double(), nullable=False), + sa.Column("baseline_hours", sa.Double(), nullable=False), + sa.Column("reform_hours", sa.Double(), nullable=False), + sa.Column("hours_change", sa.Double(), nullable=False), + sa.Column("hours_income_effect", sa.Double(), nullable=False), + sa.Column("hours_substitution_effect", sa.Double(), nullable=False), + sa.ForeignKeyConstraint( + ["report_run_id"], + ["simulation.report_runs.id"], + name="fk_labor_supply_responses_report_run", + ondelete="RESTRICT", + ), + sa.PrimaryKeyConstraint( + "report_run_id", name=op.f("pk_labor_supply_responses") + ), + schema="simulation", + ) + op.create_table( + "local_authority_impacts", + sa.Column("report_run_id", sa.Uuid(), nullable=False), + sa.Column("local_authority_code", sa.Text(), nullable=False), + sa.Column("position", sa.Integer(), nullable=False), + sa.Column("average_household_income_change", sa.Double(), nullable=False), + sa.Column("relative_household_income_change", sa.Double(), nullable=False), + sa.Column("population", sa.Double(), nullable=False), + sa.CheckConstraint( + "position >= 0", name=op.f("ck_local_authority_impacts_position") + ), + sa.ForeignKeyConstraint( + ["report_run_id"], + ["simulation.report_runs.id"], + name="fk_local_authority_impacts_report_run", + ondelete="RESTRICT", + ), + sa.PrimaryKeyConstraint( + "report_run_id", + "local_authority_code", + name=op.f("pk_local_authority_impacts"), + ), + sa.UniqueConstraint( + "report_run_id", + "position", + name=op.f("uq_local_authority_impacts_report_run_id_position"), + ), + schema="simulation", + ) + op.create_table( + "program_budget_impacts", + sa.Column("report_run_id", sa.Uuid(), nullable=False), + sa.Column("program", sa.Text(), nullable=False), + sa.Column("position", sa.Integer(), nullable=False), + sa.Column("baseline", sa.Double(), nullable=False), + sa.Column("reform", sa.Double(), nullable=False), + sa.Column("difference", sa.Double(), nullable=False), + sa.CheckConstraint( + "position >= 0", name=op.f("ck_program_budget_impacts_position") + ), + sa.ForeignKeyConstraint( + ["report_run_id"], + ["simulation.report_runs.id"], + name="fk_program_budget_impacts_report_run", + ondelete="RESTRICT", + ), + sa.PrimaryKeyConstraint( + "report_run_id", "program", name=op.f("pk_program_budget_impacts") + ), + sa.UniqueConstraint( + "report_run_id", + "position", + name=op.f("uq_program_budget_impacts_report_run_id_position"), + ), + schema="simulation", + ) + op.add_column( + "report_runs", + sa.Column("result_sections", postgresql.ARRAY(sa.Text()), nullable=True), + schema="simulation", + ) + op.add_column( + "report_runs", + sa.Column( + "spm_provenance", postgresql.JSONB(astext_type=sa.Text()), nullable=True + ), + schema="simulation", + ) + op.create_check_constraint( + op.f("ck_report_runs_spm_provenance"), + "report_runs", + "spm_provenance IS NULL OR jsonb_typeof(spm_provenance) = 'object'", + schema="simulation", + ) + + +def downgrade() -> None: + """Drop what ``upgrade`` created.""" + op.drop_constraint( + op.f("ck_report_runs_spm_provenance"), + "report_runs", + schema="simulation", + type_="check", + ) + op.drop_column("report_runs", "spm_provenance", schema="simulation") + op.drop_column("report_runs", "result_sections", schema="simulation") + op.drop_table("program_budget_impacts", schema="simulation") + op.drop_table("local_authority_impacts", schema="simulation") + op.drop_table("labor_supply_responses", schema="simulation") + op.drop_table("labor_supply_decile_impacts", schema="simulation") + op.drop_table("intra_decile_impacts", schema="simulation") + op.drop_table("decile_impacts", schema="simulation") + op.drop_table("constituency_impacts", schema="simulation") + op.drop_table("congressional_district_impacts", schema="simulation") + op.drop_table("budget_impacts", schema="simulation") + op.drop_table("poverty_rates", schema="simulation") + op.drop_table("inequality", schema="simulation") + op.drop_table("cliff_impacts", schema="simulation") diff --git a/projects/policyengine-simulation-entry/uv.lock b/projects/policyengine-simulation-entry/uv.lock index 31a2409dd..1dd314d3f 100644 --- a/projects/policyengine-simulation-entry/uv.lock +++ b/projects/policyengine-simulation-entry/uv.lock @@ -970,6 +970,7 @@ name = "policyengine-simulation-persistence" version = "0.1.0" source = { editable = "../../libs/policyengine-simulation-persistence" } dependencies = [ + { name = "policyengine-simulation-contract" }, { name = "psycopg", extra = ["binary"] }, { name = "sqlalchemy" }, ] @@ -978,6 +979,7 @@ dependencies = [ requires-dist = [ { name = "alembic", marker = "extra == 'migrations'", specifier = ">=1.17.1,<2" }, { name = "alembic", marker = "extra == 'test'", specifier = ">=1.17.1,<2" }, + { name = "policyengine-simulation-contract", editable = "../../libs/policyengine-simulation-contract" }, { name = "psycopg", extras = ["binary"], specifier = ">=3.2,<4" }, { name = "pyright", marker = "extra == 'build'", specifier = ">=1.1.401" }, { name = "pytest", marker = "extra == 'test'", specifier = ">=8.3.4" }, From 7f8f6f10a108d2551c904220b720372c7ef02e26 Mon Sep 17 00:00:00 2001 From: Anthony Volk <14987227+anth-volk@users.noreply.github.com> Date: Mon, 26 Oct 2026 16:14:46 +0400 Subject: [PATCH 02/14] Keep each UK area's disclosure tier and 90% intervals Since main took disclosure-controlled UK geography outputs, every published constituency and local-authority record carries disclosure_tier (reported or approximate) and the 90% interval bounds of its two income changes. The UK area tables had no columns for them, so a result passed the checks, lost the five fields on write and was read back with them null, which the contract keeps for results computed before disclosure control. constituency_impacts and local_authority_impacts now hold the five fields (nullable, with a check on the tier), and the writer and reader carry them. The UK national and Scotland samples now give every area a tier (some approximate), interval bounds and a map position; the local-authority sample keeps null fields, as an older result has. Co-Authored-By: Claude Opus 5.5 --- .../README.md | 4 +- .../economy_results.py | 3 + .../result_tables.py | 34 +- .../uk_local_authority_2026.json | 9 +- .../uk_nation_scotland_2026.json | 565 +- .../economy_results/uk_national_2026.json | 8750 +++++++++++++---- .../tests/test_economy_results.py | 37 + .../versions/0004_economy_result_tables.py | 18 + 8 files changed, 7505 insertions(+), 1915 deletions(-) diff --git a/libs/policyengine-simulation-persistence/README.md b/libs/policyengine-simulation-persistence/README.md index 69bf2f3a6..0b82c8e72 100644 --- a/libs/policyengine-simulation-persistence/README.md +++ b/libs/policyengine-simulation-persistence/README.md @@ -82,7 +82,9 @@ the comparison step succeeded (`RunTransitions.complete_comparison`); result model. `read_economy_comparison` rebuilds the result exactly from the rows and from labels the region catalog supplies (`EconomyResultLabels`): the model and data versions of the run's catalog version, and constituency and -local-authority names and map positions by code. +local-authority names and map positions by code. Each UK area's disclosure +tier and the 90% interval bounds of its income changes are stored with its +figures (null for a result computed before disclosure control). ## Ownership rules diff --git a/libs/policyengine-simulation-persistence/src/policyengine_simulation_persistence/economy_results.py b/libs/policyengine-simulation-persistence/src/policyengine_simulation_persistence/economy_results.py index be92198e4..fb4eb23be 100644 --- a/libs/policyengine-simulation-persistence/src/policyengine_simulation_persistence/economy_results.py +++ b/libs/policyengine-simulation-persistence/src/policyengine_simulation_persistence/economy_results.py @@ -32,6 +32,7 @@ from sqlalchemy.dialects.postgresql import insert as postgres_insert from policyengine_simulation_persistence.result_tables import ( + UK_AREA_DISCLOSURE_COLUMNS, budget_impacts, cliff_impacts, congressional_district_impacts, @@ -328,6 +329,7 @@ def _geography_rows( record.relative_household_income_change ), "population": record.population, + **{name: getattr(record, name) for name in UK_AREA_DISCLOSURE_COLUMNS}, } for position, record in enumerate(records.root) ] @@ -604,6 +606,7 @@ def _labelled_geographies( "relative_household_income_change" ], "population": row["population"], + **{name: row[name] for name in UK_AREA_DISCLOSURE_COLUMNS}, } ) return records diff --git a/libs/policyengine-simulation-persistence/src/policyengine_simulation_persistence/result_tables.py b/libs/policyengine-simulation-persistence/src/policyengine_simulation_persistence/result_tables.py index 51385752e..4a7cee744 100644 --- a/libs/policyengine-simulation-persistence/src/policyengine_simulation_persistence/result_tables.py +++ b/libs/policyengine-simulation-persistence/src/policyengine_simulation_persistence/result_tables.py @@ -8,15 +8,18 @@ their order in a ``position`` column, so a reader rebuilds the result exactly. Constituency and local-authority names and map positions are not stored: they -come from the region catalog by code. The model and data versions are pinned +come from the region catalog by code. Each area's disclosure tier and 90% +interval bounds are stored with its figures, null for a result computed before +disclosure control. The model and data versions are pinned by the run's catalog version. The SPM provenance and the list of optional sections a result holds are columns on the report run. """ from __future__ import annotations -from typing import TYPE_CHECKING +from typing import TYPE_CHECKING, get_args +from policyengine_simulation_contract.macro_output import UKGeographyDisclosureTier from sqlalchemy import ( CheckConstraint, Column, @@ -44,6 +47,14 @@ "race": ("white", "black", "hispanic", "other"), } DECILE_MEASURES = ("income", "wealth") +UK_AREA_DISCLOSURE_TIERS: tuple[str, ...] = get_args(UKGeographyDisclosureTier) +UK_AREA_DISCLOSURE_COLUMNS = ( + "disclosure_tier", + "average_household_income_change_lower", + "average_household_income_change_upper", + "relative_household_income_change_lower", + "relative_household_income_change_upper", +) def _values(values: tuple[str, ...]) -> str: @@ -85,6 +96,23 @@ def _position() -> list[SchemaItem]: ] +def _uk_area_disclosure() -> list[SchemaItem]: + """Return a UK area's disclosure tier and its changes' 90% interval bounds. + + All are null for a result computed before disclosure control. + """ + tier_column, *bound_columns = UK_AREA_DISCLOSURE_COLUMNS + return [ + Column(tier_column, Text, nullable=True), + *(Column(name, Double, nullable=True) for name in bound_columns), + CheckConstraint( + f"{tier_column} IS NULL OR " + f"{tier_column} IN ({_values(UK_AREA_DISCLOSURE_TIERS)})", + name=tier_column, + ), + ] + + # --- Per simulation run ----------------------------------------------------- poverty_rates = Table( @@ -255,6 +283,7 @@ def _position() -> list[SchemaItem]: "relative_household_income_change", "population", ), + *_uk_area_disclosure(), PrimaryKeyConstraint("report_run_id", "constituency_code"), UniqueConstraint("report_run_id", "position"), ) @@ -270,6 +299,7 @@ def _position() -> list[SchemaItem]: "relative_household_income_change", "population", ), + *_uk_area_disclosure(), PrimaryKeyConstraint("report_run_id", "local_authority_code"), UniqueConstraint("report_run_id", "position"), ) diff --git a/libs/policyengine-simulation-persistence/tests/fixtures/economy_results/uk_local_authority_2026.json b/libs/policyengine-simulation-persistence/tests/fixtures/economy_results/uk_local_authority_2026.json index 3d309bacd..832f978a9 100644 --- a/libs/policyengine-simulation-persistence/tests/fixtures/economy_results/uk_local_authority_2026.json +++ b/libs/policyengine-simulation-persistence/tests/fixtures/economy_results/uk_local_authority_2026.json @@ -300,10 +300,15 @@ "constituency_impact": null, "local_authority_impact": [ { + "disclosure_tier": null, + "average_household_income_change_lower": null, + "average_household_income_change_upper": null, + "relative_household_income_change_lower": null, + "relative_household_income_change_upper": null, "local_authority_code": "E06000000001", "local_authority_name": "Local Authority 1", - "x": null, - "y": null, + "x": 0, + "y": 0, "average_household_income_change": 23.761655080990707, "relative_household_income_change": 0.45328471316462604, "population": 103153.12548296218 diff --git a/libs/policyengine-simulation-persistence/tests/fixtures/economy_results/uk_nation_scotland_2026.json b/libs/policyengine-simulation-persistence/tests/fixtures/economy_results/uk_nation_scotland_2026.json index f7212bfcd..97e364348 100644 --- a/libs/policyengine-simulation-persistence/tests/fixtures/economy_results/uk_nation_scotland_2026.json +++ b/libs/policyengine-simulation-persistence/tests/fixtures/economy_results/uk_nation_scotland_2026.json @@ -299,15 +299,25 @@ "labor_supply_response": null, "constituency_impact": [ { + "disclosure_tier": "reported", + "average_household_income_change_lower": -29.0, + "average_household_income_change_upper": -15.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "S14000000001", "constituency_name": "Constituency 1", - "x": null, - "y": null, + "x": 0, + "y": 0, "average_household_income_change": -22.0502560822613, "relative_household_income_change": 1e-12, "population": 79332.57320595343 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1030.0, + "average_household_income_change_upper": 1402.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "S14000000002", "constituency_name": "Constituency 2", "x": 1, @@ -317,6 +327,11 @@ "population": 85934.48703372813 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -438.0, + "average_household_income_change_upper": -318.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "S14000000003", "constituency_name": "Constituency 3", "x": 2, @@ -326,6 +341,11 @@ "population": 83465.39782866623 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -2274.0, + "average_household_income_change_upper": -1675.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "S14000000004", "constituency_name": "Constituency 4", "x": 3, @@ -335,6 +355,11 @@ "population": 113477.96855441103 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": -751.0, + "average_household_income_change_upper": -549.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "S14000000005", "constituency_name": "Constituency 5", "x": 4, @@ -344,6 +369,11 @@ "population": 62789.23357183145 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -449.0, + "average_household_income_change_upper": -326.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "S14000000006", "constituency_name": "Constituency 6", "x": 5, @@ -353,6 +383,11 @@ "population": 94065.14389717858 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -838.0, + "average_household_income_change_upper": -614.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "S14000000007", "constituency_name": "Constituency 7", "x": 6, @@ -362,15 +397,25 @@ "population": 128189.16865653818 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 387.0, + "average_household_income_change_upper": 532.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "S14000000008", "constituency_name": "Constituency 8", - "x": null, - "y": null, + "x": 7, + "y": 0, "average_household_income_change": 459.8825949063641, "relative_household_income_change": -0.0, "population": 63046.60303942481 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -2035.0, + "average_household_income_change_upper": -1498.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "S14000000009", "constituency_name": "Constituency 9", "x": 8, @@ -380,6 +425,11 @@ "population": 103944.30710763739 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1909.0, + "average_household_income_change_upper": -1405.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "S14000000010", "constituency_name": "Constituency 10", "x": 9, @@ -389,6 +439,11 @@ "population": 92293.1508555326 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1807.0, + "average_household_income_change_upper": -1330.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "S14000000011", "constituency_name": "Constituency 11", "x": 10, @@ -398,6 +453,11 @@ "population": 89367.41666308911 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1775.0, + "average_household_income_change_upper": -1306.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "S14000000012", "constituency_name": "Constituency 12", "x": 11, @@ -407,6 +467,11 @@ "population": 53137.15027763359 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -61.0, + "average_household_income_change_upper": -39.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "S14000000013", "constituency_name": "Constituency 13", "x": 12, @@ -416,6 +481,11 @@ "population": 69494.2870251734 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": -1974.0, + "average_household_income_change_upper": -1453.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "S14000000014", "constituency_name": "Constituency 14", "x": 13, @@ -425,15 +495,25 @@ "population": 114944.10521441708 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 434.0, + "average_household_income_change_upper": 596.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "S14000000015", "constituency_name": "Constituency 15", - "x": null, - "y": null, + "x": 14, + "y": 0, "average_household_income_change": 515.040158455704, "relative_household_income_change": 1e-12, "population": 123680.0940363324 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 750.0, + "average_household_income_change_upper": 1023.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "S14000000016", "constituency_name": "Constituency 16", "x": 15, @@ -443,6 +523,11 @@ "population": 133563.797744863 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1567.0, + "average_household_income_change_upper": 2129.0, + "relative_household_income_change_lower": 0.8241, + "relative_household_income_change_upper": 1.1161, "constituency_code": "S14000000017", "constituency_name": "Constituency 17", "x": 16, @@ -452,6 +537,11 @@ "population": 96561.24036341548 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -233.0, + "average_household_income_change_upper": -166.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "S14000000018", "constituency_name": "Constituency 18", "x": 17, @@ -461,6 +551,11 @@ "population": 130680.98864876162 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1483.0, + "average_household_income_change_upper": -1090.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "S14000000019", "constituency_name": "Constituency 19", "x": 18, @@ -470,6 +565,11 @@ "population": 73823.59031650981 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1350.0, + "average_household_income_change_upper": -992.0, + "relative_household_income_change_lower": 0.7146, + "relative_household_income_change_upper": 0.9678, "constituency_code": "S14000000020", "constituency_name": "Constituency 20", "x": 19, @@ -479,6 +579,11 @@ "population": 95406.04234472507 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -833.0, + "average_household_income_change_upper": -609.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "S14000000021", "constituency_name": "Constituency 21", "x": 20, @@ -488,15 +593,25 @@ "population": 68215.09086082038 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1531.0, + "average_household_income_change_upper": -1125.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "S14000000022", "constituency_name": "Constituency 22", - "x": null, - "y": null, + "x": 21, + "y": 0, "average_household_income_change": -1327.8413593194002, "relative_household_income_change": 1e-12, "population": 139680.9189915626 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": 1547.0, + "average_household_income_change_upper": 2101.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "S14000000023", "constituency_name": "Constituency 23", "x": 22, @@ -506,6 +621,11 @@ "population": 135075.91381560973 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 494.0, + "average_household_income_change_upper": 677.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "S14000000024", "constituency_name": "Constituency 24", "x": 23, @@ -515,6 +635,11 @@ "population": 62805.9120249973 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -15.0, + "average_household_income_change_upper": -5.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "S14000000025", "constituency_name": "Constituency 25", "x": 24, @@ -524,6 +649,11 @@ "population": 93527.3783158783 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -298.0, + "average_household_income_change_upper": -214.0, + "relative_household_income_change_lower": 0.5463, + "relative_household_income_change_upper": 0.7402, "constituency_code": "S14000000026", "constituency_name": "Constituency 26", "x": 25, @@ -533,6 +663,11 @@ "population": 88101.31906153599 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1444.0, + "average_household_income_change_upper": 1962.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "S14000000027", "constituency_name": "Constituency 27", "x": 26, @@ -542,6 +677,11 @@ "population": 125414.43486372594 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1037.0, + "average_household_income_change_upper": 1412.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "S14000000028", "constituency_name": "Constituency 28", "x": 27, @@ -551,15 +691,25 @@ "population": 125936.64670777883 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -61.0, + "average_household_income_change_upper": -39.0, + "relative_household_income_change_lower": 0.4285, + "relative_household_income_change_upper": 0.5807, "constituency_code": "S14000000029", "constituency_name": "Constituency 29", - "x": null, - "y": null, + "x": 28, + "y": 0, "average_household_income_change": -50.36433936503304, "relative_household_income_change": 0.5045905570059873, "population": 110678.73316985903 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -2059.0, + "average_household_income_change_upper": -1516.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "S14000000030", "constituency_name": "Constituency 30", "x": 29, @@ -569,6 +719,11 @@ "population": 137815.36506324858 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -823.0, + "average_household_income_change_upper": -602.0, + "relative_household_income_change_lower": 0.6915, + "relative_household_income_change_upper": 0.9366, "constituency_code": "S14000000031", "constituency_name": "Constituency 31", "x": 30, @@ -578,235 +733,365 @@ "population": 77978.11324744608 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": 1377.0, + "average_household_income_change_upper": 1871.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "S14000000032", "constituency_name": "Constituency 32", - "x": 0, - "y": 1, + "x": 31, + "y": 0, "average_household_income_change": 1623.627170035723, "relative_household_income_change": -0.0, "population": 106220.79881424447 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1015.0, + "average_household_income_change_upper": -744.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "S14000000033", "constituency_name": "Constituency 33", - "x": 1, - "y": 1, + "x": 32, + "y": 0, "average_household_income_change": -879.6243473802599, "relative_household_income_change": -0.0, "population": 113212.96419666243 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -877.0, + "average_household_income_change_upper": -642.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "S14000000034", "constituency_name": "Constituency 34", - "x": 2, - "y": 1, + "x": 33, + "y": 0, "average_household_income_change": -759.2250650364525, "relative_household_income_change": -0.0, "population": 75244.09885972543 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 275.0, + "average_household_income_change_upper": 381.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "S14000000035", "constituency_name": "Constituency 35", - "x": 3, - "y": 1, + "x": 34, + "y": 0, "average_household_income_change": 328.0589704575538, "relative_household_income_change": -0.0, "population": 100810.42044062808 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 952.0, + "average_household_income_change_upper": 1296.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "S14000000036", "constituency_name": "Constituency 36", - "x": null, - "y": null, + "x": 35, + "y": 0, "average_household_income_change": 1123.594288313716, "relative_household_income_change": 1e-12, "population": 124050.46952325002 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -242.0, + "average_household_income_change_upper": -173.0, + "relative_household_income_change_lower": 0.4808, + "relative_household_income_change_upper": 0.6515, "constituency_code": "S14000000037", "constituency_name": "Constituency 37", - "x": 5, - "y": 1, + "x": 36, + "y": 0, "average_household_income_change": -207.40824634245314, "relative_household_income_change": 0.566121478909492, "population": 86172.31704600062 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 380.0, + "average_household_income_change_upper": 522.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "S14000000038", "constituency_name": "Constituency 38", - "x": 6, - "y": 1, + "x": 37, + "y": 0, "average_household_income_change": 450.9534054524922, "relative_household_income_change": 1e-12, "population": 71202.13598416587 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -584.0, + "average_household_income_change_upper": -426.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "S14000000039", "constituency_name": "Constituency 39", - "x": 7, - "y": 1, + "x": 38, + "y": 0, "average_household_income_change": -505.1320248700919, "relative_household_income_change": -0.0, "population": 78380.02565944156 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 310.0, + "average_household_income_change_upper": 428.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "S14000000040", "constituency_name": "Constituency 40", - "x": 8, - "y": 1, + "x": 39, + "y": 0, "average_household_income_change": 369.07046484015103, "relative_household_income_change": 0.0, "population": 96559.91677812286 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": 1464.0, + "average_household_income_change_upper": 1988.0, + "relative_household_income_change_lower": 0.5417, + "relative_household_income_change_upper": 0.7339, "constituency_code": "S14000000041", "constituency_name": "Constituency 41", - "x": 9, + "x": 0, "y": 1, "average_household_income_change": 1725.916837222794, "relative_household_income_change": 0.6377702114609652, "population": 54537.937931824395 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1127.0, + "average_household_income_change_upper": 1533.0, + "relative_household_income_change_lower": 0.4754, + "relative_household_income_change_upper": 0.6442, "constituency_code": "S14000000042", "constituency_name": "Constituency 42", - "x": 10, + "x": 1, "y": 1, "average_household_income_change": 1330.2517858463264, "relative_household_income_change": 0.5598026330340823, "population": 52934.12546599741 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1498.0, + "average_household_income_change_upper": 2035.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "S14000000043", "constituency_name": "Constituency 43", - "x": null, - "y": null, + "x": 2, + "y": 1, "average_household_income_change": 1766.9186377099031, "relative_household_income_change": 1e-12, "population": 67014.41931048906 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -663.0, + "average_household_income_change_upper": -484.0, + "relative_household_income_change_lower": 0.506, + "relative_household_income_change_upper": 0.6857, "constituency_code": "S14000000044", "constituency_name": "Constituency 44", - "x": 12, + "x": 3, "y": 1, "average_household_income_change": -573.5210003270792, "relative_household_income_change": 0.5958518145639365, "population": 143726.2105377167 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1317.0, + "average_household_income_change_upper": -967.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "S14000000045", "constituency_name": "Constituency 45", - "x": 13, + "x": 4, "y": 1, "average_household_income_change": -1142.3319096547716, "relative_household_income_change": 1e-12, "population": 127568.64904169193 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -2289.0, + "average_household_income_change_upper": -1685.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "S14000000046", "constituency_name": "Constituency 46", - "x": 14, + "x": 5, "y": 1, "average_household_income_change": -1987.0210639986383, "relative_household_income_change": -0.0, "population": 79684.65150836893 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1038.0, + "average_household_income_change_upper": -761.0, + "relative_household_income_change_lower": 0.2846, + "relative_household_income_change_upper": 0.3861, "constituency_code": "S14000000047", "constituency_name": "Constituency 47", - "x": 15, + "x": 6, "y": 1, "average_household_income_change": -899.9641960071924, "relative_household_income_change": 0.33535050184635984, "population": 110975.7867195766 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 34.0, + "average_household_income_change_upper": 54.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "S14000000048", "constituency_name": "Constituency 48", - "x": 16, + "x": 7, "y": 1, "average_household_income_change": 43.803712052223446, "relative_household_income_change": -0.0, "population": 55638.22656504041 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -2140.0, + "average_household_income_change_upper": -1576.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "S14000000049", "constituency_name": "Constituency 49", - "x": 17, + "x": 8, "y": 1, "average_household_income_change": -1858.2148152893594, "relative_household_income_change": -0.0, "population": 61494.55783779679 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": 1521.0, + "average_household_income_change_upper": 2066.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "S14000000050", "constituency_name": "Constituency 50", - "x": null, - "y": null, + "x": 9, + "y": 1, "average_household_income_change": 1793.552834263271, "relative_household_income_change": 1e-12, "population": 71150.5956498904 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 332.0, + "average_household_income_change_upper": 458.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "S14000000051", "constituency_name": "Constituency 51", - "x": 19, + "x": 10, "y": 1, "average_household_income_change": 395.1686018800302, "relative_household_income_change": -3.5e-9, "population": 57577.16533695534 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1470.0, + "average_household_income_change_upper": 1998.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "S14000000052", "constituency_name": "Constituency 52", - "x": 20, + "x": 11, "y": 1, "average_household_income_change": 1734.0747439322786, "relative_household_income_change": 1e-12, "population": 65718.41606608071 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1178.0, + "average_household_income_change_upper": -864.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "S14000000053", "constituency_name": "Constituency 53", - "x": 21, + "x": 12, "y": 1, "average_household_income_change": -1021.0283577089085, "relative_household_income_change": 1e-12, "population": 52738.38868454951 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1013.0, + "average_household_income_change_upper": 1378.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "S14000000054", "constituency_name": "Constituency 54", - "x": 22, + "x": 13, "y": 1, "average_household_income_change": 1195.60033690023, "relative_household_income_change": 0.0, "population": 58687.69580485995 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1066.0, + "average_household_income_change_upper": 1450.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "S14000000055", "constituency_name": "Constituency 55", - "x": 23, + "x": 14, "y": 1, "average_household_income_change": 1258.2528562824318, "relative_household_income_change": 1e-12, "population": 52638.640102357116 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1373.0, + "average_household_income_change_upper": -1009.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "S14000000056", "constituency_name": "Constituency 56", - "x": 24, + "x": 15, "y": 1, "average_household_income_change": -1190.9949809860163, "relative_household_income_change": -3.5e-9, "population": 95505.81052752634 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1821.0, + "average_household_income_change_upper": -1340.0, + "relative_household_income_change_lower": 0.6979, + "relative_household_income_change_upper": 0.9453, "constituency_code": "S14000000057", "constituency_name": "Constituency 57", - "x": null, - "y": null, + "x": 16, + "y": 1, "average_household_income_change": -1580.6126310753368, "relative_household_income_change": 0.8216310930495441, "population": 64646.038428561056 @@ -814,15 +1099,25 @@ ], "local_authority_impact": [ { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1452.0, + "average_household_income_change_upper": 1972.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "S12000000001", "local_authority_name": "Local Authority 1", - "x": null, - "y": null, + "x": 0, + "y": 0, "average_household_income_change": 1711.9662635106972, "relative_household_income_change": -0.0, "population": 139245.28916534188 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -878.0, + "average_household_income_change_upper": -643.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "S12000000002", "local_authority_name": "Local Authority 2", "x": 1, @@ -832,6 +1127,11 @@ "population": 100805.127015022 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1560.0, + "average_household_income_change_upper": -1147.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "S12000000003", "local_authority_name": "Local Authority 3", "x": 2, @@ -841,6 +1141,11 @@ "population": 136496.49703708116 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -2164.0, + "average_household_income_change_upper": -1594.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "S12000000004", "local_authority_name": "Local Authority 4", "x": 3, @@ -850,6 +1155,11 @@ "population": 127529.863915214 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": -727.0, + "average_household_income_change_upper": -531.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "S12000000005", "local_authority_name": "Local Authority 5", "x": 4, @@ -859,6 +1169,11 @@ "population": 119156.76386104178 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 740.0, + "average_household_income_change_upper": 1009.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "S12000000006", "local_authority_name": "Local Authority 6", "x": 5, @@ -868,6 +1183,11 @@ "population": 106277.9233003826 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 394.0, + "average_household_income_change_upper": 542.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "local_authority_code": "S12000000007", "local_authority_name": "Local Authority 7", "x": 6, @@ -877,15 +1197,25 @@ "population": 139741.54468077584 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -637.0, + "average_household_income_change_upper": -465.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "S12000000008", "local_authority_name": "Local Authority 8", - "x": null, - "y": null, + "x": 7, + "y": 0, "average_household_income_change": -550.7700901310177, "relative_household_income_change": 0.0, "population": 80739.55317161283 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -967.0, + "average_household_income_change_upper": -709.0, + "relative_household_income_change_lower": 0.3623, + "relative_household_income_change_upper": 0.4912, "local_authority_code": "S12000000009", "local_authority_name": "Local Authority 9", "x": 8, @@ -895,6 +1225,11 @@ "population": 77962.94927239053 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1508.0, + "average_household_income_change_upper": -1109.0, + "relative_household_income_change_lower": 0.6215, + "relative_household_income_change_upper": 0.8419, "local_authority_code": "S12000000010", "local_authority_name": "Local Authority 10", "x": 9, @@ -904,6 +1239,11 @@ "population": 106985.32281751494 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1384.0, + "average_household_income_change_upper": -1017.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "S12000000011", "local_authority_name": "Local Authority 11", "x": 10, @@ -913,6 +1253,11 @@ "population": 60169.16904360067 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -623.0, + "average_household_income_change_upper": -455.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "local_authority_code": "S12000000012", "local_authority_name": "Local Authority 12", "x": 11, @@ -922,6 +1267,11 @@ "population": 134657.14469719745 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -603.0, + "average_household_income_change_upper": -440.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "S12000000013", "local_authority_name": "Local Authority 13", "x": 12, @@ -931,6 +1281,11 @@ "population": 84326.3910283849 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": -468.0, + "average_household_income_change_upper": -340.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "local_authority_code": "S12000000014", "local_authority_name": "Local Authority 14", "x": 13, @@ -940,15 +1295,25 @@ "population": 90121.64285325728 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -2295.0, + "average_household_income_change_upper": -1690.0, + "relative_household_income_change_lower": 0.4578, + "relative_household_income_change_upper": 0.6204, "local_authority_code": "S12000000015", "local_authority_name": "Local Authority 15", - "x": null, - "y": null, + "x": 14, + "y": 0, "average_household_income_change": -1992.3987578717731, "relative_household_income_change": 0.5390980006995861, "population": 57146.25648990415 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1622.0, + "average_household_income_change_upper": 2203.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "S12000000016", "local_authority_name": "Local Authority 16", "x": 15, @@ -958,6 +1323,11 @@ "population": 61630.540132526454 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 572.0, + "average_household_income_change_upper": 782.0, + "relative_household_income_change_lower": 0.1885, + "relative_household_income_change_upper": 0.2561, "local_authority_code": "S12000000017", "local_authority_name": "Local Authority 17", "x": 16, @@ -967,6 +1337,11 @@ "population": 83264.51133432586 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 622.0, + "average_household_income_change_upper": 850.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "S12000000018", "local_authority_name": "Local Authority 18", "x": 17, @@ -976,6 +1351,11 @@ "population": 60421.1365110476 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1030.0, + "average_household_income_change_upper": -755.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "S12000000019", "local_authority_name": "Local Authority 19", "x": 18, @@ -985,6 +1365,11 @@ "population": 149136.34982537729 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1588.0, + "average_household_income_change_upper": 2156.0, + "relative_household_income_change_lower": 0.7913, + "relative_household_income_change_upper": 1.0717, "local_authority_code": "S12000000020", "local_authority_name": "Local Authority 20", "x": 19, @@ -994,6 +1379,11 @@ "population": 82551.14096226152 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -2045.0, + "average_household_income_change_upper": -1506.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "S12000000021", "local_authority_name": "Local Authority 21", "x": 20, @@ -1003,15 +1393,25 @@ "population": 142543.40081999943 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1422.0, + "average_household_income_change_upper": 1932.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "S12000000022", "local_authority_name": "Local Authority 22", - "x": null, - "y": null, + "x": 21, + "y": 0, "average_household_income_change": 1677.2264729092446, "relative_household_income_change": -3.5e-9, "population": 119213.98806155729 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": 212.0, + "average_household_income_change_upper": 295.0, + "relative_household_income_change_lower": 0.1427, + "relative_household_income_change_upper": 0.1942, "local_authority_code": "S12000000023", "local_authority_name": "Local Authority 23", "x": 22, @@ -1021,6 +1421,11 @@ "population": 131349.02471522414 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -2133.0, + "average_household_income_change_upper": -1570.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "S12000000024", "local_authority_name": "Local Authority 24", "x": 23, @@ -1030,6 +1435,11 @@ "population": 98606.58597465903 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1670.0, + "average_household_income_change_upper": -1228.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "local_authority_code": "S12000000025", "local_authority_name": "Local Authority 25", "x": 24, @@ -1039,6 +1449,11 @@ "population": 57564.83061204634 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1007.0, + "average_household_income_change_upper": -738.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "local_authority_code": "S12000000026", "local_authority_name": "Local Authority 26", "x": 25, @@ -1048,6 +1463,11 @@ "population": 125783.43975305068 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1512.0, + "average_household_income_change_upper": -1112.0, + "relative_household_income_change_lower": 0.8421, + "relative_household_income_change_upper": 1.1404, "local_authority_code": "S12000000027", "local_authority_name": "Local Authority 27", "x": 26, @@ -1057,6 +1477,11 @@ "population": 81237.5561149096 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 486.0, + "average_household_income_change_upper": 666.0, + "relative_household_income_change_lower": 0.5978, + "relative_household_income_change_upper": 0.8099, "local_authority_code": "S12000000028", "local_authority_name": "Local Authority 28", "x": 27, @@ -1066,15 +1491,25 @@ "population": 141107.730757162 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 812.0, + "average_household_income_change_upper": 1106.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "local_authority_code": "S12000000029", "local_authority_name": "Local Authority 29", - "x": null, - "y": null, + "x": 28, + "y": 0, "average_household_income_change": 958.8442127965027, "relative_household_income_change": 1e-12, "population": 102312.94874371101 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1549.0, + "average_household_income_change_upper": -1139.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "S12000000030", "local_authority_name": "Local Authority 30", "x": 29, @@ -1084,6 +1519,11 @@ "population": 103091.15965651689 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -34.0, + "average_household_income_change_upper": -19.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "S12000000031", "local_authority_name": "Local Authority 31", "x": 30, @@ -1093,10 +1533,15 @@ "population": 139125.5993482639 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": 1591.0, + "average_household_income_change_upper": 2160.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "local_authority_code": "S12000000032", "local_authority_name": "Local Authority 32", - "x": 0, - "y": 1, + "x": 31, + "y": 0, "average_household_income_change": 1875.5073255172429, "relative_household_income_change": 1e-12, "population": 52821.895044486846 diff --git a/libs/policyengine-simulation-persistence/tests/fixtures/economy_results/uk_national_2026.json b/libs/policyengine-simulation-persistence/tests/fixtures/economy_results/uk_national_2026.json index 726c2d974..414ea324a 100644 --- a/libs/policyengine-simulation-persistence/tests/fixtures/economy_results/uk_national_2026.json +++ b/libs/policyengine-simulation-persistence/tests/fixtures/economy_results/uk_national_2026.json @@ -369,15 +369,25 @@ }, "constituency_impact": [ { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1623.0, + "average_household_income_change_upper": 2204.0, + "relative_household_income_change_lower": 0.0459, + "relative_household_income_change_upper": 0.0632, "constituency_code": "E14000000001", "constituency_name": "Constituency 1", - "x": null, - "y": null, + "x": 0, + "y": 0, "average_household_income_change": 1913.4194334839867, "relative_household_income_change": 0.05452265501045739, "population": 98386.17433244424 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1498.0, + "average_household_income_change_upper": 2035.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000002", "constituency_name": "Constituency 2", "x": 1, @@ -387,6 +397,11 @@ "population": 65914.779888391 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1679.0, + "average_household_income_change_upper": 2279.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000003", "constituency_name": "Constituency 3", "x": 2, @@ -396,6 +411,11 @@ "population": 146525.5307749652 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -281.0, + "average_household_income_change_upper": -202.0, + "relative_household_income_change_lower": 0.0005, + "relative_household_income_change_upper": 0.0018, "constituency_code": "E14000000004", "constituency_name": "Constituency 4", "x": 3, @@ -405,6 +425,11 @@ "population": 88718.4004768281 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": -2252.0, + "average_household_income_change_upper": -1659.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000005", "constituency_name": "Constituency 5", "x": 4, @@ -414,6 +439,11 @@ "population": 98185.74579851818 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 422.0, + "average_household_income_change_upper": 579.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000006", "constituency_name": "Constituency 6", "x": 5, @@ -423,6 +453,11 @@ "population": 91600.07992596942 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1212.0, + "average_household_income_change_upper": 1648.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000007", "constituency_name": "Constituency 7", "x": 6, @@ -432,15 +467,25 @@ "population": 144767.61377682418 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 254.0, + "average_household_income_change_upper": 352.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000008", "constituency_name": "Constituency 8", - "x": null, - "y": null, + "x": 7, + "y": 0, "average_household_income_change": 303.4651099150256, "relative_household_income_change": 1e-12, "population": 104370.43989569198 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1649.0, + "average_household_income_change_upper": -1213.0, + "relative_household_income_change_lower": 0.4419, + "relative_household_income_change_upper": 0.599, "constituency_code": "E14000000009", "constituency_name": "Constituency 9", "x": 8, @@ -450,6 +495,11 @@ "population": 120355.88560972406 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1015.0, + "average_household_income_change_upper": -744.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000010", "constituency_name": "Constituency 10", "x": 9, @@ -459,6 +509,11 @@ "population": 131238.10258698944 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 529.0, + "average_household_income_change_upper": 724.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000011", "constituency_name": "Constituency 11", "x": 10, @@ -468,6 +523,11 @@ "population": 70186.41755304152 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1364.0, + "average_household_income_change_upper": -1002.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000012", "constituency_name": "Constituency 12", "x": 11, @@ -477,6 +537,11 @@ "population": 95668.57228708114 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1514.0, + "average_household_income_change_upper": -1113.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000013", "constituency_name": "Constituency 13", "x": 12, @@ -486,6 +551,11 @@ "population": 58717.759794404556 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": 441.0, + "average_household_income_change_upper": 605.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000014", "constituency_name": "Constituency 14", "x": 13, @@ -495,15 +565,25 @@ "population": 105485.06719596757 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -329.0, + "average_household_income_change_upper": -237.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000015", "constituency_name": "Constituency 15", - "x": null, - "y": null, + "x": 14, + "y": 0, "average_household_income_change": -283.01292441674696, "relative_household_income_change": -0.0, "population": 64972.126858879885 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1560.0, + "average_household_income_change_upper": 2118.0, + "relative_household_income_change_lower": 0.7247, + "relative_household_income_change_upper": 0.9815, "constituency_code": "E14000000016", "constituency_name": "Constituency 16", "x": 15, @@ -513,6 +593,11 @@ "population": 95302.11433575382 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1533.0, + "average_household_income_change_upper": 2082.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000017", "constituency_name": "Constituency 17", "x": 16, @@ -522,6 +607,11 @@ "population": 102662.03335442903 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1104.0, + "average_household_income_change_upper": 1501.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000018", "constituency_name": "Constituency 18", "x": 17, @@ -531,6 +621,11 @@ "population": 102906.71208383882 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 579.0, + "average_household_income_change_upper": 791.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000019", "constituency_name": "Constituency 19", "x": 18, @@ -540,6 +635,11 @@ "population": 54222.044888242985 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 412.0, + "average_household_income_change_upper": 565.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000020", "constituency_name": "Constituency 20", "x": 19, @@ -549,6 +649,11 @@ "population": 57009.64734391624 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -2104.0, + "average_household_income_change_upper": -1549.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000021", "constituency_name": "Constituency 21", "x": 20, @@ -558,15 +663,25 @@ "population": 60607.39438166653 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 797.0, + "average_household_income_change_upper": 1086.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000022", "constituency_name": "Constituency 22", - "x": null, - "y": null, + "x": 21, + "y": 0, "average_household_income_change": 941.3762870336742, "relative_household_income_change": 0.0, "population": 65082.17476365694 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": -195.0, + "average_household_income_change_upper": -138.0, + "relative_household_income_change_lower": 0.0388, + "relative_household_income_change_upper": 0.0536, "constituency_code": "E14000000023", "constituency_name": "Constituency 23", "x": 22, @@ -576,6 +691,11 @@ "population": 65296.52386416295 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1611.0, + "average_household_income_change_upper": -1185.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000024", "constituency_name": "Constituency 24", "x": 23, @@ -585,6 +705,11 @@ "population": 82358.07690579105 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1345.0, + "average_household_income_change_upper": -988.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000025", "constituency_name": "Constituency 25", "x": 24, @@ -594,6 +719,11 @@ "population": 58056.9265454936 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 935.0, + "average_household_income_change_upper": 1273.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000026", "constituency_name": "Constituency 26", "x": 25, @@ -603,6 +733,11 @@ "population": 138706.63023281284 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1178.0, + "average_household_income_change_upper": 1602.0, + "relative_household_income_change_lower": 0.1629, + "relative_household_income_change_upper": 0.2214, "constituency_code": "E14000000027", "constituency_name": "Constituency 27", "x": 26, @@ -612,6 +747,11 @@ "population": 82600.12292622661 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -636.0, + "average_household_income_change_upper": -464.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000028", "constituency_name": "Constituency 28", "x": 27, @@ -621,15 +761,25 @@ "population": 66882.2129669484 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -436.0, + "average_household_income_change_upper": -316.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000029", "constituency_name": "Constituency 29", - "x": null, - "y": null, + "x": 28, + "y": 0, "average_household_income_change": -376.0757965327994, "relative_household_income_change": -0.0, "population": 131755.4233245176 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -2083.0, + "average_household_income_change_upper": -1533.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000030", "constituency_name": "Constituency 30", "x": 29, @@ -639,6 +789,11 @@ "population": 76098.68374829671 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1001.0, + "average_household_income_change_upper": 1363.0, + "relative_household_income_change_lower": 0.581, + "relative_household_income_change_upper": 0.7872, "constituency_code": "E14000000031", "constituency_name": "Constituency 31", "x": 30, @@ -648,5572 +803,8667 @@ "population": 97597.70307584907 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": -2279.0, + "average_household_income_change_upper": -1678.0, + "relative_household_income_change_lower": 0.824, + "relative_household_income_change_upper": 1.1158, "constituency_code": "E14000000032", "constituency_name": "Constituency 32", - "x": 0, - "y": 1, + "x": 31, + "y": 0, "average_household_income_change": -1978.4430390331474, "relative_household_income_change": 0.9698872181871829, "population": 119385.14894333272 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1070.0, + "average_household_income_change_upper": -785.0, + "relative_household_income_change_lower": 0.5568, + "relative_household_income_change_upper": 0.7544, "constituency_code": "E14000000033", "constituency_name": "Constituency 33", - "x": 1, - "y": 1, + "x": 32, + "y": 0, "average_household_income_change": -927.783221433379, "relative_household_income_change": 0.6556433745742408, "population": 56063.824089337824 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 650.0, + "average_household_income_change_upper": 887.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000034", "constituency_name": "Constituency 34", - "x": 2, - "y": 1, + "x": 33, + "y": 0, "average_household_income_change": 768.3322762327842, "relative_household_income_change": -0.0, "population": 146677.93429020338 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1992.0, + "average_household_income_change_upper": -1467.0, + "relative_household_income_change_lower": 0.6179, + "relative_household_income_change_upper": 0.837, "constituency_code": "E14000000035", "constituency_name": "Constituency 35", - "x": 3, - "y": 1, + "x": 34, + "y": 0, "average_household_income_change": -1729.540058696729, "relative_household_income_change": 0.7274163682705892, "population": 141793.29131328876 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -977.0, + "average_household_income_change_upper": -716.0, + "relative_household_income_change_lower": 0.7206, + "relative_household_income_change_upper": 0.976, "constituency_code": "E14000000036", "constituency_name": "Constituency 36", - "x": null, - "y": null, + "x": 35, + "y": 0, "average_household_income_change": -846.208132023205, "relative_household_income_change": 0.8483280186604456, "population": 67143.97059156044 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -2231.0, + "average_household_income_change_upper": -1643.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000037", "constituency_name": "Constituency 37", - "x": 5, - "y": 1, + "x": 36, + "y": 0, "average_household_income_change": -1936.6401638583116, "relative_household_income_change": -0.0, "population": 61672.55464881558 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -727.0, + "average_household_income_change_upper": -531.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000038", "constituency_name": "Constituency 38", - "x": 6, - "y": 1, + "x": 37, + "y": 0, "average_household_income_change": -628.8145345899005, "relative_household_income_change": 1e-12, "population": 132985.11142986448 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -2048.0, + "average_household_income_change_upper": -1507.0, + "relative_household_income_change_lower": 0.448, + "relative_household_income_change_upper": 0.6072, "constituency_code": "E14000000039", "constituency_name": "Constituency 39", - "x": 7, - "y": 1, + "x": 38, + "y": 0, "average_household_income_change": -1777.3930705516138, "relative_household_income_change": 0.5276137376872608, "population": 127787.70788799871 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1084.0, + "average_household_income_change_upper": -795.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000040", "constituency_name": "Constituency 40", - "x": 8, - "y": 1, + "x": 39, + "y": 0, "average_household_income_change": -939.8753120050504, "relative_household_income_change": 1e-12, "population": 102035.60610842177 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": 1694.0, + "average_household_income_change_upper": 2300.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000041", "constituency_name": "Constituency 41", - "x": 9, + "x": 0, "y": 1, "average_household_income_change": 1996.581447976601, "relative_household_income_change": -3.5e-9, "population": 62516.54815850142 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -2189.0, + "average_household_income_change_upper": -1612.0, + "relative_household_income_change_lower": 0.5008, + "relative_household_income_change_upper": 0.6787, "constituency_code": "E14000000042", "constituency_name": "Constituency 42", - "x": 10, + "x": 1, "y": 1, "average_household_income_change": -1900.8595839448872, "relative_household_income_change": 0.5897475984561965, "population": 68761.98222160083 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -755.0, + "average_household_income_change_upper": -552.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000043", "constituency_name": "Constituency 43", - "x": null, - "y": null, + "x": 2, + "y": 1, "average_household_income_change": -653.4834431595642, "relative_household_income_change": -0.0, "population": 51348.43227638599 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1738.0, + "average_household_income_change_upper": -1279.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000044", "constituency_name": "Constituency 44", - "x": 12, + "x": 3, "y": 1, "average_household_income_change": -1508.6955230422716, "relative_household_income_change": -3.5e-9, "population": 120576.53453498721 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1569.0, + "average_household_income_change_upper": -1154.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000045", "constituency_name": "Constituency 45", - "x": 13, + "x": 4, "y": 1, "average_household_income_change": -1361.5842774754205, "relative_household_income_change": -0.0, "population": 57742.78406589189 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -410.0, + "average_household_income_change_upper": -297.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000046", "constituency_name": "Constituency 46", - "x": 14, + "x": 5, "y": 1, "average_household_income_change": -353.29379038553776, "relative_household_income_change": -3.5e-9, "population": 126551.15106107993 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1927.0, + "average_household_income_change_upper": -1418.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000047", "constituency_name": "Constituency 47", - "x": 15, + "x": 6, "y": 1, "average_household_income_change": -1672.7900598157826, "relative_household_income_change": -3.5e-9, "population": 144378.29471218237 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 642.0, + "average_household_income_change_upper": 876.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000048", "constituency_name": "Constituency 48", - "x": 16, + "x": 7, "y": 1, "average_household_income_change": 758.8777810416283, "relative_household_income_change": -0.0, "population": 115096.92998669462 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1796.0, + "average_household_income_change_upper": -1322.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000049", "constituency_name": "Constituency 49", - "x": 17, + "x": 8, "y": 1, "average_household_income_change": -1559.0227122087886, "relative_household_income_change": 1e-12, "population": 106776.20642347747 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": 668.0, + "average_household_income_change_upper": 912.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000050", "constituency_name": "Constituency 50", - "x": null, - "y": null, + "x": 9, + "y": 1, "average_household_income_change": 789.7011489873229, "relative_household_income_change": 0.0, "population": 127076.9781852224 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 131.0, + "average_household_income_change_upper": 186.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000051", "constituency_name": "Constituency 51", - "x": 19, + "x": 10, "y": 1, "average_household_income_change": 158.31787373201277, "relative_household_income_change": -3.5e-9, "population": 77473.57871872757 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 460.0, + "average_household_income_change_upper": 631.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000052", "constituency_name": "Constituency 52", - "x": 20, + "x": 11, "y": 1, "average_household_income_change": 545.7397560998354, "relative_household_income_change": 1e-12, "population": 123149.70477872998 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -2292.0, + "average_household_income_change_upper": -1688.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000053", "constituency_name": "Constituency 53", - "x": 21, + "x": 12, "y": 1, "average_household_income_change": -1989.6254923025228, "relative_household_income_change": -3.5e-9, "population": 138656.01900310494 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1509.0, + "average_household_income_change_upper": -1109.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000054", "constituency_name": "Constituency 54", - "x": 22, + "x": 13, "y": 1, "average_household_income_change": -1309.1057736433424, "relative_household_income_change": -3.5e-9, "population": 105353.90714704938 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1050.0, + "average_household_income_change_upper": -770.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000055", "constituency_name": "Constituency 55", - "x": 23, + "x": 14, "y": 1, "average_household_income_change": -910.2455237869887, "relative_household_income_change": 1e-12, "population": 92014.34882548383 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -2181.0, + "average_household_income_change_upper": -1606.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000056", "constituency_name": "Constituency 56", - "x": 24, + "x": 15, "y": 1, "average_household_income_change": -1893.3912344738899, "relative_household_income_change": 1e-12, "population": 62745.988954386 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -272.0, + "average_household_income_change_upper": -195.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000057", "constituency_name": "Constituency 57", - "x": null, - "y": null, + "x": 16, + "y": 1, "average_household_income_change": -233.6121744507622, "relative_household_income_change": 0.0, "population": 80531.25807633463 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1461.0, + "average_household_income_change_upper": 1985.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000058", "constituency_name": "Constituency 58", - "x": 26, + "x": 17, "y": 1, "average_household_income_change": 1723.235202484926, "relative_household_income_change": 0.0, "population": 62353.128351459265 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": -1142.0, + "average_household_income_change_upper": -838.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000059", "constituency_name": "Constituency 59", - "x": 27, + "x": 18, "y": 1, "average_household_income_change": -989.7236409560759, "relative_household_income_change": 0.0, "population": 82844.38317215677 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1573.0, + "average_household_income_change_upper": 2136.0, + "relative_household_income_change_lower": 0.8021, + "relative_household_income_change_upper": 1.0863, "constituency_code": "E14000000060", "constituency_name": "Constituency 60", - "x": 28, + "x": 19, "y": 1, "average_household_income_change": 1854.5416655237204, "relative_household_income_change": 0.9442223354304049, "population": 118156.82723049479 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1436.0, + "average_household_income_change_upper": -1055.0, + "relative_household_income_change_lower": 0.093, + "relative_household_income_change_upper": 0.1269, "constituency_code": "E14000000061", "constituency_name": "Constituency 61", - "x": 29, + "x": 20, "y": 1, "average_household_income_change": -1245.781306574102, "relative_household_income_change": 0.10992560517344074, "population": 121532.76585539519 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 377.0, + "average_household_income_change_upper": 518.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000062", "constituency_name": "Constituency 62", - "x": 30, + "x": 21, "y": 1, "average_household_income_change": 447.36217162511946, "relative_household_income_change": -0.0, "population": 90921.07222144597 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1678.0, + "average_household_income_change_upper": 2278.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000063", "constituency_name": "Constituency 63", - "x": 0, - "y": 2, + "x": 22, + "y": 1, "average_household_income_change": 1977.7483196114183, "relative_household_income_change": -0.0, "population": 145071.50512103183 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 708.0, + "average_household_income_change_upper": 966.0, + "relative_household_income_change_lower": 0.3249, + "relative_household_income_change_upper": 0.4406, "constituency_code": "E14000000064", "constituency_name": "Constituency 64", - "x": null, - "y": null, + "x": 23, + "y": 1, "average_household_income_change": 836.8416626768695, "relative_household_income_change": 0.3827069272720205, "population": 80491.97355110932 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -747.0, + "average_household_income_change_upper": -546.0, + "relative_household_income_change_lower": 0.5488, + "relative_household_income_change_upper": 0.7435, "constituency_code": "E14000000065", "constituency_name": "Constituency 65", - "x": 2, - "y": 2, + "x": 24, + "y": 1, "average_household_income_change": -646.4321678071556, "relative_household_income_change": 0.6461356256019504, "population": 82414.78499033627 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -314.0, + "average_household_income_change_upper": -226.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000066", "constituency_name": "Constituency 66", - "x": 3, - "y": 2, + "x": 25, + "y": 1, "average_household_income_change": -269.67895991541104, "relative_household_income_change": 0.0, "population": 107324.65179222659 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -885.0, + "average_household_income_change_upper": -648.0, + "relative_household_income_change_lower": 0.4548, + "relative_household_income_change_upper": 0.6163, "constituency_code": "E14000000067", "constituency_name": "Constituency 67", - "x": 4, - "y": 2, + "x": 26, + "y": 1, "average_household_income_change": -766.5123752502452, "relative_household_income_change": 0.5355509950976918, "population": 121437.09706568257 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": 964.0, + "average_household_income_change_upper": 1312.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000068", "constituency_name": "Constituency 68", - "x": 5, - "y": 2, + "x": 27, + "y": 1, "average_household_income_change": 1137.686580720843, "relative_household_income_change": 1e-12, "population": 105524.95460769659 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1966.0, + "average_household_income_change_upper": -1447.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000069", "constituency_name": "Constituency 69", - "x": 6, - "y": 2, + "x": 28, + "y": 1, "average_household_income_change": -1706.7509137766676, "relative_household_income_change": 1e-12, "population": 89192.43391252482 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 243.0, + "average_household_income_change_upper": 337.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000070", "constituency_name": "Constituency 70", - "x": 7, - "y": 2, + "x": 29, + "y": 1, "average_household_income_change": 290.0010881146389, "relative_household_income_change": 0.0, "population": 105626.728450015 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1200.0, + "average_household_income_change_upper": -881.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000071", "constituency_name": "Constituency 71", - "x": null, - "y": null, + "x": 30, + "y": 1, "average_household_income_change": -1040.696959610678, "relative_household_income_change": -0.0, "population": 113268.62178290357 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -735.0, + "average_household_income_change_upper": -537.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000072", "constituency_name": "Constituency 72", - "x": 9, - "y": 2, + "x": 31, + "y": 1, "average_household_income_change": -635.9903698714575, "relative_household_income_change": 0.0, "population": 56501.415493660155 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -2136.0, + "average_household_income_change_upper": -1573.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000073", "constituency_name": "Constituency 73", - "x": 10, - "y": 2, + "x": 32, + "y": 1, "average_household_income_change": -1854.3994611686637, "relative_household_income_change": -3.5e-9, "population": 102254.43848842036 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -108.0, + "average_household_income_change_upper": -74.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000074", "constituency_name": "Constituency 74", - "x": 11, - "y": 2, + "x": 33, + "y": 1, "average_household_income_change": -90.81831049588996, "relative_household_income_change": -0.0, "population": 80954.3654644868 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -495.0, + "average_household_income_change_upper": -360.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000075", "constituency_name": "Constituency 75", - "x": 12, - "y": 2, + "x": 34, + "y": 1, "average_household_income_change": -427.27767032936634, "relative_household_income_change": -0.0, "population": 108071.93041754297 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -150.0, + "average_household_income_change_upper": -105.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000076", "constituency_name": "Constituency 76", - "x": 13, - "y": 2, + "x": 35, + "y": 1, "average_household_income_change": -127.30625312048672, "relative_household_income_change": 1e-12, "population": 117467.31956453231 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": 1043.0, + "average_household_income_change_upper": 1419.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000077", "constituency_name": "Constituency 77", - "x": 14, - "y": 2, + "x": 36, + "y": 1, "average_household_income_change": 1230.791969781145, "relative_household_income_change": -3.5e-9, "population": 148070.92092286033 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 814.0, + "average_household_income_change_upper": 1109.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000078", "constituency_name": "Constituency 78", - "x": null, - "y": null, + "x": 37, + "y": 1, "average_household_income_change": 961.4866644663272, "relative_household_income_change": 0.0, "population": 102372.13679715489 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 471.0, + "average_household_income_change_upper": 646.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000079", "constituency_name": "Constituency 79", - "x": 16, - "y": 2, + "x": 38, + "y": 1, "average_household_income_change": 558.5324418439463, "relative_household_income_change": 0.0, "population": 80215.38631281923 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1233.0, + "average_household_income_change_upper": 1677.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000080", "constituency_name": "Constituency 80", - "x": 17, - "y": 2, + "x": 39, + "y": 1, "average_household_income_change": 1454.8518394753298, "relative_household_income_change": -3.5e-9, "population": 96129.88324153051 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -2299.0, + "average_household_income_change_upper": -1693.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000081", "constituency_name": "Constituency 81", - "x": 18, + "x": 0, "y": 2, "average_household_income_change": -1995.8700108929918, "relative_household_income_change": -0.0, "population": 117530.89833643334 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -760.0, + "average_household_income_change_upper": -556.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000082", "constituency_name": "Constituency 82", - "x": 19, + "x": 1, "y": 2, "average_household_income_change": -658.2352550207946, "relative_household_income_change": 0.0, "population": 91829.77214309663 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 157.0, + "average_household_income_change_upper": 220.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000083", "constituency_name": "Constituency 83", - "x": 20, + "x": 2, "y": 2, "average_household_income_change": 188.26514420342198, "relative_household_income_change": 1e-12, "population": 66881.29106756164 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 290.0, + "average_household_income_change_upper": 401.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000084", "constituency_name": "Constituency 84", - "x": 21, + "x": 3, "y": 2, "average_household_income_change": 345.8706592634417, "relative_household_income_change": 1e-12, "population": 56080.595832210536 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1928.0, + "average_household_income_change_upper": -1419.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000085", "constituency_name": "Constituency 85", - "x": null, - "y": null, + "x": 4, + "y": 2, "average_household_income_change": -1673.2370069478045, "relative_household_income_change": -3.5e-9, "population": 132596.5586019211 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": -150.0, + "average_household_income_change_upper": -105.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000086", "constituency_name": "Constituency 86", - "x": 23, + "x": 5, "y": 2, "average_household_income_change": -127.34504781316191, "relative_household_income_change": -0.0, "population": 108141.83862604474 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1538.0, + "average_household_income_change_upper": -1130.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000087", "constituency_name": "Constituency 87", - "x": 24, + "x": 6, "y": 2, "average_household_income_change": -1334.0686487199855, "relative_household_income_change": -0.0, "population": 64208.1603564976 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 764.0, + "average_household_income_change_upper": 1042.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000088", "constituency_name": "Constituency 88", - "x": 25, + "x": 7, "y": 2, "average_household_income_change": 902.6394274385958, "relative_household_income_change": 0.0, "population": 96826.50596375517 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -693.0, + "average_household_income_change_upper": -506.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000089", "constituency_name": "Constituency 89", - "x": 26, + "x": 8, "y": 2, "average_household_income_change": -599.3606996628422, "relative_household_income_change": 1e-12, "population": 73495.08876254177 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1472.0, + "average_household_income_change_upper": 2000.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000090", "constituency_name": "Constituency 90", - "x": 27, + "x": 9, "y": 2, "average_household_income_change": 1736.004403868296, "relative_household_income_change": 0.0, "population": 72671.92918410263 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -215.0, + "average_household_income_change_upper": -153.0, + "relative_household_income_change_lower": 0.3719, + "relative_household_income_change_upper": 0.5042, "constituency_code": "E14000000091", "constituency_name": "Constituency 91", - "x": 28, + "x": 10, "y": 2, "average_household_income_change": -183.77106589635696, "relative_household_income_change": 0.43806674434402326, "population": 114528.8279064073 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 633.0, + "average_household_income_change_upper": 864.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000092", "constituency_name": "Constituency 92", - "x": null, - "y": null, + "x": 11, + "y": 2, "average_household_income_change": 748.6525324379664, "relative_household_income_change": -0.0, "population": 115796.32346101322 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 744.0, + "average_household_income_change_upper": 1015.0, + "relative_household_income_change_lower": 0.8336, + "relative_household_income_change_upper": 1.1289, "constituency_code": "E14000000093", "constituency_name": "Constituency 93", - "x": 30, + "x": 12, "y": 2, "average_household_income_change": 879.2492998869496, "relative_household_income_change": 0.9812499439637178, "population": 72504.37458082387 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 72.0, + "average_household_income_change_upper": 106.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000094", "constituency_name": "Constituency 94", - "x": 0, - "y": 3, + "x": 13, + "y": 2, "average_household_income_change": 88.85783739759168, "relative_household_income_change": -0.0, "population": 98878.56897288407 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": 1397.0, + "average_household_income_change_upper": 1898.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000095", "constituency_name": "Constituency 95", - "x": 1, - "y": 3, + "x": 14, + "y": 2, "average_household_income_change": 1647.1065576113149, "relative_household_income_change": 1e-12, "population": 143872.09389896045 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 847.0, + "average_household_income_change_upper": 1154.0, + "relative_household_income_change_lower": 0.2524, + "relative_household_income_change_upper": 0.3426, "constituency_code": "E14000000096", "constituency_name": "Constituency 96", - "x": 2, - "y": 3, + "x": 15, + "y": 2, "average_household_income_change": 1000.4981954112053, "relative_household_income_change": 0.2974922761899098, "population": 95587.75122445801 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 559.0, + "average_household_income_change_upper": 765.0, + "relative_household_income_change_lower": 0.2089, + "relative_household_income_change_upper": 0.2836, "constituency_code": "E14000000097", "constituency_name": "Constituency 97", - "x": 3, - "y": 3, + "x": 16, + "y": 2, "average_household_income_change": 662.0195760611831, "relative_household_income_change": 0.24624440427242644, "population": 74596.90118944892 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1119.0, + "average_household_income_change_upper": -821.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000098", "constituency_name": "Constituency 98", - "x": 4, - "y": 3, + "x": 17, + "y": 2, "average_household_income_change": -969.5701848891072, "relative_household_income_change": -3.5e-9, "population": 119650.20784516653 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1391.0, + "average_household_income_change_upper": 1890.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000099", "constituency_name": "Constituency 99", - "x": null, - "y": null, + "x": 18, + "y": 2, "average_household_income_change": 1640.698557999197, "relative_household_income_change": 1e-12, "population": 65758.83878464595 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -2082.0, + "average_household_income_change_upper": -1533.0, + "relative_household_income_change_lower": 0.1766, + "relative_household_income_change_upper": 0.24, "constituency_code": "E14000000100", "constituency_name": "Constituency 100", - "x": 6, - "y": 3, + "x": 19, + "y": 2, "average_household_income_change": -1807.137308302433, "relative_household_income_change": 0.20830978548035517, "population": 130632.53138420294 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 209.0, + "average_household_income_change_upper": 291.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000101", "constituency_name": "Constituency 101", - "x": 7, - "y": 3, + "x": 20, + "y": 2, "average_household_income_change": 249.5946512422913, "relative_household_income_change": 0.0, "population": 117617.37454965772 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1446.0, + "average_household_income_change_upper": 1964.0, + "relative_household_income_change_lower": 0.0336, + "relative_household_income_change_upper": 0.0465, "constituency_code": "E14000000102", "constituency_name": "Constituency 102", - "x": 8, - "y": 3, + "x": 21, + "y": 2, "average_household_income_change": 1704.7622150184222, "relative_household_income_change": 0.040006378333672155, "population": 91743.07750685193 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1121.0, + "average_household_income_change_upper": 1525.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000103", "constituency_name": "Constituency 103", - "x": 9, - "y": 3, + "x": 22, + "y": 2, "average_household_income_change": 1323.0082082453052, "relative_household_income_change": -0.0, "population": 82625.82863494732 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": -635.0, + "average_household_income_change_upper": -463.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000104", "constituency_name": "Constituency 104", - "x": 10, - "y": 3, + "x": 23, + "y": 2, "average_household_income_change": -548.9345688529448, "relative_household_income_change": 0.0, "population": 106252.55590308961 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1263.0, + "average_household_income_change_upper": 1717.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000105", "constituency_name": "Constituency 105", - "x": 11, - "y": 3, + "x": 24, + "y": 2, "average_household_income_change": 1490.3340145481927, "relative_household_income_change": -0.0, "population": 52780.212642555765 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -131.0, + "average_household_income_change_upper": -91.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000106", "constituency_name": "Constituency 106", - "x": null, - "y": null, + "x": 25, + "y": 2, "average_household_income_change": -110.74050107692868, "relative_household_income_change": -0.0, "population": 132857.81166528582 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 452.0, + "average_household_income_change_upper": 620.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000107", "constituency_name": "Constituency 107", - "x": 13, - "y": 3, + "x": 26, + "y": 2, "average_household_income_change": 535.7247779833637, "relative_household_income_change": 1e-12, "population": 70233.9136272132 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1800.0, + "average_household_income_change_upper": -1324.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000108", "constituency_name": "Constituency 108", - "x": 14, - "y": 3, + "x": 27, + "y": 2, "average_household_income_change": -1562.196706775103, "relative_household_income_change": 1e-12, "population": 57613.888020112136 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -932.0, + "average_household_income_change_upper": -683.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000109", "constituency_name": "Constituency 109", - "x": 15, - "y": 3, + "x": 28, + "y": 2, "average_household_income_change": -807.5046810198771, "relative_household_income_change": 0.0, "population": 59873.63482115029 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 704.0, + "average_household_income_change_upper": 960.0, + "relative_household_income_change_lower": 0.6698, + "relative_household_income_change_upper": 0.9072, "constituency_code": "E14000000110", "constituency_name": "Constituency 110", - "x": 16, - "y": 3, + "x": 29, + "y": 2, "average_household_income_change": 831.9248746300553, "relative_household_income_change": 0.7884886691726886, "population": 118598.10011798801 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1874.0, + "average_household_income_change_upper": -1379.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000111", "constituency_name": "Constituency 111", - "x": 17, - "y": 3, + "x": 30, + "y": 2, "average_household_income_change": -1626.7832810843204, "relative_household_income_change": 1e-12, "population": 119305.13175442934 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1212.0, + "average_household_income_change_upper": 1648.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000112", "constituency_name": "Constituency 112", - "x": 18, - "y": 3, + "x": 31, + "y": 2, "average_household_income_change": 1429.6328025898952, "relative_household_income_change": 1e-12, "population": 102121.6917442946 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": -1550.0, + "average_household_income_change_upper": -1139.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000113", "constituency_name": "Constituency 113", - "x": null, - "y": null, + "x": 32, + "y": 2, "average_household_income_change": -1344.590914850559, "relative_household_income_change": 0.0, "population": 62858.80426314438 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1322.0, + "average_household_income_change_upper": -971.0, + "relative_household_income_change_lower": 0.4957, + "relative_household_income_change_upper": 0.6718, "constituency_code": "E14000000114", "constituency_name": "Constituency 114", - "x": 20, - "y": 3, + "x": 33, + "y": 2, "average_household_income_change": -1146.3259480815013, "relative_household_income_change": 0.5837592442382298, "population": 122906.79170362945 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 761.0, + "average_household_income_change_upper": 1037.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000115", "constituency_name": "Constituency 115", - "x": 21, - "y": 3, + "x": 34, + "y": 2, "average_household_income_change": 898.8663515055783, "relative_household_income_change": 0.0, "population": 99534.98962730182 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1458.0, + "average_household_income_change_upper": 1981.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000116", "constituency_name": "Constituency 116", - "x": 22, - "y": 3, + "x": 35, + "y": 2, "average_household_income_change": 1719.4014329329482, "relative_household_income_change": -3.5e-9, "population": 69591.52802599104 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 475.0, + "average_household_income_change_upper": 650.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000117", "constituency_name": "Constituency 117", - "x": 23, - "y": 3, + "x": 36, + "y": 2, "average_household_income_change": 562.4608552702921, "relative_household_income_change": 0.0, "population": 55842.24291191352 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -2074.0, + "average_household_income_change_upper": -1527.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000118", "constituency_name": "Constituency 118", - "x": 24, - "y": 3, + "x": 37, + "y": 2, "average_household_income_change": -1800.665380166868, "relative_household_income_change": 0.0, "population": 58657.962368604676 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -2095.0, + "average_household_income_change_upper": -1542.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000119", "constituency_name": "Constituency 119", - "x": 25, - "y": 3, + "x": 38, + "y": 2, "average_household_income_change": -1818.6883148220843, "relative_household_income_change": -0.0, "population": 137813.88099731703 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 384.0, + "average_household_income_change_upper": 528.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000120", "constituency_name": "Constituency 120", - "x": null, - "y": null, + "x": 39, + "y": 2, "average_household_income_change": 455.83119363301086, "relative_household_income_change": 1e-12, "population": 57970.009217312014 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1512.0, + "average_household_income_change_upper": 2054.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000121", "constituency_name": "Constituency 121", - "x": 27, + "x": 0, "y": 3, "average_household_income_change": 1782.7850710537834, "relative_household_income_change": 0.0, "population": 143164.58131962447 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": -1524.0, + "average_household_income_change_upper": -1120.0, + "relative_household_income_change_lower": 0.4602, + "relative_household_income_change_upper": 0.6237, "constituency_code": "E14000000122", "constituency_name": "Constituency 122", - "x": 28, + "x": 1, "y": 3, "average_household_income_change": -1321.9039327565874, "relative_household_income_change": 0.541962411948292, "population": 50457.04856292268 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1854.0, + "average_household_income_change_upper": -1364.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000123", "constituency_name": "Constituency 123", - "x": 29, + "x": 2, "y": 3, "average_household_income_change": -1609.0297193715548, "relative_household_income_change": 1e-12, "population": 135630.50062274272 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1267.0, + "average_household_income_change_upper": 1722.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000124", "constituency_name": "Constituency 124", - "x": 30, + "x": 3, "y": 3, "average_household_income_change": 1494.6489038444706, "relative_household_income_change": -0.0, "population": 86499.87244664696 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -237.0, + "average_household_income_change_upper": -169.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000125", "constituency_name": "Constituency 125", - "x": 0, - "y": 4, + "x": 4, + "y": 3, "average_household_income_change": -203.1025816503482, "relative_household_income_change": -3.5e-9, "population": 131450.3581071367 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -2000.0, + "average_household_income_change_upper": -1472.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000126", "constituency_name": "Constituency 126", - "x": 1, - "y": 4, + "x": 5, + "y": 3, "average_household_income_change": -1736.00876747027, "relative_household_income_change": 1e-12, "population": 77714.90708517047 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 619.0, + "average_household_income_change_upper": 846.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000127", "constituency_name": "Constituency 127", - "x": null, - "y": null, + "x": 6, + "y": 3, "average_household_income_change": 732.7271206158956, "relative_household_income_change": 0.0, "population": 62311.51182123555 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 642.0, + "average_household_income_change_upper": 876.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000128", "constituency_name": "Constituency 128", - "x": 3, - "y": 4, + "x": 7, + "y": 3, "average_household_income_change": 759.0741072953095, "relative_household_income_change": 1e-12, "population": 148750.0421308927 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -133.0, + "average_household_income_change_upper": -92.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000129", "constituency_name": "Constituency 129", - "x": 4, - "y": 4, + "x": 8, + "y": 3, "average_household_income_change": -112.66921174672939, "relative_household_income_change": -0.0, "population": 143434.03244226988 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 584.0, + "average_household_income_change_upper": 798.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000130", "constituency_name": "Constituency 130", - "x": 5, - "y": 4, + "x": 9, + "y": 3, "average_household_income_change": 691.029924028856, "relative_household_income_change": 1e-12, "population": 99922.79421022549 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": 1222.0, + "average_household_income_change_upper": 1662.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000131", "constituency_name": "Constituency 131", - "x": 6, - "y": 4, + "x": 10, + "y": 3, "average_household_income_change": 1441.9814618812738, "relative_household_income_change": -3.5e-9, "population": 131523.50923887704 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1649.0, + "average_household_income_change_upper": -1212.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000132", "constituency_name": "Constituency 132", - "x": 7, - "y": 4, + "x": 11, + "y": 3, "average_household_income_change": -1430.5752926829505, "relative_household_income_change": -3.5e-9, "population": 137924.9037228661 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -618.0, + "average_household_income_change_upper": -451.0, + "relative_household_income_change_lower": 0.6396, + "relative_household_income_change_upper": 0.8664, "constituency_code": "E14000000133", "constituency_name": "Constituency 133", - "x": 8, - "y": 4, + "x": 12, + "y": 3, "average_household_income_change": -534.625803263033, "relative_household_income_change": 0.7529910574305773, "population": 148437.97322438212 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 49.0, + "average_household_income_change_upper": 74.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000134", "constituency_name": "Constituency 134", - "x": null, - "y": null, + "x": 13, + "y": 3, "average_household_income_change": 61.61400773596615, "relative_household_income_change": -0.0, "population": 111496.92620513316 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1616.0, + "average_household_income_change_upper": 2195.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000135", "constituency_name": "Constituency 135", - "x": 10, - "y": 4, + "x": 14, + "y": 3, "average_household_income_change": 1905.6857330111927, "relative_household_income_change": -3.5e-9, "population": 138584.5575915625 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1319.0, + "average_household_income_change_upper": -969.0, + "relative_household_income_change_lower": 0.2485, + "relative_household_income_change_upper": 0.3373, "constituency_code": "E14000000136", "constituency_name": "Constituency 136", - "x": 11, - "y": 4, + "x": 15, + "y": 3, "average_household_income_change": -1144.1054423786206, "relative_household_income_change": 0.2928856424926053, "population": 53197.31312326364 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1458.0, + "average_household_income_change_upper": -1072.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000137", "constituency_name": "Constituency 137", - "x": 12, - "y": 4, + "x": 16, + "y": 3, "average_household_income_change": -1265.1713617127114, "relative_household_income_change": -3.5e-9, "population": 86572.81347329413 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -601.0, + "average_household_income_change_upper": -438.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000138", "constituency_name": "Constituency 138", - "x": 13, - "y": 4, + "x": 17, + "y": 3, "average_household_income_change": -519.7588256792973, "relative_household_income_change": 1e-12, "population": 71191.46671555749 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 134.0, + "average_household_income_change_upper": 190.0, + "relative_household_income_change_lower": 0.7526, + "relative_household_income_change_upper": 1.0192, "constituency_code": "E14000000139", "constituency_name": "Constituency 139", - "x": 14, - "y": 4, + "x": 18, + "y": 3, "average_household_income_change": 162.22254008254345, "relative_household_income_change": 0.8858936695673891, "population": 96442.4130437495 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": -282.0, + "average_household_income_change_upper": -203.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000140", "constituency_name": "Constituency 140", - "x": 15, - "y": 4, + "x": 19, + "y": 3, "average_household_income_change": -242.46320601773473, "relative_household_income_change": 0.0, "population": 80110.23234374468 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 690.0, + "average_household_income_change_upper": 942.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000141", "constituency_name": "Constituency 141", - "x": null, - "y": null, + "x": 20, + "y": 3, "average_household_income_change": 816.202709092623, "relative_household_income_change": 1e-12, "population": 73590.60951765552 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -962.0, + "average_household_income_change_upper": -705.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000142", "constituency_name": "Constituency 142", - "x": 17, - "y": 4, + "x": 21, + "y": 3, "average_household_income_change": -833.1977474989549, "relative_household_income_change": 0.0, "population": 61505.33961873027 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 983.0, + "average_household_income_change_upper": 1339.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000143", "constituency_name": "Constituency 143", - "x": 18, - "y": 4, + "x": 22, + "y": 3, "average_household_income_change": 1160.9421061865896, "relative_household_income_change": 0.0, "population": 115466.82296615103 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1047.0, + "average_household_income_change_upper": -767.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000144", "constituency_name": "Constituency 144", - "x": 19, - "y": 4, + "x": 23, + "y": 3, "average_household_income_change": -907.0148122290055, "relative_household_income_change": -0.0, "population": 146736.6126186456 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 27.0, + "average_household_income_change_upper": 44.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000145", "constituency_name": "Constituency 145", - "x": 20, - "y": 4, + "x": 24, + "y": 3, "average_household_income_change": 35.53462916544747, "relative_household_income_change": 0.0, "population": 64441.56694242156 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -147.0, + "average_household_income_change_upper": -102.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000146", "constituency_name": "Constituency 146", - "x": 21, - "y": 4, + "x": 25, + "y": 3, "average_household_income_change": -124.46281500682232, "relative_household_income_change": -0.0, "population": 120349.10959497117 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -995.0, + "average_household_income_change_upper": -729.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000147", "constituency_name": "Constituency 147", - "x": 22, - "y": 4, + "x": 26, + "y": 3, "average_household_income_change": -862.1979283911992, "relative_household_income_change": 1e-12, "population": 75978.88726544433 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 966.0, + "average_household_income_change_upper": 1315.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000148", "constituency_name": "Constituency 148", - "x": null, - "y": null, + "x": 27, + "y": 3, "average_household_income_change": 1140.4649528680948, "relative_household_income_change": 0.0, "population": 54047.383882475355 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": 573.0, + "average_household_income_change_upper": 784.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000149", "constituency_name": "Constituency 149", - "x": 24, - "y": 4, + "x": 28, + "y": 3, "average_household_income_change": 678.6107114798727, "relative_household_income_change": -3.5e-9, "population": 117413.54107700937 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1117.0, + "average_household_income_change_upper": -820.0, + "relative_household_income_change_lower": 0.3213, + "relative_household_income_change_upper": 0.4358, "constituency_code": "E14000000150", "constituency_name": "Constituency 150", - "x": 25, - "y": 4, + "x": 29, + "y": 3, "average_household_income_change": -968.559432686301, "relative_household_income_change": 0.37852725111076435, "population": 115903.15108720168 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1302.0, + "average_household_income_change_upper": -956.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000151", "constituency_name": "Constituency 151", - "x": 26, - "y": 4, + "x": 30, + "y": 3, "average_household_income_change": -1129.3003769282795, "relative_household_income_change": -3.5e-9, "population": 144612.66162939422 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1075.0, + "average_household_income_change_upper": 1463.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000152", "constituency_name": "Constituency 152", - "x": 27, - "y": 4, + "x": 31, + "y": 3, "average_household_income_change": 1269.0375684969467, "relative_household_income_change": -3.5e-9, "population": 103290.76445801418 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -561.0, + "average_household_income_change_upper": -408.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000153", "constituency_name": "Constituency 153", - "x": 28, - "y": 4, + "x": 32, + "y": 3, "average_household_income_change": -484.59589825511887, "relative_household_income_change": 0.0, "population": 78314.43303172 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1724.0, + "average_household_income_change_upper": -1268.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000154", "constituency_name": "Constituency 154", - "x": 29, - "y": 4, + "x": 33, + "y": 3, "average_household_income_change": -1495.7935523863468, "relative_household_income_change": -0.0, "population": 64071.97759800385 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -452.0, + "average_household_income_change_upper": -328.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000155", "constituency_name": "Constituency 155", - "x": null, - "y": null, + "x": 34, + "y": 3, "average_household_income_change": -389.87763296794054, "relative_household_income_change": 0.0, "population": 54102.4304805369 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1393.0, + "average_household_income_change_upper": 1894.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000156", "constituency_name": "Constituency 156", - "x": 0, - "y": 5, + "x": 35, + "y": 3, "average_household_income_change": 1643.525970306858, "relative_household_income_change": 0.0, "population": 114985.93268203211 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 425.0, + "average_household_income_change_upper": 583.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000157", "constituency_name": "Constituency 157", - "x": 1, - "y": 5, + "x": 36, + "y": 3, "average_household_income_change": 504.13911589940864, "relative_household_income_change": 1e-12, "population": 96530.2084560394 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": 1487.0, + "average_household_income_change_upper": 2021.0, + "relative_household_income_change_lower": 0.1464, + "relative_household_income_change_upper": 0.1991, "constituency_code": "E14000000158", "constituency_name": "Constituency 158", - "x": 2, - "y": 5, + "x": 37, + "y": 3, "average_household_income_change": 1753.9239358191967, "relative_household_income_change": 0.17275558712005012, "population": 63841.377140504985 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1907.0, + "average_household_income_change_upper": -1404.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000159", "constituency_name": "Constituency 159", - "x": 3, - "y": 5, + "x": 38, + "y": 3, "average_household_income_change": -1655.610381708632, "relative_household_income_change": 1e-12, "population": 59182.04001348608 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1266.0, + "average_household_income_change_upper": 1721.0, + "relative_household_income_change_lower": 0.0435, + "relative_household_income_change_upper": 0.0599, "constituency_code": "E14000000160", "constituency_name": "Constituency 160", - "x": 4, - "y": 5, + "x": 39, + "y": 3, "average_household_income_change": 1493.1892934146344, "relative_household_income_change": 0.05167241091737229, "population": 134883.8787827266 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1165.0, + "average_household_income_change_upper": -855.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000161", "constituency_name": "Constituency 161", - "x": 5, - "y": 5, + "x": 0, + "y": 4, "average_household_income_change": -1009.785320605499, "relative_household_income_change": -0.0, "population": 105313.0376348572 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1684.0, + "average_household_income_change_upper": 2287.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000162", "constituency_name": "Constituency 162", - "x": null, - "y": null, + "x": 1, + "y": 4, "average_household_income_change": 1985.790511051385, "relative_household_income_change": 0.0, "population": 59046.08239782301 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -721.0, + "average_household_income_change_upper": -527.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000163", "constituency_name": "Constituency 163", - "x": 7, - "y": 5, + "x": 2, + "y": 4, "average_household_income_change": -624.0407357817598, "relative_household_income_change": -3.5e-9, "population": 133938.68480033753 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1406.0, + "average_household_income_change_upper": -1033.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000164", "constituency_name": "Constituency 164", - "x": 8, - "y": 5, + "x": 3, + "y": 4, "average_household_income_change": -1219.380899954297, "relative_household_income_change": -3.5e-9, "population": 140688.8228403655 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 916.0, + "average_household_income_change_upper": 1248.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000165", "constituency_name": "Constituency 165", - "x": 9, - "y": 5, + "x": 4, + "y": 4, "average_household_income_change": 1082.0360022946556, "relative_household_income_change": -0.0, "population": 119206.25377648813 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1077.0, + "average_household_income_change_upper": 1465.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000166", "constituency_name": "Constituency 166", - "x": 10, - "y": 5, + "x": 5, + "y": 4, "average_household_income_change": 1270.7265069357318, "relative_household_income_change": 0.0, "population": 60177.53130640996 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": -203.0, + "average_household_income_change_upper": -144.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000167", "constituency_name": "Constituency 167", - "x": 11, - "y": 5, + "x": 6, + "y": 4, "average_household_income_change": -173.76753307330173, "relative_household_income_change": -3.5e-9, "population": 92609.98355546329 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 68.0, + "average_household_income_change_upper": 101.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000168", "constituency_name": "Constituency 168", - "x": 12, - "y": 5, + "x": 7, + "y": 4, "average_household_income_change": 84.60524462623465, "relative_household_income_change": 0.0, "population": 109246.06859637471 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1039.0, + "average_household_income_change_upper": 1414.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000169", "constituency_name": "Constituency 169", - "x": null, - "y": null, + "x": 8, + "y": 4, "average_household_income_change": 1226.4575806689, "relative_household_income_change": -3.5e-9, "population": 85779.77623277435 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1610.0, + "average_household_income_change_upper": 2186.0, + "relative_household_income_change_lower": 0.3118, + "relative_household_income_change_upper": 0.4229, "constituency_code": "E14000000170", "constituency_name": "Constituency 170", - "x": 14, - "y": 5, + "x": 9, + "y": 4, "average_household_income_change": 1897.8839697841004, "relative_household_income_change": 0.3673733728077122, "population": 134526.85600579536 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -115.0, + "average_household_income_change_upper": -79.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000171", "constituency_name": "Constituency 171", - "x": 15, - "y": 5, + "x": 10, + "y": 4, "average_household_income_change": -96.71162396045486, "relative_household_income_change": -0.0, "population": 135267.77830307873 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1471.0, + "average_household_income_change_upper": 1999.0, + "relative_household_income_change_lower": 0.6378, + "relative_household_income_change_upper": 0.8639, "constituency_code": "E14000000172", "constituency_name": "Constituency 172", - "x": 16, - "y": 5, + "x": 11, + "y": 4, "average_household_income_change": 1734.8446483630125, "relative_household_income_change": 0.7508561605283052, "population": 121288.32325809612 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 946.0, + "average_household_income_change_upper": 1288.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000173", "constituency_name": "Constituency 173", - "x": 17, - "y": 5, + "x": 12, + "y": 4, "average_household_income_change": 1116.8285362297524, "relative_household_income_change": 0.0, "population": 143666.5638784498 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1468.0, + "average_household_income_change_upper": 1994.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000174", "constituency_name": "Constituency 174", - "x": 18, - "y": 5, + "x": 13, + "y": 4, "average_household_income_change": 1731.2154456492808, "relative_household_income_change": -3.5e-9, "population": 124824.5757648796 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1653.0, + "average_household_income_change_upper": 2244.0, + "relative_household_income_change_lower": 0.4227, + "relative_household_income_change_upper": 0.573, "constituency_code": "E14000000175", "constituency_name": "Constituency 175", - "x": 19, - "y": 5, + "x": 14, + "y": 4, "average_household_income_change": 1948.654638465101, "relative_household_income_change": 0.4978536471952415, "population": 131100.4905236806 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": -591.0, + "average_household_income_change_upper": -431.0, + "relative_household_income_change_lower": 0.1106, + "relative_household_income_change_upper": 0.1507, "constituency_code": "E14000000176", "constituency_name": "Constituency 176", - "x": null, - "y": null, + "x": 15, + "y": 4, "average_household_income_change": -511.27124006434775, "relative_household_income_change": 0.13061907743062717, "population": 116551.31582614966 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -2229.0, + "average_household_income_change_upper": -1641.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000177", "constituency_name": "Constituency 177", - "x": 21, - "y": 5, + "x": 16, + "y": 4, "average_household_income_change": -1935.029384051584, "relative_household_income_change": 1e-12, "population": 137063.16851170457 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1051.0, + "average_household_income_change_upper": -771.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000178", "constituency_name": "Constituency 178", - "x": 22, - "y": 5, + "x": 17, + "y": 4, "average_household_income_change": -911.186276780501, "relative_household_income_change": -0.0, "population": 61965.39400983384 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1470.0, + "average_household_income_change_upper": 1997.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000179", "constituency_name": "Constituency 179", - "x": 23, - "y": 5, + "x": 18, + "y": 4, "average_household_income_change": 1733.1720235382163, "relative_household_income_change": 0.0, "population": 142246.5510827012 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1409.0, + "average_household_income_change_upper": 1914.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000180", "constituency_name": "Constituency 180", - "x": 24, - "y": 5, + "x": 19, + "y": 4, "average_household_income_change": 1661.238755153409, "relative_household_income_change": 0.0, "population": 90367.91791250638 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 290.0, + "average_household_income_change_upper": 401.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000181", "constituency_name": "Constituency 181", - "x": 25, - "y": 5, + "x": 20, + "y": 4, "average_household_income_change": 345.2949680294841, "relative_household_income_change": -3.5e-9, "population": 149980.7029767488 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1140.0, + "average_household_income_change_upper": -836.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000182", "constituency_name": "Constituency 182", - "x": 26, - "y": 5, + "x": 21, + "y": 4, "average_household_income_change": -988.0666839819572, "relative_household_income_change": -0.0, "population": 128097.92539036271 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 763.0, + "average_household_income_change_upper": 1041.0, + "relative_household_income_change_lower": 0.0779, + "relative_household_income_change_upper": 0.1065, "constituency_code": "E14000000183", "constituency_name": "Constituency 183", - "x": null, - "y": null, + "x": 22, + "y": 4, "average_household_income_change": 902.1430784366627, "relative_household_income_change": 0.09220506661790073, "population": 85359.46880565214 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1105.0, + "average_household_income_change_upper": -810.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000184", "constituency_name": "Constituency 184", - "x": 28, - "y": 5, + "x": 23, + "y": 4, "average_household_income_change": -957.5128615802955, "relative_household_income_change": 0.0, "population": 57657.65475740139 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": -870.0, + "average_household_income_change_upper": -637.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000185", "constituency_name": "Constituency 185", - "x": 29, - "y": 5, + "x": 24, + "y": 4, "average_household_income_change": -753.5040279733156, "relative_household_income_change": 1e-12, "population": 98478.87085938707 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1403.0, + "average_household_income_change_upper": 1907.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000186", "constituency_name": "Constituency 186", - "x": 30, - "y": 5, + "x": 25, + "y": 4, "average_household_income_change": 1655.0348378318804, "relative_household_income_change": -0.0, "population": 140589.08503782647 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -530.0, + "average_household_income_change_upper": -386.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000187", "constituency_name": "Constituency 187", - "x": 0, - "y": 6, + "x": 26, + "y": 4, "average_household_income_change": -457.6924571642285, "relative_household_income_change": -3.5e-9, "population": 60506.32404568623 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 809.0, + "average_household_income_change_upper": 1102.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000188", "constituency_name": "Constituency 188", - "x": 1, - "y": 6, + "x": 27, + "y": 4, "average_household_income_change": 955.5435083380046, "relative_household_income_change": 0.0, "population": 148637.46753157367 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -952.0, + "average_household_income_change_upper": -697.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000189", "constituency_name": "Constituency 189", - "x": 2, - "y": 6, + "x": 28, + "y": 4, "average_household_income_change": -824.5635557117255, "relative_household_income_change": 0.0, "population": 99782.64274656228 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -619.0, + "average_household_income_change_upper": -451.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000190", "constituency_name": "Constituency 190", - "x": null, - "y": null, + "x": 29, + "y": 4, "average_household_income_change": -534.8346178311823, "relative_household_income_change": 1e-12, "population": 55067.263103974285 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 952.0, + "average_household_income_change_upper": 1297.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000191", "constituency_name": "Constituency 191", - "x": 4, - "y": 6, + "x": 30, + "y": 4, "average_household_income_change": 1124.6850271956769, "relative_household_income_change": -0.0, "population": 135639.43667060742 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1624.0, + "average_household_income_change_upper": 2206.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000192", "constituency_name": "Constituency 192", - "x": 5, - "y": 6, + "x": 31, + "y": 4, "average_household_income_change": 1915.0183852603498, "relative_household_income_change": -0.0, "population": 72513.67422403721 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 395.0, + "average_household_income_change_upper": 542.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000193", "constituency_name": "Constituency 193", - "x": 6, - "y": 6, + "x": 32, + "y": 4, "average_household_income_change": 468.543806087232, "relative_household_income_change": 1e-12, "population": 51295.48380385167 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": -2270.0, + "average_household_income_change_upper": -1672.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000194", "constituency_name": "Constituency 194", - "x": 7, - "y": 6, + "x": 33, + "y": 4, "average_household_income_change": -1970.722745123179, "relative_household_income_change": -3.5e-9, "population": 90662.16267914974 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1307.0, + "average_household_income_change_upper": 1777.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000195", "constituency_name": "Constituency 195", - "x": 8, - "y": 6, + "x": 34, + "y": 4, "average_household_income_change": 1541.7517077241403, "relative_household_income_change": 0.0, "population": 51287.49142035601 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -649.0, + "average_household_income_change_upper": -473.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000196", "constituency_name": "Constituency 196", - "x": 9, - "y": 6, + "x": 35, + "y": 4, "average_household_income_change": -561.0043898564228, "relative_household_income_change": -0.0, "population": 148348.3321363182 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 717.0, + "average_household_income_change_upper": 979.0, + "relative_household_income_change_lower": 0.1024, + "relative_household_income_change_upper": 0.1396, "constituency_code": "E14000000197", "constituency_name": "Constituency 197", - "x": null, - "y": null, + "x": 36, + "y": 4, "average_household_income_change": 847.9949757046952, "relative_household_income_change": 0.12100126791021937, "population": 146252.67973033 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -145.0, + "average_household_income_change_upper": -101.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000198", "constituency_name": "Constituency 198", - "x": 11, - "y": 6, + "x": 37, + "y": 4, "average_household_income_change": -122.91164421650168, "relative_household_income_change": 0.0, "population": 108822.50841263078 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 175.0, + "average_household_income_change_upper": 245.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000199", "constituency_name": "Constituency 199", - "x": 12, - "y": 6, + "x": 38, + "y": 4, "average_household_income_change": 210.35075187056896, "relative_household_income_change": 1e-12, "population": 73060.15474275278 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1164.0, + "average_household_income_change_upper": 1583.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000200", "constituency_name": "Constituency 200", - "x": 13, - "y": 6, + "x": 39, + "y": 4, "average_household_income_change": 1373.2772747493455, "relative_household_income_change": -3.5e-9, "population": 54562.39026607954 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1506.0, + "average_household_income_change_upper": 2046.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000201", "constituency_name": "Constituency 201", - "x": 14, - "y": 6, + "x": 0, + "y": 5, "average_household_income_change": 1775.7579273582728, "relative_household_income_change": -0.0, "population": 68571.93485422268 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 411.0, + "average_household_income_change_upper": 565.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000202", "constituency_name": "Constituency 202", - "x": 15, - "y": 6, + "x": 1, + "y": 5, "average_household_income_change": 487.9521355800094, "relative_household_income_change": 1e-12, "population": 52440.31636393422 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": -1524.0, + "average_household_income_change_upper": -1120.0, + "relative_household_income_change_lower": 0.6772, + "relative_household_income_change_upper": 0.9172, "constituency_code": "E14000000203", "constituency_name": "Constituency 203", - "x": 16, - "y": 6, + "x": 2, + "y": 5, "average_household_income_change": -1322.0472054070465, "relative_household_income_change": 0.7971877766379147, "population": 135070.588467467 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1280.0, + "average_household_income_change_upper": 1740.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000204", "constituency_name": "Constituency 204", - "x": null, - "y": null, + "x": 3, + "y": 5, "average_household_income_change": 1509.8157970664406, "relative_household_income_change": 1e-12, "population": 144410.89387433697 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 692.0, + "average_household_income_change_upper": 944.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000205", "constituency_name": "Constituency 205", - "x": 18, - "y": 6, + "x": 4, + "y": 5, "average_household_income_change": 817.8577390299471, "relative_household_income_change": -0.0, "population": 110217.0617559504 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -601.0, + "average_household_income_change_upper": -438.0, + "relative_household_income_change_lower": 0.1144, + "relative_household_income_change_upper": 0.1558, "constituency_code": "E14000000206", "constituency_name": "Constituency 206", - "x": 19, - "y": 6, + "x": 5, + "y": 5, "average_household_income_change": -519.2624488298457, "relative_household_income_change": 0.13511138675068546, "population": 76651.5628612962 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1251.0, + "average_household_income_change_upper": -919.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000207", "constituency_name": "Constituency 207", - "x": 20, - "y": 6, + "x": 6, + "y": 5, "average_household_income_change": -1085.0536783564949, "relative_household_income_change": -0.0, "population": 60836.20787139632 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 253.0, + "average_household_income_change_upper": 350.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000208", "constituency_name": "Constituency 208", - "x": 21, - "y": 6, + "x": 7, + "y": 5, "average_household_income_change": 301.6568478061923, "relative_household_income_change": 0.0, "population": 87157.94506624367 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1928.0, + "average_household_income_change_upper": -1419.0, + "relative_household_income_change_lower": 0.3539, + "relative_household_income_change_upper": 0.4799, "constituency_code": "E14000000209", "constituency_name": "Constituency 209", - "x": 22, - "y": 6, + "x": 8, + "y": 5, "average_household_income_change": -1673.3597854652503, "relative_household_income_change": 0.4169266309393279, "population": 68426.82588844819 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -99.0, + "average_household_income_change_upper": -67.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000210", "constituency_name": "Constituency 210", - "x": 23, - "y": 6, + "x": 9, + "y": 5, "average_household_income_change": -83.09691011490594, "relative_household_income_change": -0.0, "population": 126920.19674232941 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 199.0, + "average_household_income_change_upper": 277.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000211", "constituency_name": "Constituency 211", - "x": null, - "y": null, + "x": 10, + "y": 5, "average_household_income_change": 237.6712620893251, "relative_household_income_change": 1e-12, "population": 60236.095478765325 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": -1827.0, + "average_household_income_change_upper": -1344.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000212", "constituency_name": "Constituency 212", - "x": 25, - "y": 6, + "x": 11, + "y": 5, "average_household_income_change": -1585.4887263147605, "relative_household_income_change": -0.0, "population": 116481.5354173281 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 41.0, + "average_household_income_change_upper": 64.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000213", "constituency_name": "Constituency 213", - "x": 26, - "y": 6, + "x": 12, + "y": 5, "average_household_income_change": 52.57033563292879, "relative_household_income_change": 0.0, "population": 79714.87039267518 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 116.0, + "average_household_income_change_upper": 165.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000214", "constituency_name": "Constituency 214", - "x": 27, - "y": 6, + "x": 13, + "y": 5, "average_household_income_change": 140.7077209407901, "relative_household_income_change": 1e-12, "population": 132320.27403479567 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1480.0, + "average_household_income_change_upper": -1088.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000215", "constituency_name": "Constituency 215", - "x": 28, - "y": 6, + "x": 14, + "y": 5, "average_household_income_change": -1284.1135147208838, "relative_household_income_change": -3.5e-9, "population": 106469.78321771967 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -2065.0, + "average_household_income_change_upper": -1520.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000216", "constituency_name": "Constituency 216", - "x": 29, - "y": 6, + "x": 15, + "y": 5, "average_household_income_change": -1792.2895026530314, "relative_household_income_change": -0.0, "population": 99990.59878057335 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -905.0, + "average_household_income_change_upper": -663.0, + "relative_household_income_change_lower": 0.2451, + "relative_household_income_change_upper": 0.3327, "constituency_code": "E14000000217", "constituency_name": "Constituency 217", - "x": 30, - "y": 6, + "x": 16, + "y": 5, "average_household_income_change": -783.8278631034128, "relative_household_income_change": 0.28888357094563333, "population": 110733.83910680971 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 542.0, + "average_household_income_change_upper": 742.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000218", "constituency_name": "Constituency 218", - "x": null, - "y": null, + "x": 17, + "y": 5, "average_household_income_change": 642.037289695729, "relative_household_income_change": -0.0, "population": 90348.9414403198 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -2081.0, + "average_household_income_change_upper": -1532.0, + "relative_household_income_change_lower": 0.0706, + "relative_household_income_change_upper": 0.0966, "constituency_code": "E14000000219", "constituency_name": "Constituency 219", - "x": 1, - "y": 7, + "x": 18, + "y": 5, "average_household_income_change": -1806.0966714650708, "relative_household_income_change": 0.08357134950427492, "population": 141405.8939185595 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -611.0, + "average_household_income_change_upper": -445.0, + "relative_household_income_change_lower": 0.4128, + "relative_household_income_change_upper": 0.5595, "constituency_code": "E14000000220", "constituency_name": "Constituency 220", - "x": 2, - "y": 7, + "x": 19, + "y": 5, "average_household_income_change": -528.2119277643891, "relative_household_income_change": 0.4861389513239871, "population": 71685.69023793048 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": 805.0, + "average_household_income_change_upper": 1098.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000221", "constituency_name": "Constituency 221", - "x": 3, - "y": 7, + "x": 20, + "y": 5, "average_household_income_change": 951.5333154614805, "relative_household_income_change": -0.0, "population": 79177.23029313763 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 706.0, + "average_household_income_change_upper": 963.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000222", "constituency_name": "Constituency 222", - "x": 4, - "y": 7, + "x": 21, + "y": 5, "average_household_income_change": 834.3379193338874, "relative_household_income_change": 1e-12, "population": 110931.01259918352 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1403.0, + "average_household_income_change_upper": 1907.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000223", "constituency_name": "Constituency 223", - "x": 5, - "y": 7, + "x": 22, + "y": 5, "average_household_income_change": 1654.9743225435302, "relative_household_income_change": -0.0, "population": 144906.40272194232 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1573.0, + "average_household_income_change_upper": 2137.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000224", "constituency_name": "Constituency 224", - "x": 6, - "y": 7, + "x": 23, + "y": 5, "average_household_income_change": 1855.1096996562494, "relative_household_income_change": -3.5e-9, "population": 66984.07968401432 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 943.0, + "average_household_income_change_upper": 1284.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000225", "constituency_name": "Constituency 225", - "x": null, - "y": null, + "x": 24, + "y": 5, "average_household_income_change": 1113.0857713770702, "relative_household_income_change": -3.5e-9, "population": 60678.66657872668 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -368.0, + "average_household_income_change_upper": -266.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000226", "constituency_name": "Constituency 226", - "x": 8, - "y": 7, + "x": 25, + "y": 5, "average_household_income_change": -317.2806673045674, "relative_household_income_change": 1e-12, "population": 85565.2841368982 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 121.0, + "average_household_income_change_upper": 172.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000227", "constituency_name": "Constituency 227", - "x": 9, - "y": 7, + "x": 26, + "y": 5, "average_household_income_change": 146.19610700532658, "relative_household_income_change": 0.0, "population": 54058.96768105369 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1035.0, + "average_household_income_change_upper": 1408.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000228", "constituency_name": "Constituency 228", - "x": 10, - "y": 7, + "x": 27, + "y": 5, "average_household_income_change": 1221.1828572635995, "relative_household_income_change": -0.0, "population": 72968.59443746644 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -549.0, + "average_household_income_change_upper": -400.0, + "relative_household_income_change_lower": 0.381, + "relative_household_income_change_upper": 0.5166, "constituency_code": "E14000000229", "constituency_name": "Constituency 229", - "x": 11, - "y": 7, + "x": 28, + "y": 5, "average_household_income_change": -474.6414251653745, "relative_household_income_change": 0.44878570088574854, "population": 90285.80408850596 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": -86.0, + "average_household_income_change_upper": -58.0, + "relative_household_income_change_lower": 0.4616, + "relative_household_income_change_upper": 0.6256, "constituency_code": "E14000000230", "constituency_name": "Constituency 230", - "x": 12, - "y": 7, + "x": 29, + "y": 5, "average_household_income_change": -71.76530955441463, "relative_household_income_change": 0.5436024592612985, "population": 141221.01934312264 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -439.0, + "average_household_income_change_upper": -318.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000231", "constituency_name": "Constituency 231", - "x": 13, - "y": 7, + "x": 30, + "y": 5, "average_household_income_change": -378.30934127288975, "relative_household_income_change": -3.5e-9, "population": 116505.42531287429 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 851.0, + "average_household_income_change_upper": 1160.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000232", "constituency_name": "Constituency 232", - "x": null, - "y": null, + "x": 31, + "y": 5, "average_household_income_change": 1005.3928185121252, "relative_household_income_change": -0.0, "population": 75058.25944668779 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1345.0, + "average_household_income_change_upper": 1828.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000233", "constituency_name": "Constituency 233", - "x": 15, - "y": 7, + "x": 32, + "y": 5, "average_household_income_change": 1586.7343046544327, "relative_household_income_change": 1e-12, "population": 67712.64242455097 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1354.0, + "average_household_income_change_upper": -995.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000234", "constituency_name": "Constituency 234", - "x": 16, - "y": 7, + "x": 33, + "y": 5, "average_household_income_change": -1174.252830775441, "relative_household_income_change": -3.5e-9, "population": 63789.03547513046 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 545.0, + "average_household_income_change_upper": 746.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000235", "constituency_name": "Constituency 235", - "x": 17, - "y": 7, + "x": 34, + "y": 5, "average_household_income_change": 645.6604038115912, "relative_household_income_change": 0.0, "population": 122263.69384295912 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -691.0, + "average_household_income_change_upper": -505.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000236", "constituency_name": "Constituency 236", - "x": 18, - "y": 7, + "x": 35, + "y": 5, "average_household_income_change": -597.6576548607908, "relative_household_income_change": -3.5e-9, "population": 98804.04918650471 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 350.0, + "average_household_income_change_upper": 481.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000237", "constituency_name": "Constituency 237", - "x": 19, - "y": 7, + "x": 36, + "y": 5, "average_household_income_change": 415.38377283407124, "relative_household_income_change": 1e-12, "population": 72462.68658428223 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -581.0, + "average_household_income_change_upper": -423.0, + "relative_household_income_change_lower": 0.3381, + "relative_household_income_change_upper": 0.4584, "constituency_code": "E14000000238", "constituency_name": "Constituency 238", - "x": 20, - "y": 7, + "x": 37, + "y": 5, "average_household_income_change": -502.30148175641, "relative_household_income_change": 0.39825500487354804, "population": 75577.16208619578 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": 1681.0, + "average_household_income_change_upper": 2283.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000239", "constituency_name": "Constituency 239", - "x": null, - "y": null, + "x": 38, + "y": 5, "average_household_income_change": 1982.22971422196, "relative_household_income_change": 0.0, "population": 100039.3452447531 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 55.0, + "average_household_income_change_upper": 83.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000240", "constituency_name": "Constituency 240", - "x": 22, - "y": 7, + "x": 39, + "y": 5, "average_household_income_change": 68.96842129588521, "relative_household_income_change": 0.0, "population": 78623.37294752918 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -543.0, + "average_household_income_change_upper": -395.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000241", "constituency_name": "Constituency 241", - "x": 23, - "y": 7, + "x": 0, + "y": 6, "average_household_income_change": -469.3900179759347, "relative_household_income_change": -3.5e-9, "population": 71536.75669369439 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1042.0, + "average_household_income_change_upper": 1418.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000242", "constituency_name": "Constituency 242", - "x": 24, - "y": 7, + "x": 1, + "y": 6, "average_household_income_change": 1230.3207047092353, "relative_household_income_change": -3.5e-9, "population": 63353.07779126578 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -2222.0, + "average_household_income_change_upper": -1636.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000243", "constituency_name": "Constituency 243", - "x": 25, - "y": 7, + "x": 2, + "y": 6, "average_household_income_change": -1928.9219199088845, "relative_household_income_change": -3.5e-9, "population": 62849.86261697499 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 940.0, + "average_household_income_change_upper": 1280.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000244", "constituency_name": "Constituency 244", - "x": 26, - "y": 7, + "x": 3, + "y": 6, "average_household_income_change": 1110.3372470128168, "relative_household_income_change": -0.0, "population": 76727.3810569975 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1155.0, + "average_household_income_change_upper": 1571.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000245", "constituency_name": "Constituency 245", - "x": 27, - "y": 7, + "x": 4, + "y": 6, "average_household_income_change": 1362.7103896145973, "relative_household_income_change": -0.0, "population": 124325.70785994509 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -316.0, + "average_household_income_change_upper": -227.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000246", "constituency_name": "Constituency 246", - "x": null, - "y": null, + "x": 5, + "y": 6, "average_household_income_change": -271.49022713741465, "relative_household_income_change": 1e-12, "population": 99799.46872015242 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1304.0, + "average_household_income_change_upper": 1772.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000247", "constituency_name": "Constituency 247", - "x": 29, - "y": 7, + "x": 6, + "y": 6, "average_household_income_change": 1537.7903349770033, "relative_household_income_change": -3.5e-9, "population": 123746.60837519364 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": -1255.0, + "average_household_income_change_upper": -921.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000248", "constituency_name": "Constituency 248", - "x": 30, - "y": 7, + "x": 7, + "y": 6, "average_household_income_change": -1087.8785006624473, "relative_household_income_change": 1e-12, "population": 97600.39659601363 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1551.0, + "average_household_income_change_upper": -1140.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000249", "constituency_name": "Constituency 249", - "x": 0, - "y": 8, + "x": 8, + "y": 6, "average_household_income_change": -1345.7662153813862, "relative_household_income_change": 0.0, "population": 114313.09710587711 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1406.0, + "average_household_income_change_upper": 1911.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000250", "constituency_name": "Constituency 250", - "x": 1, - "y": 8, + "x": 9, + "y": 6, "average_household_income_change": 1658.6777073773708, "relative_household_income_change": -0.0, "population": 94609.60109811788 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -601.0, + "average_household_income_change_upper": -438.0, + "relative_household_income_change_lower": 0.0445, + "relative_household_income_change_upper": 0.0613, "constituency_code": "E14000000251", "constituency_name": "Constituency 251", - "x": 2, - "y": 8, + "x": 10, + "y": 6, "average_household_income_change": -519.6173843357359, "relative_household_income_change": 0.05288350383949525, "population": 101879.58740965034 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 49.0, + "average_household_income_change_upper": 74.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000252", "constituency_name": "Constituency 252", - "x": 3, - "y": 8, + "x": 11, + "y": 6, "average_household_income_change": 61.39724136454517, "relative_household_income_change": 0.0, "population": 122016.25936999946 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 167.0, + "average_household_income_change_upper": 234.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000253", "constituency_name": "Constituency 253", - "x": null, - "y": null, + "x": 12, + "y": 6, "average_household_income_change": 200.79508742853758, "relative_household_income_change": 1e-12, "population": 112382.16718067882 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 55.0, + "average_household_income_change_upper": 82.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000254", "constituency_name": "Constituency 254", - "x": 5, - "y": 8, + "x": 13, + "y": 6, "average_household_income_change": 68.46081134368464, "relative_household_income_change": 1e-12, "population": 79034.69952823792 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1211.0, + "average_household_income_change_upper": -889.0, + "relative_household_income_change_lower": 0.0578, + "relative_household_income_change_upper": 0.0793, "constituency_code": "E14000000255", "constituency_name": "Constituency 255", - "x": 6, - "y": 8, + "x": 14, + "y": 6, "average_household_income_change": -1049.8419544678975, "relative_household_income_change": 0.0685689670992683, "population": 84627.21548030981 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1596.0, + "average_household_income_change_upper": 2167.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000256", "constituency_name": "Constituency 256", - "x": 7, - "y": 8, + "x": 15, + "y": 6, "average_household_income_change": 1881.2593648861452, "relative_household_income_change": -3.5e-9, "population": 135723.15777362182 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": -349.0, + "average_household_income_change_upper": -252.0, + "relative_household_income_change_lower": 0.3284, + "relative_household_income_change_upper": 0.4453, "constituency_code": "E14000000257", "constituency_name": "Constituency 257", - "x": 8, - "y": 8, + "x": 16, + "y": 6, "average_household_income_change": -300.59480412605757, "relative_household_income_change": 0.38686768114256065, "population": 140550.79135966688 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -348.0, + "average_household_income_change_upper": -251.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000258", "constituency_name": "Constituency 258", - "x": 9, - "y": 8, + "x": 17, + "y": 6, "average_household_income_change": -299.27228807240124, "relative_household_income_change": -3.5e-9, "population": 136940.02453417546 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -2268.0, + "average_household_income_change_upper": -1670.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000259", "constituency_name": "Constituency 259", - "x": 10, - "y": 8, + "x": 18, + "y": 6, "average_household_income_change": -1968.8831338393782, "relative_household_income_change": 1e-12, "population": 116862.35781095125 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -2232.0, + "average_household_income_change_upper": -1643.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000260", "constituency_name": "Constituency 260", - "x": null, - "y": null, + "x": 19, + "y": 6, "average_household_income_change": -1937.396708083625, "relative_household_income_change": -0.0, "population": 53050.95960456516 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 233.0, + "average_household_income_change_upper": 324.0, + "relative_household_income_change_lower": 0.695, + "relative_household_income_change_upper": 0.9414, "constituency_code": "E14000000261", "constituency_name": "Constituency 261", - "x": 12, - "y": 8, + "x": 20, + "y": 6, "average_household_income_change": 278.54418344988784, "relative_household_income_change": 0.8182049447786189, "population": 145996.30964651122 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -2009.0, + "average_household_income_change_upper": -1479.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000262", "constituency_name": "Constituency 262", - "x": 13, - "y": 8, + "x": 21, + "y": 6, "average_household_income_change": -1743.60096454641, "relative_household_income_change": -3.5e-9, "population": 137665.3909221181 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 345.0, + "average_household_income_change_upper": 475.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000263", "constituency_name": "Constituency 263", - "x": 14, - "y": 8, + "x": 22, + "y": 6, "average_household_income_change": 410.3648552033592, "relative_household_income_change": 0.0, "population": 130733.25893769521 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1005.0, + "average_household_income_change_upper": -737.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000264", "constituency_name": "Constituency 264", - "x": 15, - "y": 8, + "x": 23, + "y": 6, "average_household_income_change": -870.6543863626357, "relative_household_income_change": 0.0, "population": 130659.0095046039 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 968.0, + "average_household_income_change_upper": 1318.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000265", "constituency_name": "Constituency 265", - "x": 16, - "y": 8, + "x": 24, + "y": 6, "average_household_income_change": 1143.162831284736, "relative_household_income_change": 0.0, "population": 107575.18022024026 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": -1220.0, + "average_household_income_change_upper": -896.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000266", "constituency_name": "Constituency 266", - "x": 17, - "y": 8, + "x": 25, + "y": 6, "average_household_income_change": -1057.9486970304836, "relative_household_income_change": -0.0, "population": 91442.6613340457 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1538.0, + "average_household_income_change_upper": 2090.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000267", "constituency_name": "Constituency 267", - "x": null, - "y": null, + "x": 26, + "y": 6, "average_household_income_change": 1814.0649747416485, "relative_household_income_change": 1e-12, "population": 65130.079693553234 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1748.0, + "average_household_income_change_upper": -1286.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000268", "constituency_name": "Constituency 268", - "x": 19, - "y": 8, + "x": 27, + "y": 6, "average_household_income_change": -1516.7977290124063, "relative_household_income_change": -0.0, "population": 55364.656447213056 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -342.0, + "average_household_income_change_upper": -247.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000269", "constituency_name": "Constituency 269", - "x": 20, - "y": 8, + "x": 28, + "y": 6, "average_household_income_change": -294.20877227662066, "relative_household_income_change": -0.0, "population": 61555.40574473531 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 588.0, + "average_household_income_change_upper": 803.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000270", - "constituency_name": "Constituency 270", - "x": 21, - "y": 8, + "constituency_name": "Constituency 270", + "x": 29, + "y": 6, "average_household_income_change": 695.5018348863717, "relative_household_income_change": -0.0, "population": 68812.25148927994 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -407.0, + "average_household_income_change_upper": -295.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000271", "constituency_name": "Constituency 271", - "x": 22, - "y": 8, + "x": 30, + "y": 6, "average_household_income_change": -351.1802166259006, "relative_household_income_change": -0.0, "population": 54027.65899145163 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1892.0, + "average_household_income_change_upper": -1392.0, + "relative_household_income_change_lower": 0.7118, + "relative_household_income_change_upper": 0.9641, "constituency_code": "E14000000272", "constituency_name": "Constituency 272", - "x": 23, - "y": 8, + "x": 31, + "y": 6, "average_household_income_change": -1642.2915725524824, "relative_household_income_change": 0.8379817398377877, "population": 88079.14001836749 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -229.0, + "average_household_income_change_upper": -163.0, + "relative_household_income_change_lower": 0.5259, + "relative_household_income_change_upper": 0.7125, "constituency_code": "E14000000273", "constituency_name": "Constituency 273", - "x": 24, - "y": 8, + "x": 32, + "y": 6, "average_household_income_change": -196.16611907612392, "relative_household_income_change": 0.6191859545022685, "population": 143901.09379379006 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1350.0, + "average_household_income_change_upper": 1835.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000274", "constituency_name": "Constituency 274", - "x": null, - "y": null, + "x": 33, + "y": 6, "average_household_income_change": 1592.5511593747626, "relative_household_income_change": 1e-12, "population": 56538.644750654064 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": 1059.0, + "average_household_income_change_upper": 1441.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000275", "constituency_name": "Constituency 275", - "x": 26, - "y": 8, + "x": 34, + "y": 6, "average_household_income_change": 1249.8308107022656, "relative_household_income_change": 0.0, "population": 82852.1573553915 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1935.0, + "average_household_income_change_upper": -1424.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000276", "constituency_name": "Constituency 276", - "x": 27, - "y": 8, + "x": 35, + "y": 6, "average_household_income_change": -1679.6035271853639, "relative_household_income_change": 1e-12, "population": 82624.31099995461 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 916.0, + "average_household_income_change_upper": 1247.0, + "relative_household_income_change_lower": 0.6047, + "relative_household_income_change_upper": 0.8192, "constituency_code": "E14000000277", "constituency_name": "Constituency 277", - "x": 28, - "y": 8, + "x": 36, + "y": 6, "average_household_income_change": 1081.625804541158, "relative_household_income_change": 0.7119632280929965, "population": 56373.70772158275 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1745.0, + "average_household_income_change_upper": -1283.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000278", "constituency_name": "Constituency 278", - "x": 29, - "y": 8, + "x": 37, + "y": 6, "average_household_income_change": -1514.008414001978, "relative_household_income_change": -3.5e-9, "population": 54038.13587168238 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1015.0, + "average_household_income_change_upper": -744.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000279", "constituency_name": "Constituency 279", - "x": 30, - "y": 8, + "x": 38, + "y": 6, "average_household_income_change": -879.656036805668, "relative_household_income_change": 0.0, "population": 66920.7276918206 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1653.0, + "average_household_income_change_upper": -1216.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000280", "constituency_name": "Constituency 280", - "x": 0, - "y": 9, + "x": 39, + "y": 6, "average_household_income_change": -1434.2729900398488, "relative_household_income_change": -3.5e-9, "population": 114525.67044788442 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 64.0, + "average_household_income_change_upper": 94.0, + "relative_household_income_change_lower": 0.7725, + "relative_household_income_change_upper": 1.0462, "constituency_code": "E14000000281", "constituency_name": "Constituency 281", - "x": null, - "y": null, + "x": 0, + "y": 7, "average_household_income_change": 78.84229063710268, "relative_household_income_change": 0.9093867952915566, "population": 71203.42519173468 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 7.0, + "average_household_income_change_upper": 18.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000282", "constituency_name": "Constituency 282", - "x": 2, - "y": 9, + "x": 1, + "y": 7, "average_household_income_change": 12.239268357744137, "relative_household_income_change": -0.0, "population": 57133.2670657449 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1015.0, + "average_household_income_change_upper": -744.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000283", "constituency_name": "Constituency 283", - "x": 3, - "y": 9, + "x": 2, + "y": 7, "average_household_income_change": -879.1966266472486, "relative_household_income_change": -3.5e-9, "population": 117950.37248663565 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": 618.0, + "average_household_income_change_upper": 845.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000284", "constituency_name": "Constituency 284", - "x": 4, - "y": 9, + "x": 3, + "y": 7, "average_household_income_change": 731.6369198544824, "relative_household_income_change": 0.0, "population": 60677.670160915164 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 455.0, + "average_household_income_change_upper": 623.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000285", "constituency_name": "Constituency 285", - "x": 5, - "y": 9, + "x": 4, + "y": 7, "average_household_income_change": 538.8786664582988, "relative_household_income_change": 0.0, "population": 134931.71481241478 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -422.0, + "average_household_income_change_upper": -306.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000286", "constituency_name": "Constituency 286", - "x": 6, - "y": 9, + "x": 5, + "y": 7, "average_household_income_change": -363.61423705336284, "relative_household_income_change": -3.5e-9, "population": 59397.05353299759 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -51.0, + "average_household_income_change_upper": -32.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000287", "constituency_name": "Constituency 287", - "x": 7, - "y": 9, + "x": 6, + "y": 7, "average_household_income_change": -41.56094887664574, "relative_household_income_change": -0.0, "population": 101221.93183884669 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1890.0, + "average_household_income_change_upper": -1391.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000288", "constituency_name": "Constituency 288", - "x": null, - "y": null, + "x": 7, + "y": 7, "average_household_income_change": -1640.8394237733885, "relative_household_income_change": -0.0, "population": 85331.20565330614 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1363.0, + "average_household_income_change_upper": 1852.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000289", "constituency_name": "Constituency 289", - "x": 9, - "y": 9, + "x": 8, + "y": 7, "average_household_income_change": 1607.6675640232882, "relative_household_income_change": 0.0, "population": 54725.222443885046 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1663.0, + "average_household_income_change_upper": -1223.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000290", "constituency_name": "Constituency 290", - "x": 10, - "y": 9, + "x": 9, + "y": 7, "average_household_income_change": -1442.7349429318213, "relative_household_income_change": 1e-12, "population": 119504.45090787341 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1497.0, + "average_household_income_change_upper": -1100.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000291", "constituency_name": "Constituency 291", - "x": 11, - "y": 9, + "x": 10, + "y": 7, "average_household_income_change": -1298.611495104644, "relative_household_income_change": -0.0, "population": 124055.42495705158 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -422.0, + "average_household_income_change_upper": -306.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000292", "constituency_name": "Constituency 292", - "x": 12, - "y": 9, + "x": 11, + "y": 7, "average_household_income_change": -363.63670045492836, "relative_household_income_change": -0.0, "population": 80797.82277151337 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": 763.0, + "average_household_income_change_upper": 1041.0, + "relative_household_income_change_lower": 0.5075, + "relative_household_income_change_upper": 0.6876, "constituency_code": "E14000000293", "constituency_name": "Constituency 293", - "x": 13, - "y": 9, + "x": 12, + "y": 7, "average_household_income_change": 902.118169666097, "relative_household_income_change": 0.5975509379823232, "population": 129073.02446683323 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -164.0, + "average_household_income_change_upper": -115.0, + "relative_household_income_change_lower": 0.0527, + "relative_household_income_change_upper": 0.0724, "constituency_code": "E14000000294", "constituency_name": "Constituency 294", - "x": 14, - "y": 9, + "x": 13, + "y": 7, "average_household_income_change": -139.25701863002172, "relative_household_income_change": 0.06255641858639482, "population": 57752.53085066069 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1341.0, + "average_household_income_change_upper": -985.0, + "relative_household_income_change_lower": 0.7445, + "relative_household_income_change_upper": 1.0083, "constituency_code": "E14000000295", "constituency_name": "Constituency 295", - "x": null, - "y": null, + "x": 14, + "y": 7, "average_household_income_change": -1163.432231007708, "relative_household_income_change": 0.8764210555336815, "population": 106333.06119563997 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1935.0, + "average_household_income_change_upper": -1424.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000296", "constituency_name": "Constituency 296", - "x": 16, - "y": 9, + "x": 15, + "y": 7, "average_household_income_change": -1679.9787950530365, "relative_household_income_change": 1e-12, "population": 75692.39275484561 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1342.0, + "average_household_income_change_upper": 1824.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000297", "constituency_name": "Constituency 297", - "x": 17, - "y": 9, + "x": 16, + "y": 7, "average_household_income_change": 1582.697326893069, "relative_household_income_change": 0.0, "population": 117975.52461036804 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -166.0, + "average_household_income_change_upper": -117.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000298", "constituency_name": "Constituency 298", - "x": 18, - "y": 9, + "x": 17, + "y": 7, "average_household_income_change": -141.68662686740774, "relative_household_income_change": 0.0, "population": 147122.08267887653 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 208.0, + "average_household_income_change_upper": 289.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000299", "constituency_name": "Constituency 299", - "x": 19, - "y": 9, + "x": 18, + "y": 7, "average_household_income_change": 248.44524455147445, "relative_household_income_change": 0.0, "population": 57914.21355725573 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1654.0, + "average_household_income_change_upper": -1216.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000300", "constituency_name": "Constituency 300", - "x": 20, - "y": 9, + "x": 19, + "y": 7, "average_household_income_change": -1435.1194306235277, "relative_household_income_change": 1e-12, "population": 89667.12520548898 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 926.0, + "average_household_income_change_upper": 1261.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000301", "constituency_name": "Constituency 301", - "x": 21, - "y": 9, + "x": 20, + "y": 7, "average_household_income_change": 1093.4980272431533, "relative_household_income_change": 0.0, "population": 149640.69785386953 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": 42.0, + "average_household_income_change_upper": 65.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000302", "constituency_name": "Constituency 302", - "x": null, - "y": null, + "x": 21, + "y": 7, "average_household_income_change": 53.08937001870451, "relative_household_income_change": -0.0, "population": 66230.07359490372 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -546.0, + "average_household_income_change_upper": -398.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000303", "constituency_name": "Constituency 303", - "x": 23, - "y": 9, + "x": 22, + "y": 7, "average_household_income_change": -471.8832314261454, "relative_household_income_change": -3.5e-9, "population": 57337.41263366653 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1183.0, + "average_household_income_change_upper": -869.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000304", "constituency_name": "Constituency 304", - "x": 24, - "y": 9, + "x": 23, + "y": 7, "average_household_income_change": -1026.020840673814, "relative_household_income_change": 1e-12, "population": 142490.88938975122 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 514.0, + "average_household_income_change_upper": 704.0, + "relative_household_income_change_lower": 0.544, + "relative_household_income_change_upper": 0.737, "constituency_code": "E14000000305", "constituency_name": "Constituency 305", - "x": 25, - "y": 9, + "x": 24, + "y": 7, "average_household_income_change": 608.8165690306914, "relative_household_income_change": 0.6404988087018922, "population": 72487.89624498294 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -137.0, + "average_household_income_change_upper": -95.0, + "relative_household_income_change_lower": 0.3317, + "relative_household_income_change_upper": 0.4499, "constituency_code": "E14000000306", "constituency_name": "Constituency 306", - "x": 26, - "y": 9, + "x": 25, + "y": 7, "average_household_income_change": -115.80972292330483, "relative_household_income_change": 0.39081883301841813, "population": 77350.48896896599 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1833.0, + "average_household_income_change_upper": -1349.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000307", "constituency_name": "Constituency 307", - "x": 27, - "y": 9, + "x": 26, + "y": 7, "average_household_income_change": -1591.2097568655606, "relative_household_income_change": -0.0, "population": 130601.76627288382 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -237.0, + "average_household_income_change_upper": -169.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000308", "constituency_name": "Constituency 308", - "x": 28, - "y": 9, + "x": 27, + "y": 7, "average_household_income_change": -202.68597089062146, "relative_household_income_change": -3.5e-9, "population": 127803.58575356533 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1962.0, + "average_household_income_change_upper": -1444.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000309", "constituency_name": "Constituency 309", - "x": null, - "y": null, + "x": 28, + "y": 7, "average_household_income_change": -1703.293029455986, "relative_household_income_change": 0.0, "population": 96967.75627127332 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -960.0, + "average_household_income_change_upper": -703.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000310", "constituency_name": "Constituency 310", - "x": 30, - "y": 9, + "x": 29, + "y": 7, "average_household_income_change": -831.6689332469039, "relative_household_income_change": -3.5e-9, "population": 115309.39370340896 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": 1586.0, + "average_household_income_change_upper": 2154.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000311", "constituency_name": "Constituency 311", - "x": 0, - "y": 10, + "x": 30, + "y": 7, "average_household_income_change": 1870.4055118959807, "relative_household_income_change": 0.0, "population": 83882.90139684646 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 414.0, + "average_household_income_change_upper": 569.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000312", "constituency_name": "Constituency 312", - "x": 1, - "y": 10, + "x": 31, + "y": 7, "average_household_income_change": 491.49040529432983, "relative_household_income_change": -0.0, "population": 80790.58693080283 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 316.0, + "average_household_income_change_upper": 435.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000313", "constituency_name": "Constituency 313", - "x": 2, - "y": 10, + "x": 32, + "y": 7, "average_household_income_change": 375.3827408162542, "relative_household_income_change": 1e-12, "population": 84326.10208188766 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 25.0, + "average_household_income_change_upper": 41.0, + "relative_household_income_change_lower": 0.4593, + "relative_household_income_change_upper": 0.6225, "constituency_code": "E14000000314", "constituency_name": "Constituency 314", - "x": 3, - "y": 10, + "x": 33, + "y": 7, "average_household_income_change": 33.000174958145664, "relative_household_income_change": 0.5409158451119593, "population": 133101.32286826705 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1543.0, + "average_household_income_change_upper": -1134.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000315", "constituency_name": "Constituency 315", - "x": 4, - "y": 10, + "x": 34, + "y": 7, "average_household_income_change": -1338.6782648550195, "relative_household_income_change": 1e-12, "population": 135673.8907982766 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -746.0, + "average_household_income_change_upper": -545.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000316", "constituency_name": "Constituency 316", - "x": null, - "y": null, + "x": 35, + "y": 7, "average_household_income_change": -645.4749752199311, "relative_household_income_change": 0.0, "population": 53154.68071281595 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 740.0, + "average_household_income_change_upper": 1010.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000317", "constituency_name": "Constituency 317", - "x": 6, - "y": 10, + "x": 36, + "y": 7, "average_household_income_change": 875.2196826351822, "relative_household_income_change": -0.0, "population": 54663.23250214491 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -2196.0, + "average_household_income_change_upper": -1617.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000318", "constituency_name": "Constituency 318", - "x": 7, - "y": 10, + "x": 37, + "y": 7, "average_household_income_change": -1906.3685553236708, "relative_household_income_change": -0.0, "population": 62216.10372183205 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 222.0, + "average_household_income_change_upper": 309.0, + "relative_household_income_change_lower": 0.0599, + "relative_household_income_change_upper": 0.0821, "constituency_code": "E14000000319", "constituency_name": "Constituency 319", - "x": 8, - "y": 10, + "x": 38, + "y": 7, "average_household_income_change": 265.67730367256326, "relative_household_income_change": 0.07095713112290669, "population": 123272.98162748596 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": 810.0, + "average_household_income_change_upper": 1105.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000320", "constituency_name": "Constituency 320", - "x": 9, - "y": 10, + "x": 39, + "y": 7, "average_household_income_change": 957.6221647457519, "relative_household_income_change": -3.5e-9, "population": 117320.59667338144 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 755.0, + "average_household_income_change_upper": 1030.0, + "relative_household_income_change_lower": 0.0127, + "relative_household_income_change_upper": 0.0182, "constituency_code": "E14000000321", "constituency_name": "Constituency 321", - "x": 10, - "y": 10, + "x": 0, + "y": 8, "average_household_income_change": 892.5971352867052, "relative_household_income_change": 0.01547062226303364, "population": 64382.017243272196 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -106.0, + "average_household_income_change_upper": -73.0, + "relative_household_income_change_lower": 0.5448, + "relative_household_income_change_upper": 0.7382, "constituency_code": "E14000000322", "constituency_name": "Constituency 322", - "x": 11, - "y": 10, + "x": 1, + "y": 8, "average_household_income_change": -89.5120196189252, "relative_household_income_change": 0.6415075542058354, "population": 125144.8692163065 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1536.0, + "average_household_income_change_upper": 2086.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000323", "constituency_name": "Constituency 323", - "x": null, - "y": null, + "x": 2, + "y": 8, "average_household_income_change": 1811.2694791851518, "relative_household_income_change": -3.5e-9, "population": 65712.70150761414 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1269.0, + "average_household_income_change_upper": -932.0, + "relative_household_income_change_lower": 0.3553, + "relative_household_income_change_upper": 0.4817, "constituency_code": "E14000000324", "constituency_name": "Constituency 324", - "x": 13, - "y": 10, + "x": 3, + "y": 8, "average_household_income_change": -1100.7471361008027, "relative_household_income_change": 0.4185108779894693, "population": 114836.3220960143 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1294.0, + "average_household_income_change_upper": -951.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000325", "constituency_name": "Constituency 325", - "x": 14, - "y": 10, + "x": 4, + "y": 8, "average_household_income_change": -1122.6043621770434, "relative_household_income_change": 1e-12, "population": 55237.5686532306 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1593.0, + "average_household_income_change_upper": -1172.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000326", "constituency_name": "Constituency 326", - "x": 15, - "y": 10, + "x": 5, + "y": 8, "average_household_income_change": -1382.4413984731443, "relative_household_income_change": -0.0, "population": 94786.54853619754 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -722.0, + "average_household_income_change_upper": -528.0, + "relative_household_income_change_lower": 0.6869, + "relative_household_income_change_upper": 0.9304, "constituency_code": "E14000000327", "constituency_name": "Constituency 327", - "x": 16, - "y": 10, + "x": 6, + "y": 8, "average_household_income_change": -624.9672122114114, "relative_household_income_change": 0.8086293754051761, "population": 91180.08167511584 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1766.0, + "average_household_income_change_upper": -1299.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000328", "constituency_name": "Constituency 328", - "x": 17, - "y": 10, + "x": 7, + "y": 8, "average_household_income_change": -1532.5080712305694, "relative_household_income_change": 1e-12, "population": 74992.84884821136 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": 1065.0, + "average_household_income_change_upper": 1449.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000329", "constituency_name": "Constituency 329", - "x": 18, - "y": 10, + "x": 8, + "y": 8, "average_household_income_change": 1256.8611941470808, "relative_household_income_change": -0.0, "population": 73264.68467329515 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1238.0, + "average_household_income_change_upper": 1683.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000330", "constituency_name": "Constituency 330", - "x": null, - "y": null, + "x": 9, + "y": 8, "average_household_income_change": 1460.216582001018, "relative_household_income_change": -0.0, "population": 120762.21259691025 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 958.0, + "average_household_income_change_upper": 1304.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000331", "constituency_name": "Constituency 331", - "x": 20, - "y": 10, + "x": 10, + "y": 8, "average_household_income_change": 1131.1627205329526, "relative_household_income_change": -3.5e-9, "population": 124414.09849910664 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1096.0, + "average_household_income_change_upper": -804.0, + "relative_household_income_change_lower": 0.2551, + "relative_household_income_change_upper": 0.3462, "constituency_code": "E14000000332", "constituency_name": "Constituency 332", - "x": 21, - "y": 10, + "x": 11, + "y": 8, "average_household_income_change": -950.333632645132, "relative_household_income_change": 0.30068912666377334, "population": 102386.62156113084 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -765.0, + "average_household_income_change_upper": -559.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000333", "constituency_name": "Constituency 333", - "x": 22, - "y": 10, + "x": 12, + "y": 8, "average_household_income_change": -662.1771673166976, "relative_household_income_change": -3.5e-9, "population": 99217.79434560373 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -360.0, + "average_household_income_change_upper": -260.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000334", "constituency_name": "Constituency 334", - "x": 23, - "y": 10, + "x": 13, + "y": 8, "average_household_income_change": -310.1144178009183, "relative_household_income_change": 0.0, "population": 82642.85198374328 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -117.0, + "average_household_income_change_upper": -80.0, + "relative_household_income_change_lower": 0.2093, + "relative_household_income_change_upper": 0.2843, "constituency_code": "E14000000335", "constituency_name": "Constituency 335", - "x": 24, - "y": 10, + "x": 14, + "y": 8, "average_household_income_change": -98.61823883872577, "relative_household_income_change": 0.24680610402164405, "population": 101928.52381666923 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1527.0, + "average_household_income_change_upper": 2074.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000336", "constituency_name": "Constituency 336", - "x": 25, - "y": 10, + "x": 15, + "y": 8, "average_household_income_change": 1800.075825253157, "relative_household_income_change": 0.0, "population": 106604.47201418565 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1182.0, + "average_household_income_change_upper": -867.0, + "relative_household_income_change_lower": 0.4486, + "relative_household_income_change_upper": 0.608, "constituency_code": "E14000000337", "constituency_name": "Constituency 337", - "x": null, - "y": null, + "x": 16, + "y": 8, "average_household_income_change": -1024.5596852965332, "relative_household_income_change": 0.5282743216274547, "population": 84831.59483429573 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": -1797.0, + "average_household_income_change_upper": -1322.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000338", "constituency_name": "Constituency 338", - "x": 27, - "y": 10, + "x": 17, + "y": 8, "average_household_income_change": -1559.9200409332993, "relative_household_income_change": 0.0, "population": 132190.56010856107 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -374.0, + "average_household_income_change_upper": -271.0, + "relative_household_income_change_lower": 0.1911, + "relative_household_income_change_upper": 0.2595, "constituency_code": "E14000000339", "constituency_name": "Constituency 339", - "x": 28, - "y": 10, + "x": 18, + "y": 8, "average_household_income_change": -322.5458070710423, "relative_household_income_change": 0.22529688748048748, "population": 106479.0884301016 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 826.0, + "average_household_income_change_upper": 1126.0, + "relative_household_income_change_lower": 0.784, + "relative_household_income_change_upper": 1.0617, "constituency_code": "E14000000340", "constituency_name": "Constituency 340", - "x": 29, - "y": 10, + "x": 19, + "y": 8, "average_household_income_change": 975.9731193891134, "relative_household_income_change": 0.9228591687698418, "population": 147412.05136602212 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1036.0, + "average_household_income_change_upper": 1410.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000341", "constituency_name": "Constituency 341", - "x": 30, - "y": 10, + "x": 20, + "y": 8, "average_household_income_change": 1222.6290457869818, "relative_household_income_change": 0.0, "population": 144225.48837876614 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -365.0, + "average_household_income_change_upper": -264.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000342", "constituency_name": "Constituency 342", - "x": 0, - "y": 11, + "x": 21, + "y": 8, "average_household_income_change": -314.19552200388875, "relative_household_income_change": 1e-12, "population": 111129.0169869452 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1134.0, + "average_household_income_change_upper": 1542.0, + "relative_household_income_change_lower": 0.515, + "relative_household_income_change_upper": 0.6979, "constituency_code": "E14000000343", "constituency_name": "Constituency 343", - "x": 1, - "y": 11, + "x": 22, + "y": 8, "average_household_income_change": 1337.6914447481315, "relative_household_income_change": 0.6064418096250256, "population": 72777.5551270252 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -579.0, + "average_household_income_change_upper": -422.0, + "relative_household_income_change_lower": 0.0211, + "relative_household_income_change_upper": 0.0297, "constituency_code": "E14000000344", "constituency_name": "Constituency 344", - "x": null, - "y": null, + "x": 23, + "y": 8, "average_household_income_change": -500.28648215289894, "relative_household_income_change": 0.02539666980792299, "population": 140300.06720143737 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1038.0, + "average_household_income_change_upper": -761.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000345", "constituency_name": "Constituency 345", - "x": 3, - "y": 11, + "x": 24, + "y": 8, "average_household_income_change": -899.8299632125404, "relative_household_income_change": -3.5e-9, "population": 118550.12291309344 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -952.0, + "average_household_income_change_upper": -697.0, + "relative_household_income_change_lower": 0.0479, + "relative_household_income_change_upper": 0.0659, "constituency_code": "E14000000346", "constituency_name": "Constituency 346", - "x": 4, - "y": 11, + "x": 25, + "y": 8, "average_household_income_change": -824.48101449791, "relative_household_income_change": 0.05691560918933902, "population": 84746.18474953297 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": 1153.0, + "average_household_income_change_upper": 1568.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000347", "constituency_name": "Constituency 347", - "x": 5, - "y": 11, + "x": 26, + "y": 8, "average_household_income_change": 1360.4905042331795, "relative_household_income_change": 1e-12, "population": 115209.82974713409 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1505.0, + "average_household_income_change_upper": 2045.0, + "relative_household_income_change_lower": 0.0974, + "relative_household_income_change_upper": 0.1329, "constituency_code": "E14000000348", "constituency_name": "Constituency 348", - "x": 6, - "y": 11, + "x": 27, + "y": 8, "average_household_income_change": 1775.1536699727137, "relative_household_income_change": 0.11514487999565826, "population": 80112.3937259131 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1448.0, + "average_household_income_change_upper": 1967.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000349", "constituency_name": "Constituency 349", - "x": 7, - "y": 11, + "x": 28, + "y": 8, "average_household_income_change": 1707.8194320756604, "relative_household_income_change": 1e-12, "population": 76833.07357783025 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1271.0, + "average_household_income_change_upper": 1728.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000350", "constituency_name": "Constituency 350", - "x": 8, - "y": 11, + "x": 29, + "y": 8, "average_household_income_change": 1499.4873663114822, "relative_household_income_change": 1e-12, "population": 102963.34481014374 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -976.0, + "average_household_income_change_upper": -715.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000351", "constituency_name": "Constituency 351", - "x": null, - "y": null, + "x": 30, + "y": 8, "average_household_income_change": -845.488142728954, "relative_household_income_change": 0.0, "population": 77060.88122496438 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 758.0, + "average_household_income_change_upper": 1034.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000352", "constituency_name": "Constituency 352", - "x": 10, - "y": 11, + "x": 31, + "y": 8, "average_household_income_change": 895.7933970570076, "relative_household_income_change": 1e-12, "population": 121186.05852623229 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 367.0, + "average_household_income_change_upper": 505.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000353", "constituency_name": "Constituency 353", - "x": 11, - "y": 11, + "x": 32, + "y": 8, "average_household_income_change": 436.30185633340534, "relative_household_income_change": -3.5e-9, "population": 90359.39372869075 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1299.0, + "average_household_income_change_upper": 1765.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000354", "constituency_name": "Constituency 354", - "x": 12, - "y": 11, + "x": 33, + "y": 8, "average_household_income_change": 1531.899304402959, "relative_household_income_change": -3.5e-9, "population": 125773.89335858136 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1612.0, + "average_household_income_change_upper": 2189.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000355", "constituency_name": "Constituency 355", - "x": 13, - "y": 11, + "x": 34, + "y": 8, "average_household_income_change": 1900.3636110963519, "relative_household_income_change": -3.5e-9, "population": 86402.77703380983 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": 839.0, + "average_household_income_change_upper": 1143.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000356", "constituency_name": "Constituency 356", - "x": 14, - "y": 11, + "x": 35, + "y": 8, "average_household_income_change": 990.6809907292611, "relative_household_income_change": 1e-12, "population": 133926.5278974796 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -122.0, + "average_household_income_change_upper": -84.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000357", "constituency_name": "Constituency 357", - "x": 15, - "y": 11, + "x": 36, + "y": 8, "average_household_income_change": -102.81392002473177, "relative_household_income_change": 1e-12, "population": 91672.73914310064 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1198.0, + "average_household_income_change_upper": 1629.0, + "relative_household_income_change_lower": 0.1002, + "relative_household_income_change_upper": 0.1366, "constituency_code": "E14000000358", "constituency_name": "Constituency 358", - "x": null, - "y": null, + "x": 37, + "y": 8, "average_household_income_change": 1413.2362731585495, "relative_household_income_change": 0.11842765300769598, "population": 131869.28448096052 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1759.0, + "average_household_income_change_upper": -1294.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000359", "constituency_name": "Constituency 359", - "x": 17, - "y": 11, + "x": 38, + "y": 8, "average_household_income_change": -1526.3658607536765, "relative_household_income_change": 1e-12, "population": 76359.1774732786 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1191.0, + "average_household_income_change_upper": -874.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000360", "constituency_name": "Constituency 360", - "x": 18, - "y": 11, + "x": 39, + "y": 8, "average_household_income_change": -1032.2988351211718, "relative_household_income_change": -3.5e-9, "population": 81960.88765276896 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 767.0, + "average_household_income_change_upper": 1046.0, + "relative_household_income_change_lower": 0.4261, + "relative_household_income_change_upper": 0.5775, "constituency_code": "E14000000361", "constituency_name": "Constituency 361", - "x": 19, - "y": 11, + "x": 0, + "y": 9, "average_household_income_change": 906.6356976421935, "relative_household_income_change": 0.5017789670349119, "population": 57719.93054066484 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1925.0, + "average_household_income_change_upper": -1417.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000362", "constituency_name": "Constituency 362", - "x": 20, - "y": 11, + "x": 1, + "y": 9, "average_household_income_change": -1671.2986473147962, "relative_household_income_change": -0.0, "population": 113415.38429893683 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 91.0, + "average_household_income_change_upper": 131.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000363", "constituency_name": "Constituency 363", - "x": 21, - "y": 11, + "x": 2, + "y": 9, "average_household_income_change": 111.27087975723614, "relative_household_income_change": 0.0, "population": 68079.6212173605 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -903.0, + "average_household_income_change_upper": -661.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000364", "constituency_name": "Constituency 364", - "x": 22, - "y": 11, + "x": 3, + "y": 9, "average_household_income_change": -781.90725602331, "relative_household_income_change": -0.0, "population": 67864.18906912404 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": 256.0, + "average_household_income_change_upper": 354.0, + "relative_household_income_change_lower": 0.3957, + "relative_household_income_change_upper": 0.5365, "constituency_code": "E14000000365", "constituency_name": "Constituency 365", - "x": null, - "y": null, + "x": 4, + "y": 9, "average_household_income_change": 305.0824783887256, "relative_household_income_change": 0.4660933581476817, "population": 61334.79792201664 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 612.0, + "average_household_income_change_upper": 837.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000366", "constituency_name": "Constituency 366", - "x": 24, - "y": 11, + "x": 5, + "y": 9, "average_household_income_change": 724.4525151520427, "relative_household_income_change": 1e-12, "population": 106024.91759136216 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1961.0, + "average_household_income_change_upper": -1444.0, + "relative_household_income_change_lower": 0.0935, + "relative_household_income_change_upper": 0.1276, "constituency_code": "E14000000367", "constituency_name": "Constituency 367", - "x": 25, - "y": 11, + "x": 6, + "y": 9, "average_household_income_change": -1702.5549476447566, "relative_household_income_change": 0.11056314456087024, "population": 81926.19788223934 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -2225.0, + "average_household_income_change_upper": -1638.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000368", "constituency_name": "Constituency 368", - "x": 26, - "y": 11, + "x": 7, + "y": 9, "average_household_income_change": -1931.3909280413527, "relative_household_income_change": 1e-12, "population": 71770.85701884079 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 670.0, + "average_household_income_change_upper": 914.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000369", "constituency_name": "Constituency 369", - "x": 27, - "y": 11, + "x": 8, + "y": 9, "average_household_income_change": 792.0308313732289, "relative_household_income_change": 1e-12, "population": 50440.10731257584 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 359.0, + "average_household_income_change_upper": 493.0, + "relative_household_income_change_lower": 0.601, + "relative_household_income_change_upper": 0.8142, "constituency_code": "E14000000370", "constituency_name": "Constituency 370", - "x": 28, - "y": 11, + "x": 9, + "y": 9, "average_household_income_change": 425.9231978760969, "relative_household_income_change": 0.7075709754638798, "population": 112090.1619356483 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -2090.0, + "average_household_income_change_upper": -1539.0, + "relative_household_income_change_lower": 0.6873, + "relative_household_income_change_upper": 0.931, "constituency_code": "E14000000371", "constituency_name": "Constituency 371", - "x": 29, - "y": 11, + "x": 10, + "y": 9, "average_household_income_change": -1814.3519191458379, "relative_household_income_change": 0.8091499706226665, "population": 52356.510651433506 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 939.0, + "average_household_income_change_upper": 1279.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000372", "constituency_name": "Constituency 372", - "x": null, - "y": null, + "x": 11, + "y": 9, "average_household_income_change": 1109.08621756159, "relative_household_income_change": -0.0, "population": 83600.63778977693 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 13.0, + "average_household_income_change_upper": 26.0, + "relative_household_income_change_lower": 0.437, + "relative_household_income_change_upper": 0.5923, "constituency_code": "E14000000373", "constituency_name": "Constituency 373", - "x": 0, - "y": 12, + "x": 12, + "y": 9, "average_household_income_change": 19.22110165496216, "relative_household_income_change": 0.5146548251212197, "population": 66507.908891974 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": -866.0, + "average_household_income_change_upper": -634.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000374", "constituency_name": "Constituency 374", - "x": 1, - "y": 12, + "x": 13, + "y": 9, "average_household_income_change": -749.5772000344579, "relative_household_income_change": -3.5e-9, "population": 146792.99486028682 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -905.0, + "average_household_income_change_upper": -663.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000375", "constituency_name": "Constituency 375", - "x": 2, - "y": 12, + "x": 14, + "y": 9, "average_household_income_change": -783.8395562619974, "relative_household_income_change": 1e-12, "population": 65422.167957346835 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1671.0, + "average_household_income_change_upper": -1229.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000376", "constituency_name": "Constituency 376", - "x": 3, - "y": 12, + "x": 15, + "y": 9, "average_household_income_change": -1450.1221650989824, "relative_household_income_change": 0.0, "population": 85866.87293099564 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -746.0, + "average_household_income_change_upper": -545.0, + "relative_household_income_change_lower": 0.4225, + "relative_household_income_change_upper": 0.5727, "constituency_code": "E14000000377", "constituency_name": "Constituency 377", - "x": 4, - "y": 12, + "x": 16, + "y": 9, "average_household_income_change": -645.798670669981, "relative_household_income_change": 0.4976229122040582, "population": 122889.59326278509 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1386.0, + "average_household_income_change_upper": 1884.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000378", "constituency_name": "Constituency 378", - "x": 5, - "y": 12, + "x": 17, + "y": 9, "average_household_income_change": 1635.1724174774276, "relative_household_income_change": 0.0, "population": 140388.28343393683 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1525.0, + "average_household_income_change_upper": -1121.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000379", "constituency_name": "Constituency 379", - "x": null, - "y": null, + "x": 18, + "y": 9, "average_household_income_change": -1322.91414940455, "relative_household_income_change": 1e-12, "population": 130180.15071380371 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 544.0, + "average_household_income_change_upper": 744.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000380", "constituency_name": "Constituency 380", - "x": 7, - "y": 12, + "x": 19, + "y": 9, "average_household_income_change": 643.6955982549462, "relative_household_income_change": 1e-12, "population": 141937.50754987824 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -2045.0, + "average_household_income_change_upper": -1505.0, + "relative_household_income_change_lower": 0.3687, + "relative_household_income_change_upper": 0.4999, "constituency_code": "E14000000381", "constituency_name": "Constituency 381", - "x": 8, - "y": 12, + "x": 20, + "y": 9, "average_household_income_change": -1775.2096638418507, "relative_household_income_change": 0.43429070796214286, "population": 145004.63125557202 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1488.0, + "average_household_income_change_upper": 2021.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000382", "constituency_name": "Constituency 382", - "x": 9, - "y": 12, + "x": 21, + "y": 9, "average_household_income_change": 1754.3529428875963, "relative_household_income_change": 1e-12, "population": 82461.35902260432 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": 961.0, + "average_household_income_change_upper": 1308.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000383", "constituency_name": "Constituency 383", - "x": 10, - "y": 12, + "x": 22, + "y": 9, "average_household_income_change": 1134.450520364727, "relative_household_income_change": 1e-12, "population": 146435.07039696595 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -2229.0, + "average_household_income_change_upper": -1641.0, + "relative_household_income_change_lower": 0.2742, + "relative_household_income_change_upper": 0.3721, "constituency_code": "E14000000384", "constituency_name": "Constituency 384", - "x": 11, - "y": 12, + "x": 23, + "y": 9, "average_household_income_change": -1935.1463493486115, "relative_household_income_change": 0.32313335925070485, "population": 58004.102496374035 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -244.0, + "average_household_income_change_upper": -174.0, + "relative_household_income_change_lower": 0.5254, + "relative_household_income_change_upper": 0.7119, "constituency_code": "E14000000385", "constituency_name": "Constituency 385", - "x": 12, - "y": 12, + "x": 24, + "y": 9, "average_household_income_change": -209.05028104926782, "relative_household_income_change": 0.6186153260113829, "population": 117034.62816551719 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1436.0, + "average_household_income_change_upper": 1952.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000386", "constituency_name": "Constituency 386", - "x": null, - "y": null, + "x": 25, + "y": 9, "average_household_income_change": 1694.0160478141113, "relative_household_income_change": -0.0, "population": 89858.43775105188 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1019.0, + "average_household_income_change_upper": 1387.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000387", "constituency_name": "Constituency 387", - "x": 14, - "y": 12, + "x": 26, + "y": 9, "average_household_income_change": 1203.3637271579084, "relative_household_income_change": -3.5e-9, "population": 147699.35190383965 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1201.0, + "average_household_income_change_upper": -882.0, + "relative_household_income_change_lower": 0.6593, + "relative_household_income_change_upper": 0.8931, "constituency_code": "E14000000388", "constituency_name": "Constituency 388", - "x": 15, - "y": 12, + "x": 27, + "y": 9, "average_household_income_change": -1041.2816219126073, "relative_household_income_change": 0.7761888702877715, "population": 140566.11583849424 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1665.0, + "average_household_income_change_upper": 2262.0, + "relative_household_income_change_lower": 0.1343, + "relative_household_income_change_upper": 0.1828, "constituency_code": "E14000000389", "constituency_name": "Constituency 389", - "x": 16, - "y": 12, + "x": 28, + "y": 9, "average_household_income_change": 1963.4883502536732, "relative_household_income_change": 0.15856590673397397, "population": 99208.27114640783 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -626.0, + "average_household_income_change_upper": -457.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000390", "constituency_name": "Constituency 390", - "x": 17, - "y": 12, + "x": 29, + "y": 9, "average_household_income_change": -541.6746768853842, "relative_household_income_change": -0.0, "population": 146739.93179938247 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 330.0, + "average_household_income_change_upper": 455.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000391", "constituency_name": "Constituency 391", - "x": 18, - "y": 12, + "x": 30, + "y": 9, "average_household_income_change": 392.3345088407983, "relative_household_income_change": -3.5e-9, "population": 110310.79494795081 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": -1607.0, + "average_household_income_change_upper": -1182.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000392", "constituency_name": "Constituency 392", - "x": 19, - "y": 12, + "x": 31, + "y": 9, "average_household_income_change": -1394.3824785730135, "relative_household_income_change": 0.0, "population": 91123.9105954635 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1600.0, + "average_household_income_change_upper": 2173.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000393", "constituency_name": "Constituency 393", - "x": null, - "y": null, + "x": 32, + "y": 9, "average_household_income_change": 1886.147031653585, "relative_household_income_change": 1e-12, "population": 127053.70056596707 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -883.0, + "average_household_income_change_upper": -646.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000394", "constituency_name": "Constituency 394", - "x": 21, - "y": 12, + "x": 33, + "y": 9, "average_household_income_change": -764.3913703477714, "relative_household_income_change": 0.0, "population": 74690.3431446662 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -478.0, + "average_household_income_change_upper": -347.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000395", "constituency_name": "Constituency 395", - "x": 22, - "y": 12, + "x": 34, + "y": 9, "average_household_income_change": -412.86388601931725, "relative_household_income_change": -0.0, "population": 91152.69472270005 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -606.0, + "average_household_income_change_upper": -442.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000396", "constituency_name": "Constituency 396", - "x": 23, - "y": 12, + "x": 35, + "y": 9, "average_household_income_change": -523.5367854396005, "relative_household_income_change": -0.0, "population": 96083.32104944291 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -508.0, + "average_household_income_change_upper": -369.0, + "relative_household_income_change_lower": 0.3128, + "relative_household_income_change_upper": 0.4243, "constituency_code": "E14000000397", "constituency_name": "Constituency 397", - "x": 24, - "y": 12, + "x": 36, + "y": 9, "average_household_income_change": -438.4916791503861, "relative_household_income_change": 0.36857333601514064, "population": 65334.83510074024 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1716.0, + "average_household_income_change_upper": -1262.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000398", "constituency_name": "Constituency 398", - "x": 25, - "y": 12, + "x": 37, + "y": 9, "average_household_income_change": -1489.3255914403437, "relative_household_income_change": -0.0, "population": 75879.3948917247 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1085.0, + "average_household_income_change_upper": 1476.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000399", "constituency_name": "Constituency 399", - "x": 26, - "y": 12, + "x": 38, + "y": 9, "average_household_income_change": 1280.5129456302825, "relative_household_income_change": 0.0, "population": 140421.26314416766 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 709.0, + "average_household_income_change_upper": 967.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000400", "constituency_name": "Constituency 400", - "x": null, - "y": null, + "x": 39, + "y": 9, "average_household_income_change": 838.1710243074423, "relative_household_income_change": 1e-12, "population": 102164.8608901718 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": -2057.0, + "average_household_income_change_upper": -1514.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000401", "constituency_name": "Constituency 401", - "x": 28, - "y": 12, + "x": 0, + "y": 10, "average_household_income_change": -1785.5002054920485, "relative_household_income_change": -0.0, "population": 87580.2271317752 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -796.0, + "average_household_income_change_upper": -582.0, + "relative_household_income_change_lower": 0.5727, + "relative_household_income_change_upper": 0.7758, "constituency_code": "E14000000402", "constituency_name": "Constituency 402", - "x": 29, - "y": 12, + "x": 1, + "y": 10, "average_household_income_change": -689.4004480676439, "relative_household_income_change": 0.6742375088852286, "population": 81438.53883171464 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -456.0, + "average_household_income_change_upper": -331.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000403", "constituency_name": "Constituency 403", - "x": 30, - "y": 12, + "x": 2, + "y": 10, "average_household_income_change": -393.4628128033797, "relative_household_income_change": -0.0, "population": 75039.98922314639 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1327.0, + "average_household_income_change_upper": 1803.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000404", "constituency_name": "Constituency 404", - "x": 0, - "y": 13, + "x": 3, + "y": 10, "average_household_income_change": 1565.0837804033047, "relative_household_income_change": 0.0, "population": 142227.87444765354 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -392.0, + "average_household_income_change_upper": -284.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000405", "constituency_name": "Constituency 405", - "x": 1, - "y": 13, + "x": 4, + "y": 10, "average_household_income_change": -337.8714605234876, "relative_household_income_change": -3.5e-9, "population": 77203.57983346927 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1217.0, + "average_household_income_change_upper": -894.0, + "relative_household_income_change_lower": 0.3462, + "relative_household_income_change_upper": 0.4695, "constituency_code": "E14000000406", "constituency_name": "Constituency 406", - "x": 2, - "y": 13, + "x": 5, + "y": 10, "average_household_income_change": -1055.3789197118797, "relative_household_income_change": 0.4078556824436944, "population": 136422.76200474886 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 705.0, + "average_household_income_change_upper": 963.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000407", "constituency_name": "Constituency 407", - "x": null, - "y": null, + "x": 6, + "y": 10, "average_household_income_change": 834.0527556961325, "relative_household_income_change": -3.5e-9, "population": 97354.9639783863 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 110.0, + "average_household_income_change_upper": 158.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000408", "constituency_name": "Constituency 408", - "x": 4, - "y": 13, + "x": 7, + "y": 10, "average_household_income_change": 134.09988432838736, "relative_household_income_change": -3.5e-9, "population": 119310.48812370429 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 600.0, + "average_household_income_change_upper": 820.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000409", "constituency_name": "Constituency 409", - "x": 5, - "y": 13, + "x": 8, + "y": 10, "average_household_income_change": 710.0191188423665, "relative_household_income_change": -3.5e-9, "population": 104900.49608990214 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": -1997.0, + "average_household_income_change_upper": -1470.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000410", "constituency_name": "Constituency 410", - "x": 6, - "y": 13, + "x": 9, + "y": 10, "average_household_income_change": -1733.3123895866431, "relative_household_income_change": -3.5e-9, "population": 72416.44538586303 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1126.0, + "average_household_income_change_upper": 1532.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000411", "constituency_name": "Constituency 411", - "x": 7, - "y": 13, + "x": 10, + "y": 10, "average_household_income_change": 1328.957189349265, "relative_household_income_change": 1e-12, "population": 55101.62863024679 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 732.0, + "average_household_income_change_upper": 998.0, + "relative_household_income_change_lower": 0.2194, + "relative_household_income_change_upper": 0.2979, "constituency_code": "E14000000412", "constituency_name": "Constituency 412", - "x": 8, - "y": 13, + "x": 11, + "y": 10, "average_household_income_change": 864.9534307001913, "relative_household_income_change": 0.25864922967497583, "population": 82769.6707088191 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1171.0, + "average_household_income_change_upper": -860.0, + "relative_household_income_change_lower": 0.4727, + "relative_household_income_change_upper": 0.6406, "constituency_code": "E14000000413", "constituency_name": "Constituency 413", - "x": 9, - "y": 13, + "x": 12, + "y": 10, "average_household_income_change": -1015.563802054348, "relative_household_income_change": 0.5566808097245476, "population": 115698.84677273533 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1668.0, + "average_household_income_change_upper": 2264.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000414", "constituency_name": "Constituency 414", - "x": null, - "y": null, + "x": 13, + "y": 10, "average_household_income_change": 1966.0549435935516, "relative_household_income_change": -3.5e-9, "population": 63072.63158724338 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1981.0, + "average_household_income_change_upper": -1458.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000415", "constituency_name": "Constituency 415", - "x": 11, - "y": 13, + "x": 14, + "y": 10, "average_household_income_change": -1719.4482496747435, "relative_household_income_change": 1e-12, "population": 122400.05252854996 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -736.0, + "average_household_income_change_upper": -538.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000416", "constituency_name": "Constituency 416", - "x": 12, - "y": 13, + "x": 15, + "y": 10, "average_household_income_change": -637.0025407932425, "relative_household_income_change": -0.0, "population": 117953.03763761363 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -666.0, + "average_household_income_change_upper": -486.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000417", - "constituency_name": "Constituency 417", - "x": 13, - "y": 13, + "constituency_name": "Constituency 417", + "x": 16, + "y": 10, "average_household_income_change": -576.1912016158312, "relative_household_income_change": -0.0, "population": 109259.17191042229 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1159.0, + "average_household_income_change_upper": -850.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000418", "constituency_name": "Constituency 418", - "x": 14, - "y": 13, + "x": 17, + "y": 10, "average_household_income_change": -1004.6878933670484, "relative_household_income_change": -3.5e-9, "population": 91871.97834788615 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": -2231.0, + "average_household_income_change_upper": -1643.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000419", "constituency_name": "Constituency 419", - "x": 15, - "y": 13, + "x": 18, + "y": 10, "average_household_income_change": -1937.3634334742933, "relative_household_income_change": 0.0, "population": 115991.17237357103 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -105.0, + "average_household_income_change_upper": -72.0, + "relative_household_income_change_lower": 0.1651, + "relative_household_income_change_upper": 0.2244, "constituency_code": "E14000000420", "constituency_name": "Constituency 420", - "x": 16, - "y": 13, + "x": 19, + "y": 10, "average_household_income_change": -88.33450719112923, "relative_household_income_change": 0.19477066794069864, "population": 138651.37596406846 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -2055.0, + "average_household_income_change_upper": -1513.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000421", "constituency_name": "Constituency 421", - "x": null, - "y": null, + "x": 20, + "y": 10, "average_household_income_change": -1783.8506563658334, "relative_household_income_change": -0.0, "population": 119996.31865550006 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -147.0, + "average_household_income_change_upper": -103.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000422", "constituency_name": "Constituency 422", - "x": 18, - "y": 13, + "x": 21, + "y": 10, "average_household_income_change": -124.97928653299084, "relative_household_income_change": -0.0, "population": 103284.53004234466 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 631.0, + "average_household_income_change_upper": 863.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000423", "constituency_name": "Constituency 423", - "x": 19, - "y": 13, + "x": 22, + "y": 10, "average_household_income_change": 746.9717492722236, "relative_household_income_change": 0.0, "population": 64314.765602602485 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -464.0, + "average_household_income_change_upper": -337.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000424", "constituency_name": "Constituency 424", - "x": 20, - "y": 13, + "x": 23, + "y": 10, "average_household_income_change": -400.21091127364275, "relative_household_income_change": -3.5e-9, "population": 126140.46522738156 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -13.0, + "average_household_income_change_upper": -4.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000425", "constituency_name": "Constituency 425", - "x": 21, - "y": 13, + "x": 24, + "y": 10, "average_household_income_change": -8.615886541627926, "relative_household_income_change": 1e-12, "population": 120500.20874521669 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1666.0, + "average_household_income_change_upper": -1225.0, + "relative_household_income_change_lower": 0.8489, + "relative_household_income_change_upper": 1.1496, "constituency_code": "E14000000426", "constituency_name": "Constituency 426", - "x": 22, - "y": 13, + "x": 25, + "y": 10, "average_household_income_change": -1445.5321322845048, "relative_household_income_change": 0.9992850483781154, "population": 78517.46219775046 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 217.0, + "average_household_income_change_upper": 302.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000427", "constituency_name": "Constituency 427", - "x": 23, - "y": 13, + "x": 26, + "y": 10, "average_household_income_change": 259.7025064134226, "relative_household_income_change": -3.5e-9, "population": 134534.28932349032 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": 1147.0, + "average_household_income_change_upper": 1560.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000428", "constituency_name": "Constituency 428", - "x": null, - "y": null, + "x": 27, + "y": 10, "average_household_income_change": 1353.384121501907, "relative_household_income_change": -3.5e-9, "population": 65122.60724567148 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1386.0, + "average_household_income_change_upper": -1018.0, + "relative_household_income_change_lower": 0.3715, + "relative_household_income_change_upper": 0.5036, "constituency_code": "E14000000429", "constituency_name": "Constituency 429", - "x": 25, - "y": 13, + "x": 28, + "y": 10, "average_household_income_change": -1202.1846279558727, "relative_household_income_change": 0.4375422625855504, "population": 106516.88841622724 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1114.0, + "average_household_income_change_upper": -818.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000430", "constituency_name": "Constituency 430", - "x": 26, - "y": 13, + "x": 29, + "y": 10, "average_household_income_change": -965.9386032117636, "relative_household_income_change": -3.5e-9, "population": 77348.31795576304 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -463.0, + "average_household_income_change_upper": -336.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000431", "constituency_name": "Constituency 431", - "x": 27, - "y": 13, + "x": 30, + "y": 10, "average_household_income_change": -399.31020340847834, "relative_household_income_change": -0.0, "population": 120119.21276118392 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1731.0, + "average_household_income_change_upper": -1273.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000432", "constituency_name": "Constituency 432", - "x": 28, - "y": 13, + "x": 31, + "y": 10, "average_household_income_change": -1501.7510086178102, "relative_household_income_change": -3.5e-9, "population": 123543.00333458264 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1587.0, + "average_household_income_change_upper": 2156.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000433", "constituency_name": "Constituency 433", - "x": 29, - "y": 13, + "x": 32, + "y": 10, "average_household_income_change": 1871.3633908875686, "relative_household_income_change": -0.0, "population": 114188.50689344354 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1014.0, + "average_household_income_change_upper": -744.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000434", "constituency_name": "Constituency 434", - "x": 30, - "y": 13, + "x": 33, + "y": 10, "average_household_income_change": -878.9359766848924, "relative_household_income_change": 0.0, "population": 137125.66547882586 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 15.0, + "average_household_income_change_upper": 29.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000435", "constituency_name": "Constituency 435", - "x": null, - "y": null, + "x": 34, + "y": 10, "average_household_income_change": 22.292631722566902, "relative_household_income_change": -3.5e-9, "population": 81603.38693974496 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -991.0, + "average_household_income_change_upper": -726.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000436", "constituency_name": "Constituency 436", - "x": 1, - "y": 14, + "x": 35, + "y": 10, "average_household_income_change": -858.5202969894166, "relative_household_income_change": -3.5e-9, "population": 134844.320946582 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": 939.0, + "average_household_income_change_upper": 1279.0, + "relative_household_income_change_lower": 0.6774, + "relative_household_income_change_upper": 0.9175, "constituency_code": "E14000000437", "constituency_name": "Constituency 437", - "x": 2, - "y": 14, + "x": 36, + "y": 10, "average_household_income_change": 1108.7892653049796, "relative_household_income_change": 0.7974146129248088, "population": 109738.3225739174 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -2232.0, + "average_household_income_change_upper": -1644.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000438", "constituency_name": "Constituency 438", - "x": 3, - "y": 14, + "x": 37, + "y": 10, "average_household_income_change": -1938.1221811323512, "relative_household_income_change": -3.5e-9, "population": 133395.10392182146 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 438.0, + "average_household_income_change_upper": 601.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000439", "constituency_name": "Constituency 439", - "x": 4, - "y": 14, + "x": 38, + "y": 10, "average_household_income_change": 519.5332360344125, "relative_household_income_change": -0.0, "population": 110056.89208575683 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1018.0, + "average_household_income_change_upper": 1385.0, + "relative_household_income_change_lower": 0.5377, + "relative_household_income_change_upper": 0.7285, "constituency_code": "E14000000440", "constituency_name": "Constituency 440", - "x": 5, - "y": 14, + "x": 39, + "y": 10, "average_household_income_change": 1201.6281562769175, "relative_household_income_change": 0.6330995821885036, "population": 139221.9302277582 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1196.0, + "average_household_income_change_upper": 1627.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000441", "constituency_name": "Constituency 441", - "x": 6, - "y": 14, + "x": 0, + "y": 11, "average_household_income_change": 1411.4779232097058, "relative_household_income_change": -0.0, "population": 98613.22805672791 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -2130.0, + "average_household_income_change_upper": -1568.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000442", "constituency_name": "Constituency 442", - "x": null, - "y": null, + "x": 1, + "y": 11, "average_household_income_change": -1849.2825797469372, "relative_household_income_change": 1e-12, "population": 114277.94687681618 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1254.0, + "average_household_income_change_upper": 1705.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000443", "constituency_name": "Constituency 443", - "x": 8, - "y": 14, + "x": 2, + "y": 11, "average_household_income_change": 1479.1634504108054, "relative_household_income_change": -0.0, "population": 55027.6507208199 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -363.0, + "average_household_income_change_upper": -262.0, + "relative_household_income_change_lower": 0.5014, + "relative_household_income_change_upper": 0.6794, "constituency_code": "E14000000444", "constituency_name": "Constituency 444", - "x": 9, - "y": 14, + "x": 3, + "y": 11, "average_household_income_change": -312.3263436457391, "relative_household_income_change": 0.5903607041796785, "population": 134005.43950487245 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -275.0, + "average_household_income_change_upper": -197.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000445", "constituency_name": "Constituency 445", - "x": 10, - "y": 14, + "x": 4, + "y": 11, "average_household_income_change": -235.72010774130314, "relative_household_income_change": -0.0, "population": 107152.43583785828 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": 232.0, + "average_household_income_change_upper": 322.0, + "relative_household_income_change_lower": 0.4361, + "relative_household_income_change_upper": 0.591, "constituency_code": "E14000000446", "constituency_name": "Constituency 446", - "x": 11, - "y": 14, + "x": 5, + "y": 11, "average_household_income_change": 277.1497954833628, "relative_household_income_change": 0.5135397749456319, "population": 70104.98439053618 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1551.0, + "average_household_income_change_upper": 2106.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000447", "constituency_name": "Constituency 447", - "x": 12, - "y": 14, + "x": 6, + "y": 11, "average_household_income_change": 1828.3291736397134, "relative_household_income_change": 0.0, "population": 105758.01403771316 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1818.0, + "average_household_income_change_upper": -1337.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000448", "constituency_name": "Constituency 448", - "x": 13, - "y": 14, + "x": 7, + "y": 11, "average_household_income_change": -1577.4235955150164, "relative_household_income_change": -0.0, "population": 84769.36787383328 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1586.0, + "average_household_income_change_upper": -1166.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000449", "constituency_name": "Constituency 449", - "x": null, - "y": null, + "x": 8, + "y": 11, "average_household_income_change": -1375.9862826114268, "relative_household_income_change": -3.5e-9, "population": 68155.11585838869 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1373.0, + "average_household_income_change_upper": 1866.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000450", "constituency_name": "Constituency 450", - "x": 15, - "y": 14, + "x": 9, + "y": 11, "average_household_income_change": 1619.7588245435081, "relative_household_income_change": 1e-12, "population": 108529.78607189572 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -154.0, + "average_household_income_change_upper": -107.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000451", "constituency_name": "Constituency 451", - "x": 16, - "y": 14, + "x": 10, + "y": 11, "average_household_income_change": -130.43885920074817, "relative_household_income_change": -3.5e-9, "population": 102164.24550005347 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1336.0, + "average_household_income_change_upper": 1816.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000452", "constituency_name": "Constituency 452", - "x": 17, - "y": 14, + "x": 11, + "y": 11, "average_household_income_change": 1575.9769085769442, "relative_household_income_change": -0.0, "population": 83074.55414942687 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1587.0, + "average_household_income_change_upper": -1167.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000453", "constituency_name": "Constituency 453", - "x": 18, - "y": 14, + "x": 12, + "y": 11, "average_household_income_change": -1376.5227309882753, "relative_household_income_change": 1e-12, "population": 76954.27379439081 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 20.0, + "average_household_income_change_upper": 36.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000454", "constituency_name": "Constituency 454", - "x": 19, - "y": 14, + "x": 13, + "y": 11, "average_household_income_change": 27.855930561574205, "relative_household_income_change": -3.5e-9, "population": 67970.8621895939 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": 214.0, + "average_household_income_change_upper": 297.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000455", "constituency_name": "Constituency 455", - "x": 20, - "y": 14, + "x": 14, + "y": 11, "average_household_income_change": 255.4598736945679, "relative_household_income_change": -0.0, "population": 134897.99335933474 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1695.0, + "average_household_income_change_upper": -1247.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000456", "constituency_name": "Constituency 456", - "x": null, - "y": null, + "x": 15, + "y": 11, "average_household_income_change": -1470.9287179798966, "relative_household_income_change": -0.0, "population": 110214.6845204571 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1229.0, + "average_household_income_change_upper": -902.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000457", "constituency_name": "Constituency 457", - "x": 22, - "y": 14, + "x": 16, + "y": 11, "average_household_income_change": -1065.357672584253, "relative_household_income_change": 0.0, "population": 85225.7969482269 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1549.0, + "average_household_income_change_upper": 2104.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000458", "constituency_name": "Constituency 458", - "x": 23, - "y": 14, + "x": 17, + "y": 11, "average_household_income_change": 1826.5135187399758, "relative_household_income_change": 1e-12, "population": 98812.90540379459 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -2025.0, + "average_household_income_change_upper": -1491.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000459", "constituency_name": "Constituency 459", - "x": 24, - "y": 14, + "x": 18, + "y": 11, "average_household_income_change": -1758.258007451244, "relative_household_income_change": 0.0, "population": 120834.59886771583 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1409.0, + "average_household_income_change_upper": 1914.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000460", "constituency_name": "Constituency 460", - "x": 25, - "y": 14, + "x": 19, + "y": 11, "average_household_income_change": 1661.4752599701808, "relative_household_income_change": -3.5e-9, "population": 140361.971015295 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 714.0, + "average_household_income_change_upper": 974.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000461", "constituency_name": "Constituency 461", - "x": 26, - "y": 14, + "x": 20, + "y": 11, "average_household_income_change": 843.8123826337538, "relative_household_income_change": -0.0, "population": 107298.60428240836 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -305.0, + "average_household_income_change_upper": -219.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000462", "constituency_name": "Constituency 462", - "x": 27, - "y": 14, + "x": 21, + "y": 11, "average_household_income_change": -261.89617854069394, "relative_household_income_change": -0.0, "population": 64880.04282406481 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -420.0, + "average_household_income_change_upper": -305.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000463", "constituency_name": "Constituency 463", - "x": null, - "y": null, + "x": 22, + "y": 11, "average_household_income_change": -362.59096189355546, "relative_household_income_change": 0.0, "population": 50746.49871824345 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": -1590.0, + "average_household_income_change_upper": -1169.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000464", "constituency_name": "Constituency 464", - "x": 29, - "y": 14, + "x": 23, + "y": 11, "average_household_income_change": -1379.3381831933407, "relative_household_income_change": -3.5e-9, "population": 81843.30796123961 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1034.0, + "average_household_income_change_upper": -758.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000465", "constituency_name": "Constituency 465", - "x": 30, - "y": 14, + "x": 24, + "y": 11, "average_household_income_change": -895.9319061295998, "relative_household_income_change": -0.0, "population": 86307.51948753887 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1206.0, + "average_household_income_change_upper": -885.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000466", "constituency_name": "Constituency 466", - "x": 0, - "y": 15, + "x": 25, + "y": 11, "average_household_income_change": -1045.5240756289488, "relative_household_income_change": 0.0, "population": 106630.97285104157 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -155.0, + "average_household_income_change_upper": -108.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000467", "constituency_name": "Constituency 467", - "x": 1, - "y": 15, + "x": 26, + "y": 11, "average_household_income_change": -131.40113141275344, "relative_household_income_change": 0.0, "population": 85625.67572050777 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -997.0, + "average_household_income_change_upper": -731.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000468", "constituency_name": "Constituency 468", - "x": 2, - "y": 15, + "x": 27, + "y": 11, "average_household_income_change": -864.2228005114356, "relative_household_income_change": 1e-12, "population": 110692.75990094521 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1404.0, + "average_household_income_change_upper": -1031.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000469", "constituency_name": "Constituency 469", - "x": 3, - "y": 15, + "x": 28, + "y": 11, "average_household_income_change": -1217.396077124258, "relative_household_income_change": 1e-12, "population": 95791.24250102474 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 693.0, + "average_household_income_change_upper": 946.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000470", "constituency_name": "Constituency 470", - "x": null, - "y": null, + "x": 29, + "y": 11, "average_household_income_change": 819.4095140623756, "relative_household_income_change": -3.5e-9, "population": 132591.75404400696 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -783.0, + "average_household_income_change_upper": -572.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000471", "constituency_name": "Constituency 471", - "x": 5, - "y": 15, + "x": 30, + "y": 11, "average_household_income_change": -677.4478721217139, "relative_household_income_change": -0.0, "population": 93372.07825937188 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 650.0, + "average_household_income_change_upper": 888.0, + "relative_household_income_change_lower": 0.2976, + "relative_household_income_change_upper": 0.4038, "constituency_code": "E14000000472", "constituency_name": "Constituency 472", - "x": 6, - "y": 15, + "x": 31, + "y": 11, "average_household_income_change": 769.2812919052758, "relative_household_income_change": 0.35070114616556214, "population": 82749.8384185931 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": 1549.0, + "average_household_income_change_upper": 2104.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000473", "constituency_name": "Constituency 473", - "x": 7, - "y": 15, + "x": 32, + "y": 11, "average_household_income_change": 1826.5823371023187, "relative_household_income_change": -0.0, "population": 94452.51692962078 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -986.0, + "average_household_income_change_upper": -723.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000474", "constituency_name": "Constituency 474", - "x": 8, - "y": 15, + "x": 33, + "y": 11, "average_household_income_change": -854.2150106850004, "relative_household_income_change": 0.0, "population": 73725.82272334029 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1548.0, + "average_household_income_change_upper": 2103.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000475", "constituency_name": "Constituency 475", - "x": 9, - "y": 15, + "x": 34, + "y": 11, "average_household_income_change": 1825.4016048874723, "relative_household_income_change": 0.0, "population": 77291.27368977931 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 181.0, + "average_household_income_change_upper": 253.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000476", "constituency_name": "Constituency 476", - "x": 10, - "y": 15, + "x": 35, + "y": 11, "average_household_income_change": 216.77639129025695, "relative_household_income_change": 0.0, "population": 77824.36965646 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1836.0, + "average_household_income_change_upper": -1351.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000477", "constituency_name": "Constituency 477", - "x": null, - "y": null, + "x": 36, + "y": 11, "average_household_income_change": -1593.3122775483603, "relative_household_income_change": -3.5e-9, "population": 111493.02905492586 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1455.0, + "average_household_income_change_upper": -1069.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000478", "constituency_name": "Constituency 478", - "x": 12, - "y": 15, + "x": 37, + "y": 11, "average_household_income_change": -1262.0158636617136, "relative_household_income_change": -0.0, "population": 57389.887600907605 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -2001.0, + "average_household_income_change_upper": -1473.0, + "relative_household_income_change_lower": 0.4041, + "relative_household_income_change_upper": 0.5477, "constituency_code": "E14000000479", "constituency_name": "Constituency 479", - "x": 13, - "y": 15, + "x": 38, + "y": 11, "average_household_income_change": -1737.3547076698944, "relative_household_income_change": 0.4758874388681912, "population": 146184.4538265504 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1541.0, + "average_household_income_change_upper": -1133.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000480", "constituency_name": "Constituency 480", - "x": 14, - "y": 15, + "x": 39, + "y": 11, "average_household_income_change": -1337.146372116397, "relative_household_income_change": -0.0, "population": 99503.02345698366 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -513.0, + "average_household_income_change_upper": -373.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000481", "constituency_name": "Constituency 481", - "x": 15, - "y": 15, + "x": 0, + "y": 12, "average_household_income_change": -443.31641902452026, "relative_household_income_change": 1e-12, "population": 95722.83718255228 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": 422.0, + "average_household_income_change_upper": 579.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000482", "constituency_name": "Constituency 482", - "x": 16, - "y": 15, + "x": 1, + "y": 12, "average_household_income_change": 500.8423169444973, "relative_household_income_change": 1e-12, "population": 93764.74125416626 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -416.0, + "average_household_income_change_upper": -302.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000483", "constituency_name": "Constituency 483", - "x": 17, - "y": 15, + "x": 2, + "y": 12, "average_household_income_change": -359.07471826969186, "relative_household_income_change": 0.0, "population": 138311.96152862016 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1183.0, + "average_household_income_change_upper": 1609.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000484", "constituency_name": "Constituency 484", - "x": null, - "y": null, + "x": 3, + "y": 12, "average_household_income_change": 1395.8256437349855, "relative_household_income_change": -0.0, "population": 86636.26588590886 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 810.0, + "average_household_income_change_upper": 1105.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000485", "constituency_name": "Constituency 485", - "x": 19, - "y": 15, + "x": 4, + "y": 12, "average_household_income_change": 957.414181435833, "relative_household_income_change": -3.5e-9, "population": 68778.62572790433 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 41.0, + "average_household_income_change_upper": 63.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000486", "constituency_name": "Constituency 486", - "x": 20, - "y": 15, + "x": 5, + "y": 12, "average_household_income_change": 52.068594084960566, "relative_household_income_change": -0.0, "population": 149629.3667680624 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -538.0, + "average_household_income_change_upper": -392.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000487", "constituency_name": "Constituency 487", - "x": 21, - "y": 15, + "x": 6, + "y": 12, "average_household_income_change": -464.85862856143, "relative_household_income_change": -0.0, "population": 110352.0278947326 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1496.0, + "average_household_income_change_upper": 2032.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000488", "constituency_name": "Constituency 488", - "x": 22, - "y": 15, + "x": 7, + "y": 12, "average_household_income_change": 1764.0835881287157, "relative_household_income_change": 1e-12, "population": 62384.47166940049 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 585.0, + "average_household_income_change_upper": 800.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000489", "constituency_name": "Constituency 489", - "x": 23, - "y": 15, + "x": 8, + "y": 12, "average_household_income_change": 692.3998314092001, "relative_household_income_change": 0.0, "population": 85408.80666901525 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1357.0, + "average_household_income_change_upper": 1845.0, + "relative_household_income_change_lower": 0.2763, + "relative_household_income_change_upper": 0.3749, "constituency_code": "E14000000490", "constituency_name": "Constituency 490", - "x": 24, - "y": 15, + "x": 9, + "y": 12, "average_household_income_change": 1601.0227417620797, "relative_household_income_change": 0.3256023747916895, "population": 127392.7504156333 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": -1067.0, + "average_household_income_change_upper": -782.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000491", "constituency_name": "Constituency 491", - "x": null, - "y": null, + "x": 10, + "y": 12, "average_household_income_change": -924.525713053443, "relative_household_income_change": 1e-12, "population": 115834.91080642746 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1363.0, + "average_household_income_change_upper": 1852.0, + "relative_household_income_change_lower": 0.0729, + "relative_household_income_change_upper": 0.0996, "constituency_code": "E14000000492", "constituency_name": "Constituency 492", - "x": 26, - "y": 15, + "x": 11, + "y": 12, "average_household_income_change": 1607.7828851379104, "relative_household_income_change": 0.08626010051598998, "population": 116576.36483302494 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 330.0, + "average_household_income_change_upper": 455.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000493", "constituency_name": "Constituency 493", - "x": 27, - "y": 15, + "x": 12, + "y": 12, "average_household_income_change": 392.5900111746632, "relative_household_income_change": -0.0, "population": 132360.86716965502 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 187.0, + "average_household_income_change_upper": 261.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000494", "constituency_name": "Constituency 494", - "x": 28, - "y": 15, + "x": 13, + "y": 12, "average_household_income_change": 223.9340392642153, "relative_household_income_change": -3.5e-9, "population": 134846.52691992815 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1222.0, + "average_household_income_change_upper": 1661.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000495", "constituency_name": "Constituency 495", - "x": 29, - "y": 15, + "x": 14, + "y": 12, "average_household_income_change": 1441.2988042773184, "relative_household_income_change": 0.0, "population": 137986.4965672183 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -577.0, + "average_household_income_change_upper": -420.0, + "relative_household_income_change_lower": 0.2761, + "relative_household_income_change_upper": 0.3745, "constituency_code": "E14000000496", "constituency_name": "Constituency 496", - "x": 30, - "y": 15, + "x": 15, + "y": 12, "average_household_income_change": -498.7039191058127, "relative_household_income_change": 0.3252945301780501, "population": 143405.9946706618 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 960.0, + "average_household_income_change_upper": 1307.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000497", "constituency_name": "Constituency 497", - "x": 0, - "y": 16, + "x": 16, + "y": 12, "average_household_income_change": 1133.1963374325728, "relative_household_income_change": 1e-12, "population": 68426.46908976509 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1316.0, + "average_household_income_change_upper": 1789.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000498", "constituency_name": "Constituency 498", - "x": null, - "y": null, + "x": 17, + "y": 12, "average_household_income_change": 1552.2279517645652, "relative_household_income_change": 1e-12, "population": 69801.21947574713 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -2226.0, + "average_household_income_change_upper": -1640.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000499", "constituency_name": "Constituency 499", - "x": 2, - "y": 16, + "x": 18, + "y": 12, "average_household_income_change": -1933.0121573332403, "relative_household_income_change": -0.0, "population": 71810.7127554828 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": 1574.0, + "average_household_income_change_upper": 2138.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000500", "constituency_name": "Constituency 500", - "x": 3, - "y": 16, + "x": 19, + "y": 12, "average_household_income_change": 1856.020820102462, "relative_household_income_change": -0.0, "population": 115990.60962848747 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1645.0, + "average_household_income_change_upper": 2234.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000501", "constituency_name": "Constituency 501", - "x": 4, - "y": 16, + "x": 20, + "y": 12, "average_household_income_change": 1939.131245149897, "relative_household_income_change": 0.0, "population": 145774.10814719292 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1395.0, + "average_household_income_change_upper": 1895.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000502", "constituency_name": "Constituency 502", - "x": 5, - "y": 16, + "x": 21, + "y": 12, "average_household_income_change": 1644.716537294447, "relative_household_income_change": -0.0, "population": 115658.11807754858 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1886.0, + "average_household_income_change_upper": -1388.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000503", "constituency_name": "Constituency 503", - "x": 6, - "y": 16, + "x": 22, + "y": 12, "average_household_income_change": -1636.9003200301875, "relative_household_income_change": 0.0, "population": 89531.70714848021 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 72.0, + "average_household_income_change_upper": 106.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000504", "constituency_name": "Constituency 504", - "x": 7, - "y": 16, + "x": 23, + "y": 12, "average_household_income_change": 88.92124000860102, "relative_household_income_change": 1e-12, "population": 125688.2659888468 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1520.0, + "average_household_income_change_upper": -1117.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000505", "constituency_name": "Constituency 505", - "x": null, - "y": null, + "x": 24, + "y": 12, "average_household_income_change": -1318.7744512100821, "relative_household_income_change": 0.0, "population": 91088.20168102277 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1356.0, + "average_household_income_change_upper": -996.0, + "relative_household_income_change_lower": 0.2598, + "relative_household_income_change_upper": 0.3525, "constituency_code": "E14000000506", "constituency_name": "Constituency 506", - "x": 9, - "y": 16, + "x": 25, + "y": 12, "average_household_income_change": -1175.9495393146576, "relative_household_income_change": 0.30616875596009807, "population": 131214.95491923267 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1659.0, + "average_household_income_change_upper": -1220.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000507", "constituency_name": "Constituency 507", - "x": 10, - "y": 16, + "x": 26, + "y": 12, "average_household_income_change": -1439.7064451060162, "relative_household_income_change": -3.5e-9, "population": 119035.7114330096 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 444.0, + "average_household_income_change_upper": 608.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000508", "constituency_name": "Constituency 508", - "x": 11, - "y": 16, + "x": 27, + "y": 12, "average_household_income_change": 525.9315378974767, "relative_household_income_change": 0.0, "population": 149780.60570252594 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": -1576.0, + "average_household_income_change_upper": -1159.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000509", "constituency_name": "Constituency 509", - "x": 12, - "y": 16, + "x": 28, + "y": 12, "average_household_income_change": -1367.1976497187427, "relative_household_income_change": 0.0, "population": 99775.86963739073 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 575.0, + "average_household_income_change_upper": 787.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000510", "constituency_name": "Constituency 510", - "x": 13, - "y": 16, + "x": 29, + "y": 12, "average_household_income_change": 681.0185339591745, "relative_household_income_change": 0.0, "population": 52250.53683271075 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 601.0, + "average_household_income_change_upper": 821.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000511", "constituency_name": "Constituency 511", - "x": 14, - "y": 16, + "x": 30, + "y": 12, "average_household_income_change": 711.0597691914737, "relative_household_income_change": -0.0, "population": 73213.28057757275 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 412.0, + "average_household_income_change_upper": 566.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000512", "constituency_name": "Constituency 512", - "x": null, - "y": null, + "x": 31, + "y": 12, "average_household_income_change": 488.84935913679016, "relative_household_income_change": 0.0, "population": 125981.89147263978 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1380.0, + "average_household_income_change_upper": -1014.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000513", "constituency_name": "Constituency 513", - "x": 16, - "y": 16, + "x": 32, + "y": 12, "average_household_income_change": -1196.9661233102288, "relative_household_income_change": -3.5e-9, "population": 128616.27263812006 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1305.0, + "average_household_income_change_upper": 1774.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000514", "constituency_name": "Constituency 514", - "x": 17, - "y": 16, + "x": 33, + "y": 12, "average_household_income_change": 1539.7654878967505, "relative_household_income_change": 1e-12, "population": 104552.41760001461 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 561.0, + "average_household_income_change_upper": 768.0, + "relative_household_income_change_lower": 0.778, + "relative_household_income_change_upper": 1.0536, "constituency_code": "E14000000515", "constituency_name": "Constituency 515", - "x": 18, - "y": 16, + "x": 34, + "y": 12, "average_household_income_change": 664.5980280202077, "relative_household_income_change": 0.9157729795254148, "population": 132900.03832707356 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 740.0, + "average_household_income_change_upper": 1010.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000516", "constituency_name": "Constituency 516", - "x": 19, - "y": 16, + "x": 35, + "y": 12, "average_household_income_change": 874.7981354443475, "relative_household_income_change": -0.0, "population": 139599.38195812594 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -110.0, + "average_household_income_change_upper": -75.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000517", "constituency_name": "Constituency 517", - "x": 20, - "y": 16, + "x": 36, + "y": 12, "average_household_income_change": -92.51945756994174, "relative_household_income_change": -0.0, "population": 127203.73196954656 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": 1188.0, + "average_household_income_change_upper": 1616.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000518", "constituency_name": "Constituency 518", - "x": 21, - "y": 16, + "x": 37, + "y": 12, "average_household_income_change": 1401.7863678742444, "relative_household_income_change": 0.0, "population": 101400.21509992852 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 805.0, + "average_household_income_change_upper": 1097.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000519", "constituency_name": "Constituency 519", - "x": null, - "y": null, + "x": 38, + "y": 12, "average_household_income_change": 950.872054844548, "relative_household_income_change": -3.5e-9, "population": 102808.51547701252 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 224.0, + "average_household_income_change_upper": 311.0, + "relative_household_income_change_lower": 0.7477, + "relative_household_income_change_upper": 1.0126, "constituency_code": "E14000000520", "constituency_name": "Constituency 520", - "x": 23, - "y": 16, + "x": 39, + "y": 12, "average_household_income_change": 267.1213839802129, "relative_household_income_change": 0.8801315917911949, "population": 113871.08181816454 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1343.0, + "average_household_income_change_upper": 1825.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000521", "constituency_name": "Constituency 521", - "x": 24, - "y": 16, + "x": 0, + "y": 13, "average_household_income_change": 1583.6668839155411, "relative_household_income_change": -0.0, "population": 76415.2914843896 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 399.0, + "average_household_income_change_upper": 548.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000522", "constituency_name": "Constituency 522", - "x": 25, - "y": 16, + "x": 1, + "y": 13, "average_household_income_change": 473.62702776804167, "relative_household_income_change": -0.0, "population": 110938.16395304399 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1409.0, + "average_household_income_change_upper": 1914.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000523", "constituency_name": "Constituency 523", - "x": 26, - "y": 16, + "x": 2, + "y": 13, "average_household_income_change": 1661.2704907714462, "relative_household_income_change": 1e-12, "population": 86960.28366122275 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1423.0, + "average_household_income_change_upper": 1933.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000524", "constituency_name": "Constituency 524", - "x": 27, - "y": 16, + "x": 3, + "y": 13, "average_household_income_change": 1677.6832707399083, "relative_household_income_change": -0.0, "population": 62627.66271913964 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 24.0, + "average_household_income_change_upper": 41.0, + "relative_household_income_change_lower": 0.6845, + "relative_household_income_change_upper": 0.9271, "constituency_code": "E14000000525", "constituency_name": "Constituency 525", - "x": 28, - "y": 16, + "x": 4, + "y": 13, "average_household_income_change": 32.65960657239475, "relative_household_income_change": 0.8058113644644113, "population": 88512.16871276736 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 810.0, + "average_household_income_change_upper": 1104.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000526", "constituency_name": "Constituency 526", - "x": null, - "y": null, + "x": 5, + "y": 13, "average_household_income_change": 956.6026427007084, "relative_household_income_change": 1e-12, "population": 67177.90548895177 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": -95.0, + "average_household_income_change_upper": -64.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000527", "constituency_name": "Constituency 527", - "x": 30, - "y": 16, + "x": 6, + "y": 13, "average_household_income_change": -79.65777433093812, "relative_household_income_change": -0.0, "population": 129359.15970497992 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1763.0, + "average_household_income_change_upper": -1297.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000528", "constituency_name": "Constituency 528", - "x": 0, - "y": 17, + "x": 7, + "y": 13, "average_household_income_change": -1530.3875617109775, "relative_household_income_change": -3.5e-9, "population": 122544.81803253728 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -797.0, + "average_household_income_change_upper": -583.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000529", "constituency_name": "Constituency 529", - "x": 1, - "y": 17, + "x": 8, + "y": 13, "average_household_income_change": -690.1267696520264, "relative_household_income_change": -0.0, "population": 74964.53753227353 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1544.0, + "average_household_income_change_upper": 2098.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000530", "constituency_name": "Constituency 530", - "x": 2, - "y": 17, + "x": 9, + "y": 13, "average_household_income_change": 1821.0119974157406, "relative_household_income_change": -3.5e-9, "population": 117617.45171258436 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 173.0, + "average_household_income_change_upper": 243.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000531", "constituency_name": "Constituency 531", - "x": 3, - "y": 17, + "x": 10, + "y": 13, "average_household_income_change": 208.0498046541739, "relative_household_income_change": -3.5e-9, "population": 143004.6731627013 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 17.0, + "average_household_income_change_upper": 32.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000532", "constituency_name": "Constituency 532", - "x": 4, - "y": 17, + "x": 11, + "y": 13, "average_household_income_change": 24.455900708818756, "relative_household_income_change": 0.0, "population": 74337.36080179275 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1682.0, + "average_household_income_change_upper": 2284.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000533", "constituency_name": "Constituency 533", - "x": null, - "y": null, + "x": 12, + "y": 13, "average_household_income_change": 1983.1116832288517, "relative_household_income_change": -3.5e-9, "population": 117952.23903240418 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 870.0, + "average_household_income_change_upper": 1185.0, + "relative_household_income_change_lower": 0.5132, + "relative_household_income_change_upper": 0.6954, "constituency_code": "E14000000534", "constituency_name": "Constituency 534", - "x": 6, - "y": 17, + "x": 13, + "y": 13, "average_household_income_change": 1027.6081219737403, "relative_household_income_change": 0.6042977436890922, "population": 122635.04116619783 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 747.0, + "average_household_income_change_upper": 1019.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000535", "constituency_name": "Constituency 535", - "x": 7, - "y": 17, + "x": 14, + "y": 13, "average_household_income_change": 883.3729304827402, "relative_household_income_change": -0.0, "population": 84563.45632753313 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": -481.0, + "average_household_income_change_upper": -349.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000536", "constituency_name": "Constituency 536", - "x": 8, - "y": 17, + "x": 15, + "y": 13, "average_household_income_change": -415.0102749434339, "relative_household_income_change": -3.5e-9, "population": 139019.39363636472 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1073.0, + "average_household_income_change_upper": -787.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000537", "constituency_name": "Constituency 537", - "x": 9, - "y": 17, + "x": 16, + "y": 13, "average_household_income_change": -929.7356907140188, "relative_household_income_change": -3.5e-9, "population": 62512.41742705785 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -2300.0, + "average_household_income_change_upper": -1694.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000538", "constituency_name": "Constituency 538", - "x": 10, - "y": 17, + "x": 17, + "y": 13, "average_household_income_change": -1996.7697301134376, "relative_household_income_change": 0.0, "population": 90369.34146142566 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1528.0, + "average_household_income_change_upper": 2075.0, + "relative_household_income_change_lower": 0.669, + "relative_household_income_change_upper": 0.9062, "constituency_code": "E14000000539", "constituency_name": "Constituency 539", - "x": 11, - "y": 17, + "x": 18, + "y": 13, "average_household_income_change": 1801.4507622204592, "relative_household_income_change": 0.7875965623100697, "population": 118552.27021021653 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -657.0, + "average_household_income_change_upper": -480.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000540", "constituency_name": "Constituency 540", - "x": null, - "y": null, + "x": 19, + "y": 13, "average_household_income_change": -568.5524660509858, "relative_household_income_change": -3.5e-9, "population": 129523.3537724613 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1078.0, + "average_household_income_change_upper": 1467.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000541", "constituency_name": "Constituency 541", - "x": 13, - "y": 17, + "x": 20, + "y": 13, "average_household_income_change": 1272.6941414223477, "relative_household_income_change": -0.0, "population": 57640.64659864336 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -886.0, + "average_household_income_change_upper": -649.0, + "relative_household_income_change_lower": 0.2849, + "relative_household_income_change_upper": 0.3865, "constituency_code": "E14000000542", "constituency_name": "Constituency 542", - "x": 14, - "y": 17, + "x": 21, + "y": 13, "average_household_income_change": -767.5057915657742, "relative_household_income_change": 0.3357304975304993, "population": 115692.15832822133 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 56.0, + "average_household_income_change_upper": 84.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000543", "constituency_name": "Constituency 543", - "x": 15, - "y": 17, + "x": 22, + "y": 13, "average_household_income_change": 70.06268109612046, "relative_household_income_change": 0.0, "population": 87007.97793879958 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1668.0, + "average_household_income_change_upper": 2265.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000544", "constituency_name": "Constituency 544", - "x": 16, - "y": 17, + "x": 23, + "y": 13, "average_household_income_change": 1966.6092641458092, "relative_household_income_change": 0.0, "population": 114343.38680480534 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": -407.0, + "average_household_income_change_upper": -295.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000545", "constituency_name": "Constituency 545", - "x": 17, - "y": 17, + "x": 24, + "y": 13, "average_household_income_change": -350.98957610023353, "relative_household_income_change": 1e-12, "population": 121673.71687105054 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 239.0, + "average_household_income_change_upper": 331.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000546", "constituency_name": "Constituency 546", - "x": 18, - "y": 17, + "x": 25, + "y": 13, "average_household_income_change": 284.78850562685795, "relative_household_income_change": -3.5e-9, "population": 90107.91467113272 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 456.0, + "average_household_income_change_upper": 625.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000547", "constituency_name": "Constituency 547", - "x": null, - "y": null, + "x": 26, + "y": 13, "average_household_income_change": 540.7926305781476, "relative_household_income_change": -0.0, "population": 77857.17106791587 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1333.0, + "average_household_income_change_upper": 1812.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000548", "constituency_name": "Constituency 548", - "x": 20, - "y": 17, + "x": 27, + "y": 13, "average_household_income_change": 1572.495720645288, "relative_household_income_change": 1e-12, "population": 63776.77103353226 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 665.0, + "average_household_income_change_upper": 908.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000549", "constituency_name": "Constituency 549", - "x": 21, - "y": 17, + "x": 28, + "y": 13, "average_household_income_change": 786.1815131891445, "relative_household_income_change": 0.0, "population": 72317.31785925994 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 422.0, + "average_household_income_change_upper": 580.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000550", "constituency_name": "Constituency 550", - "x": 22, - "y": 17, + "x": 29, + "y": 13, "average_household_income_change": 501.0373161137469, "relative_household_income_change": -3.5e-9, "population": 51968.97767258395 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1007.0, + "average_household_income_change_upper": -738.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000551", "constituency_name": "Constituency 551", - "x": 23, - "y": 17, + "x": 30, + "y": 13, "average_household_income_change": -872.3149541947821, "relative_household_income_change": 0.0, "population": 103860.54079116536 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1993.0, + "average_household_income_change_upper": -1467.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000552", "constituency_name": "Constituency 552", - "x": 24, - "y": 17, + "x": 31, + "y": 13, "average_household_income_change": -1729.9601043319988, "relative_household_income_change": 0.0, "population": 144540.067456093 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1361.0, + "average_household_income_change_upper": -1000.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000553", "constituency_name": "Constituency 553", - "x": 25, - "y": 17, + "x": 32, + "y": 13, "average_household_income_change": -1180.1590196030402, "relative_household_income_change": 1e-12, "population": 66543.61008387458 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": 46.0, + "average_household_income_change_upper": 71.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000554", "constituency_name": "Constituency 554", - "x": null, - "y": null, + "x": 33, + "y": 13, "average_household_income_change": 58.6742524695163, "relative_household_income_change": 1e-12, "population": 141632.26250944004 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1589.0, + "average_household_income_change_upper": -1169.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000555", "constituency_name": "Constituency 555", - "x": 27, - "y": 17, + "x": 34, + "y": 13, "average_household_income_change": -1379.002800676671, "relative_household_income_change": 1e-12, "population": 65107.374171665964 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1769.0, + "average_household_income_change_upper": -1301.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000556", "constituency_name": "Constituency 556", - "x": 28, - "y": 17, + "x": 35, + "y": 13, "average_household_income_change": -1534.8529282878776, "relative_household_income_change": -3.5e-9, "population": 98585.83289728437 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1012.0, + "average_household_income_change_upper": 1378.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000557", "constituency_name": "Constituency 557", - "x": 29, - "y": 17, + "x": 36, + "y": 13, "average_household_income_change": 1195.252276686837, "relative_household_income_change": 0.0, "population": 121134.06333908037 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -679.0, + "average_household_income_change_upper": -496.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000558", "constituency_name": "Constituency 558", - "x": 30, - "y": 17, + "x": 37, + "y": 13, "average_household_income_change": -587.1983257619266, "relative_household_income_change": 1e-12, "population": 56035.946122824156 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1533.0, + "average_household_income_change_upper": -1127.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000559", "constituency_name": "Constituency 559", - "x": 0, - "y": 18, + "x": 38, + "y": 13, "average_household_income_change": -1329.7265899480517, "relative_household_income_change": 0.0, "population": 75557.55189169839 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1447.0, + "average_household_income_change_upper": -1064.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000560", "constituency_name": "Constituency 560", - "x": 1, - "y": 18, + "x": 39, + "y": 13, "average_household_income_change": -1255.3949599405319, "relative_household_income_change": 1e-12, "population": 94964.38366509751 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1571.0, + "average_household_income_change_upper": 2134.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000561", "constituency_name": "Constituency 561", - "x": null, - "y": null, + "x": 0, + "y": 14, "average_household_income_change": 1852.312025967675, "relative_household_income_change": 0.0, "population": 124320.79269576802 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1031.0, + "average_household_income_change_upper": 1403.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000562", "constituency_name": "Constituency 562", - "x": 3, - "y": 18, + "x": 1, + "y": 14, "average_household_income_change": 1216.5399142250092, "relative_household_income_change": -3.5e-9, "population": 72214.34664091107 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": 792.0, + "average_household_income_change_upper": 1080.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000563", "constituency_name": "Constituency 563", - "x": 4, - "y": 18, + "x": 2, + "y": 14, "average_household_income_change": 936.0199128578968, "relative_household_income_change": -0.0, "population": 52121.195242426424 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 388.0, + "average_household_income_change_upper": 533.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000564", "constituency_name": "Constituency 564", - "x": 5, - "y": 18, + "x": 3, + "y": 14, "average_household_income_change": 460.4087216784598, "relative_household_income_change": 0.0, "population": 132579.04007382633 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1416.0, + "average_household_income_change_upper": -1040.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000565", "constituency_name": "Constituency 565", - "x": 6, - "y": 18, + "x": 4, + "y": 14, "average_household_income_change": -1228.017075495524, "relative_household_income_change": 1e-12, "population": 127756.68581745084 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 837.0, + "average_household_income_change_upper": 1141.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000566", "constituency_name": "Constituency 566", - "x": 7, - "y": 18, + "x": 5, + "y": 14, "average_household_income_change": 989.0043124308359, "relative_household_income_change": 1e-12, "population": 96691.3995080644 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 535.0, + "average_household_income_change_upper": 732.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000567", "constituency_name": "Constituency 567", - "x": 8, - "y": 18, + "x": 6, + "y": 14, "average_household_income_change": 633.2752797320067, "relative_household_income_change": -3.5e-9, "population": 105847.73106323073 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1304.0, + "average_household_income_change_upper": 1772.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000568", "constituency_name": "Constituency 568", - "x": null, - "y": null, + "x": 7, + "y": 14, "average_household_income_change": 1537.6835760239028, "relative_household_income_change": -0.0, "population": 59574.52355411442 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 477.0, + "average_household_income_change_upper": 653.0, + "relative_household_income_change_lower": 0.3686, + "relative_household_income_change_upper": 0.4998, "constituency_code": "E14000000569", "constituency_name": "Constituency 569", - "x": 10, - "y": 18, + "x": 8, + "y": 14, "average_household_income_change": 564.9755937017145, "relative_household_income_change": 0.4342081333144031, "population": 122732.6148148665 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1612.0, + "average_household_income_change_upper": 2190.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000570", "constituency_name": "Constituency 570", - "x": 11, - "y": 18, + "x": 9, + "y": 14, "average_household_income_change": 1901.1059243448528, "relative_household_income_change": -3.5e-9, "population": 86291.08878565823 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1397.0, + "average_household_income_change_upper": 1898.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000571", "constituency_name": "Constituency 571", - "x": 12, - "y": 18, + "x": 10, + "y": 14, "average_household_income_change": 1647.0976068910384, "relative_household_income_change": 0.0, "population": 83118.92406031303 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": 777.0, + "average_household_income_change_upper": 1059.0, + "relative_household_income_change_lower": 0.6066, + "relative_household_income_change_upper": 0.8217, "constituency_code": "E14000000572", "constituency_name": "Constituency 572", - "x": 13, - "y": 18, + "x": 11, + "y": 14, "average_household_income_change": 917.6942423765499, "relative_household_income_change": 0.7141296082160444, "population": 83980.99861545017 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -918.0, + "average_household_income_change_upper": -672.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000573", "constituency_name": "Constituency 573", - "x": 14, - "y": 18, + "x": 12, + "y": 14, "average_household_income_change": -794.8516659664629, "relative_household_income_change": -0.0, "population": 116611.44894635049 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 659.0, + "average_household_income_change_upper": 900.0, + "relative_household_income_change_lower": 0.813, + "relative_household_income_change_upper": 1.101, "constituency_code": "E14000000574", "constituency_name": "Constituency 574", - "x": 15, - "y": 18, + "x": 13, + "y": 14, "average_household_income_change": 779.5916049469769, "relative_household_income_change": 0.9569943470482749, "population": 56838.49468248409 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1401.0, + "average_household_income_change_upper": 1904.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000575", "constituency_name": "Constituency 575", - "x": null, - "y": null, + "x": 14, + "y": 14, "average_household_income_change": 1652.578569337204, "relative_household_income_change": -0.0, "population": 104940.63353614656 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 258.0, + "average_household_income_change_upper": 357.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000576", "constituency_name": "Constituency 576", - "x": 17, - "y": 18, + "x": 15, + "y": 14, "average_household_income_change": 307.4118121606677, "relative_household_income_change": 1e-12, "population": 126993.11969852142 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 627.0, + "average_household_income_change_upper": 856.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000577", "constituency_name": "Constituency 577", - "x": 18, - "y": 18, + "x": 16, + "y": 14, "average_household_income_change": 741.5070307134765, "relative_household_income_change": 1e-12, "population": 119936.8884747448 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -340.0, + "average_household_income_change_upper": -246.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000578", "constituency_name": "Constituency 578", - "x": 19, - "y": 18, + "x": 17, + "y": 14, "average_household_income_change": -293.01348432114384, "relative_household_income_change": -0.0, "population": 139054.8255490753 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 959.0, + "average_household_income_change_upper": 1305.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000579", "constituency_name": "Constituency 579", - "x": 20, - "y": 18, + "x": 18, + "y": 14, "average_household_income_change": 1131.8770630588108, "relative_household_income_change": 0.0, "population": 72826.75061051587 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -729.0, + "average_household_income_change_upper": -533.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000580", "constituency_name": "Constituency 580", - "x": 21, - "y": 18, + "x": 19, + "y": 14, "average_household_income_change": -630.9564099040315, "relative_household_income_change": -3.5e-9, "population": 56888.615982387026 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": 1318.0, + "average_household_income_change_upper": 1791.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000581", "constituency_name": "Constituency 581", - "x": 22, - "y": 18, + "x": 20, + "y": 14, "average_household_income_change": 1554.3278310363116, "relative_household_income_change": 0.0, "population": 145841.03237646338 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 813.0, + "average_household_income_change_upper": 1108.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000582", "constituency_name": "Constituency 582", - "x": null, - "y": null, + "x": 21, + "y": 14, "average_household_income_change": 960.0847099843812, "relative_household_income_change": -0.0, "population": 137570.1463791927 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 696.0, + "average_household_income_change_upper": 950.0, + "relative_household_income_change_lower": 0.7327, + "relative_household_income_change_upper": 0.9924, "constituency_code": "E14000000583", "constituency_name": "Constituency 583", - "x": 24, - "y": 18, + "x": 22, + "y": 14, "average_household_income_change": 823.4577882062744, "relative_household_income_change": 0.8625367572015296, "population": 130636.04667489542 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -84.0, + "average_household_income_change_upper": -56.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000584", "constituency_name": "Constituency 584", - "x": 25, - "y": 18, + "x": 23, + "y": 14, "average_household_income_change": -70.09732998103146, "relative_household_income_change": 0.0, "population": 70802.83526568713 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1350.0, + "average_household_income_change_upper": 1835.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000585", "constituency_name": "Constituency 585", - "x": 26, - "y": 18, + "x": 24, + "y": 14, "average_household_income_change": 1592.447556354229, "relative_household_income_change": 1e-12, "population": 60038.29592953278 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1324.0, + "average_household_income_change_upper": 1799.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000586", "constituency_name": "Constituency 586", - "x": 27, - "y": 18, + "x": 25, + "y": 14, "average_household_income_change": 1561.290651214074, "relative_household_income_change": 0.0, "population": 123015.32138698698 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 75.0, + "average_household_income_change_upper": 110.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000587", "constituency_name": "Constituency 587", - "x": 28, - "y": 18, + "x": 26, + "y": 14, "average_household_income_change": 92.60827995758403, "relative_household_income_change": -3.5e-9, "population": 74372.69820872009 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1999.0, + "average_household_income_change_upper": -1471.0, + "relative_household_income_change_lower": 0.735, + "relative_household_income_change_upper": 0.9955, "constituency_code": "E14000000588", "constituency_name": "Constituency 588", - "x": 29, - "y": 18, + "x": 27, + "y": 14, "average_household_income_change": -1735.1883462164376, "relative_household_income_change": 0.8652316608891197, "population": 107990.85608582196 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -845.0, + "average_household_income_change_upper": -619.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000589", "constituency_name": "Constituency 589", - "x": null, - "y": null, + "x": 28, + "y": 14, "average_household_income_change": -731.794768168398, "relative_household_income_change": -0.0, "population": 133607.86126488214 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": 952.0, + "average_household_income_change_upper": 1296.0, + "relative_household_income_change_lower": 0.8439, + "relative_household_income_change_upper": 1.1428, "constituency_code": "E14000000590", "constituency_name": "Constituency 590", - "x": 0, - "y": 19, + "x": 29, + "y": 14, "average_household_income_change": 1124.1223787780555, "relative_household_income_change": 0.9933078591651776, "population": 55151.75031185687 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -929.0, + "average_household_income_change_upper": -681.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000591", "constituency_name": "Constituency 591", - "x": 1, - "y": 19, + "x": 30, + "y": 14, "average_household_income_change": -804.9034884896406, "relative_household_income_change": 0.0, "population": 132303.99221559628 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -309.0, + "average_household_income_change_upper": -222.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000592", "constituency_name": "Constituency 592", - "x": 2, - "y": 19, + "x": 31, + "y": 14, "average_household_income_change": -265.5169125780508, "relative_household_income_change": -3.5e-9, "population": 53366.22724187432 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -2259.0, + "average_household_income_change_upper": -1664.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000593", "constituency_name": "Constituency 593", - "x": 3, - "y": 19, + "x": 32, + "y": 14, "average_household_income_change": -1961.2404528225684, "relative_household_income_change": 1e-12, "population": 97782.92636483927 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 403.0, + "average_household_income_change_upper": 553.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000594", "constituency_name": "Constituency 594", - "x": 4, - "y": 19, + "x": 33, + "y": 14, "average_household_income_change": 477.65139708514994, "relative_household_income_change": 1e-12, "population": 84078.00961891914 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -632.0, + "average_household_income_change_upper": -461.0, + "relative_household_income_change_lower": 0.2873, + "relative_household_income_change_upper": 0.3898, "constituency_code": "E14000000595", "constituency_name": "Constituency 595", - "x": 5, - "y": 19, + "x": 34, + "y": 14, "average_household_income_change": -546.6949474395025, "relative_household_income_change": 0.3385683294268179, "population": 76236.94173217926 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1401.0, + "average_household_income_change_upper": 1904.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000596", "constituency_name": "Constituency 596", - "x": null, - "y": null, + "x": 35, + "y": 14, "average_household_income_change": 1652.2575803141276, "relative_household_income_change": -0.0, "population": 89450.32745730813 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -2046.0, + "average_household_income_change_upper": -1506.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000597", "constituency_name": "Constituency 597", - "x": 7, - "y": 19, + "x": 36, + "y": 14, "average_household_income_change": -1775.7536371573299, "relative_household_income_change": 0.0, "population": 117045.28244465016 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 648.0, + "average_household_income_change_upper": 885.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000598", "constituency_name": "Constituency 598", - "x": 8, - "y": 19, + "x": 37, + "y": 14, "average_household_income_change": 766.7318410506416, "relative_household_income_change": 0.0, "population": 88213.62626352572 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": 1297.0, + "average_household_income_change_upper": 1764.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000599", "constituency_name": "Constituency 599", - "x": 9, - "y": 19, + "x": 38, + "y": 14, "average_household_income_change": 1530.454228643761, "relative_household_income_change": -0.0, "population": 138297.81002117688 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1497.0, + "average_household_income_change_upper": 2034.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000600", "constituency_name": "Constituency 600", - "x": 10, - "y": 19, + "x": 39, + "y": 14, "average_household_income_change": 1765.2977730020027, "relative_household_income_change": 0.0, "population": 139824.0752634297 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1036.0, + "average_household_income_change_upper": 1410.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000601", "constituency_name": "Constituency 601", - "x": 11, - "y": 19, + "x": 0, + "y": 15, "average_household_income_change": 1223.2611077151216, "relative_household_income_change": 1e-12, "population": 113591.50698099248 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 322.0, + "average_household_income_change_upper": 444.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000602", "constituency_name": "Constituency 602", - "x": 12, - "y": 19, + "x": 1, + "y": 15, "average_household_income_change": 382.6683234379353, "relative_household_income_change": 0.0, "population": 141310.5086029322 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 724.0, + "average_household_income_change_upper": 988.0, + "relative_household_income_change_lower": 0.6482, + "relative_household_income_change_upper": 0.878, "constituency_code": "E14000000603", "constituency_name": "Constituency 603", - "x": null, - "y": null, + "x": 2, + "y": 15, "average_household_income_change": 856.1768560114076, "relative_household_income_change": 0.7630627694108344, "population": 111736.58376417658 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -445.0, + "average_household_income_change_upper": -323.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000604", "constituency_name": "Constituency 604", - "x": 14, - "y": 19, + "x": 3, + "y": 15, "average_household_income_change": -383.73355517201844, "relative_household_income_change": 0.0, "population": 74431.454997639 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1007.0, + "average_household_income_change_upper": 1371.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000605", "constituency_name": "Constituency 605", - "x": 15, - "y": 19, + "x": 4, + "y": 15, "average_household_income_change": 1189.128223761453, "relative_household_income_change": 0.0, "population": 96831.1726712148 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1627.0, + "average_household_income_change_upper": 2209.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000606", "constituency_name": "Constituency 606", - "x": 16, - "y": 19, + "x": 5, + "y": 15, "average_household_income_change": 1918.0756490163558, "relative_household_income_change": -0.0, "population": 141947.63285895935 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -415.0, + "average_household_income_change_upper": -301.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000607", "constituency_name": "Constituency 607", - "x": 17, - "y": 19, + "x": 6, + "y": 15, "average_household_income_change": -357.7091821516629, "relative_household_income_change": 0.0, "population": 104614.10256123879 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": 531.0, + "average_household_income_change_upper": 726.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000608", "constituency_name": "Constituency 608", - "x": 18, - "y": 19, + "x": 7, + "y": 15, "average_household_income_change": 628.4179318357687, "relative_household_income_change": 1e-12, "population": 103755.05655807689 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1440.0, + "average_household_income_change_upper": -1058.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000609", "constituency_name": "Constituency 609", - "x": 19, - "y": 19, + "x": 8, + "y": 15, "average_household_income_change": -1248.9217949583033, "relative_household_income_change": -0.0, "population": 147521.3750362315 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1825.0, + "average_household_income_change_upper": -1343.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000610", "constituency_name": "Constituency 610", - "x": null, - "y": null, + "x": 9, + "y": 15, "average_household_income_change": -1583.7983552457956, "relative_household_income_change": 0.0, "population": 51688.1449805309 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1125.0, + "average_household_income_change_upper": 1530.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000611", "constituency_name": "Constituency 611", - "x": 21, - "y": 19, + "x": 10, + "y": 15, "average_household_income_change": 1327.7323629112625, "relative_household_income_change": -0.0, "population": 103884.21189524661 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1674.0, + "average_household_income_change_upper": 2273.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000612", "constituency_name": "Constituency 612", - "x": 22, - "y": 19, + "x": 11, + "y": 15, "average_household_income_change": 1973.251067041317, "relative_household_income_change": 1e-12, "population": 83744.23359295663 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 67.0, + "average_household_income_change_upper": 99.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000613", "constituency_name": "Constituency 613", - "x": 23, - "y": 19, + "x": 12, + "y": 15, "average_household_income_change": 83.21324225082982, "relative_household_income_change": -0.0, "population": 68368.57302030973 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -458.0, + "average_household_income_change_upper": -332.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000614", "constituency_name": "Constituency 614", - "x": 24, - "y": 19, + "x": 13, + "y": 15, "average_household_income_change": -395.21045059080564, "relative_household_income_change": 0.0, "population": 80043.8086664578 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1108.0, + "average_household_income_change_upper": 1507.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000615", "constituency_name": "Constituency 615", - "x": 25, - "y": 19, + "x": 14, + "y": 15, "average_household_income_change": 1307.3369463042873, "relative_household_income_change": -0.0, "population": 105144.40885855842 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1479.0, + "average_household_income_change_upper": -1087.0, + "relative_household_income_change_lower": 0.3606, + "relative_household_income_change_upper": 0.489, "constituency_code": "E14000000616", "constituency_name": "Constituency 616", - "x": 26, - "y": 19, + "x": 15, + "y": 15, "average_household_income_change": -1282.621906237099, "relative_household_income_change": 0.4248049166319652, "population": 128939.8907021561 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": 807.0, + "average_household_income_change_upper": 1100.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000617", "constituency_name": "Constituency 617", - "x": null, - "y": null, + "x": 16, + "y": 15, "average_household_income_change": 953.4736754873703, "relative_household_income_change": 0.0, "population": 103767.56011373061 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1073.0, + "average_household_income_change_upper": -787.0, + "relative_household_income_change_lower": 0.5754, + "relative_household_income_change_upper": 0.7795, "constituency_code": "E14000000618", "constituency_name": "Constituency 618", - "x": 28, - "y": 19, + "x": 17, + "y": 15, "average_household_income_change": -929.6915636162972, "relative_household_income_change": 0.6774768027545954, "population": 149677.9304957911 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 652.0, + "average_household_income_change_upper": 891.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000619", "constituency_name": "Constituency 619", - "x": 29, - "y": 19, + "x": 18, + "y": 15, "average_household_income_change": 771.5763025685698, "relative_household_income_change": 0.0, "population": 77227.88788830965 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -885.0, + "average_household_income_change_upper": -648.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000620", "constituency_name": "Constituency 620", - "x": 30, - "y": 19, + "x": 19, + "y": 15, "average_household_income_change": -766.5509814539178, "relative_household_income_change": -3.5e-9, "population": 82122.3677446993 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -869.0, + "average_household_income_change_upper": -637.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000621", "constituency_name": "Constituency 621", - "x": 0, - "y": 20, + "x": 20, + "y": 15, "average_household_income_change": -752.9484879757442, "relative_household_income_change": -3.5e-9, "population": 76081.76656371151 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1036.0, + "average_household_income_change_upper": 1410.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000622", "constituency_name": "Constituency 622", - "x": 1, - "y": 20, + "x": 21, + "y": 15, "average_household_income_change": 1222.9442365982281, "relative_household_income_change": 0.0, "population": 120679.12954257091 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1651.0, + "average_household_income_change_upper": -1214.0, + "relative_household_income_change_lower": 0.7811, + "relative_household_income_change_upper": 1.0579, "constituency_code": "E14000000623", "constituency_name": "Constituency 623", - "x": 2, - "y": 20, + "x": 22, + "y": 15, "average_household_income_change": -1432.8521114865923, "relative_household_income_change": 0.9195260235316269, "population": 119371.17541933047 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 451.0, + "average_household_income_change_upper": 619.0, + "relative_household_income_change_lower": 0.2833, + "relative_household_income_change_upper": 0.3843, "constituency_code": "E14000000624", "constituency_name": "Constituency 624", - "x": null, - "y": null, + "x": 23, + "y": 15, "average_household_income_change": 534.9241254942352, "relative_household_income_change": 0.3338237028975374, "population": 60955.649829977745 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1564.0, + "average_household_income_change_upper": 2124.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000625", "constituency_name": "Constituency 625", - "x": 4, - "y": 20, + "x": 24, + "y": 15, "average_household_income_change": 1843.912890268073, "relative_household_income_change": 1e-12, "population": 129358.11465348065 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": 312.0, + "average_household_income_change_upper": 431.0, + "relative_household_income_change_lower": 0.1579, + "relative_household_income_change_upper": 0.2146, "constituency_code": "E14000000626", "constituency_name": "Constituency 626", - "x": 5, - "y": 20, + "x": 25, + "y": 15, "average_household_income_change": 371.6653569909436, "relative_household_income_change": 0.18625157984189045, "population": 55491.321063149466 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -380.0, + "average_household_income_change_upper": -275.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000627", "constituency_name": "Constituency 627", - "x": 6, - "y": 20, + "x": 26, + "y": 15, "average_household_income_change": -327.3032084220029, "relative_household_income_change": 1e-12, "population": 105868.16394036285 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1721.0, + "average_household_income_change_upper": -1266.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000628", "constituency_name": "Constituency 628", - "x": 7, - "y": 20, + "x": 27, + "y": 15, "average_household_income_change": -1493.6082836546789, "relative_household_income_change": 1e-12, "population": 92021.95979984169 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1958.0, + "average_household_income_change_upper": -1441.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000629", "constituency_name": "Constituency 629", - "x": 8, - "y": 20, + "x": 28, + "y": 15, "average_household_income_change": -1699.9458449766842, "relative_household_income_change": -0.0, "population": 122067.3726304384 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -522.0, + "average_household_income_change_upper": -380.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000630", "constituency_name": "Constituency 630", - "x": 9, - "y": 20, + "x": 29, + "y": 15, "average_household_income_change": -450.5896596519281, "relative_household_income_change": 1e-12, "population": 52936.33348045289 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1588.0, + "average_household_income_change_upper": -1168.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000631", "constituency_name": "Constituency 631", - "x": null, - "y": null, + "x": 30, + "y": 15, "average_household_income_change": -1377.8764440953496, "relative_household_income_change": 1e-12, "population": 123121.2733392203 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1212.0, + "average_household_income_change_upper": -890.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000632", "constituency_name": "Constituency 632", - "x": 11, - "y": 20, + "x": 31, + "y": 15, "average_household_income_change": -1051.2636353189384, "relative_household_income_change": 0.0, "population": 96399.63093497188 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 9.0, + "average_household_income_change_upper": 20.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000633", "constituency_name": "Constituency 633", - "x": 12, - "y": 20, + "x": 32, + "y": 15, "average_household_income_change": 14.147980833502327, "relative_household_income_change": -0.0, "population": 90394.5248879687 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -2117.0, + "average_household_income_change_upper": -1559.0, + "relative_household_income_change_lower": 0.7402, + "relative_household_income_change_upper": 1.0024, "constituency_code": "E14000000634", "constituency_name": "Constituency 634", - "x": 13, - "y": 20, + "x": 33, + "y": 15, "average_household_income_change": -1838.0730523928687, "relative_household_income_change": 0.8712942895857928, "population": 60641.30386365898 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": -104.0, + "average_household_income_change_upper": -71.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000635", "constituency_name": "Constituency 635", - "x": 14, - "y": 20, + "x": 34, + "y": 15, "average_household_income_change": -87.23716684922378, "relative_household_income_change": 0.0, "population": 104747.24642102896 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1645.0, + "average_household_income_change_upper": 2234.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000636", "constituency_name": "Constituency 636", - "x": 15, - "y": 20, + "x": 35, + "y": 15, "average_household_income_change": 1939.336244729525, "relative_household_income_change": 0.0, "population": 127050.64843988064 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 734.0, + "average_household_income_change_upper": 1002.0, + "relative_household_income_change_lower": 0.8389, + "relative_household_income_change_upper": 1.1361, "constituency_code": "E14000000637", "constituency_name": "Constituency 637", - "x": 16, - "y": 20, + "x": 36, + "y": 15, "average_household_income_change": 868.1707597779589, "relative_household_income_change": 0.987503057055717, "population": 129088.10024620766 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -2058.0, + "average_household_income_change_upper": -1515.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000638", "constituency_name": "Constituency 638", - "x": null, - "y": null, + "x": 37, + "y": 15, "average_household_income_change": -1786.8649278672845, "relative_household_income_change": -0.0, "population": 123939.15459225708 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -221.0, + "average_household_income_change_upper": -157.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000639", "constituency_name": "Constituency 639", - "x": 18, - "y": 20, + "x": 38, + "y": 15, "average_household_income_change": -189.309168849606, "relative_household_income_change": -0.0, "population": 120874.07398615906 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1352.0, + "average_household_income_change_upper": 1838.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000640", "constituency_name": "Constituency 640", - "x": 19, - "y": 20, + "x": 39, + "y": 15, "average_household_income_change": 1594.94324793443, "relative_household_income_change": -0.0, "population": 74818.70120486079 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 334.0, + "average_household_income_change_upper": 460.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000641", "constituency_name": "Constituency 641", - "x": 20, - "y": 20, + "x": 0, + "y": 16, "average_household_income_change": 396.5805294054912, "relative_household_income_change": -3.5e-9, "population": 107085.6435479035 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -2291.0, + "average_household_income_change_upper": -1687.0, + "relative_household_income_change_lower": 0.6342, + "relative_household_income_change_upper": 0.8591, "constituency_code": "E14000000642", "constituency_name": "Constituency 642", - "x": 21, - "y": 20, + "x": 1, + "y": 16, "average_household_income_change": -1988.8676478597636, "relative_household_income_change": 0.7466795414572786, "population": 68794.36517222921 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1632.0, + "average_household_income_change_upper": -1200.0, + "relative_household_income_change_lower": 0.4116, + "relative_household_income_change_upper": 0.558, "constituency_code": "E14000000643", "constituency_name": "Constituency 643", - "x": 22, - "y": 20, + "x": 2, + "y": 16, "average_household_income_change": -1416.3933519071054, "relative_household_income_change": 0.4848194651534483, "population": 60473.494553043936 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": 1058.0, + "average_household_income_change_upper": 1440.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000644", "constituency_name": "Constituency 644", - "x": 23, - "y": 20, + "x": 3, + "y": 16, "average_household_income_change": 1249.393074236446, "relative_household_income_change": -3.5e-9, "population": 123993.994089221 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 886.0, + "average_household_income_change_upper": 1207.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000645", "constituency_name": "Constituency 645", - "x": null, - "y": null, + "x": 4, + "y": 16, "average_household_income_change": 1046.8309597875534, "relative_household_income_change": -3.5e-9, "population": 82589.20612888796 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 899.0, + "average_household_income_change_upper": 1225.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000646", "constituency_name": "Constituency 646", - "x": 25, - "y": 20, + "x": 5, + "y": 16, "average_household_income_change": 1062.21099433036, "relative_household_income_change": 1e-12, "population": 123517.19941423072 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -364.0, + "average_household_income_change_upper": -263.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000647", "constituency_name": "Constituency 647", - "x": 26, - "y": 20, + "x": 6, + "y": 16, "average_household_income_change": -313.8369092416631, "relative_household_income_change": -3.5e-9, "population": 144734.81087895617 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1407.0, + "average_household_income_change_upper": 1911.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000648", "constituency_name": "Constituency 648", - "x": 27, - "y": 20, + "x": 7, + "y": 16, "average_household_income_change": 1658.9417288888621, "relative_household_income_change": 0.0, "population": 54363.82273350112 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 376.0, + "average_household_income_change_upper": 518.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "constituency_code": "E14000000649", "constituency_name": "Constituency 649", - "x": 28, - "y": 20, + "x": 8, + "y": 16, "average_household_income_change": 446.986217100954, "relative_household_income_change": 1e-12, "population": 129264.05146024606 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 267.0, + "average_household_income_change_upper": 369.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "constituency_code": "E14000000650", "constituency_name": "Constituency 650", - "x": 29, - "y": 20, + "x": 9, + "y": 16, "average_household_income_change": 317.6664618952065, "relative_household_income_change": -3.5e-9, "population": 56840.72937490232 @@ -6221,15 +9471,25 @@ ], "local_authority_impact": [ { + "disclosure_tier": "reported", + "average_household_income_change_lower": 395.0, + "average_household_income_change_upper": 542.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000001", "local_authority_name": "Local Authority 1", - "x": null, - "y": null, + "x": 0, + "y": 0, "average_household_income_change": 468.5659066798089, "relative_household_income_change": -3.5e-9, "population": 100206.37490705009 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -83.0, + "average_household_income_change_upper": -55.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "local_authority_code": "E06000000002", "local_authority_name": "Local Authority 2", "x": 1, @@ -6239,6 +9499,11 @@ "population": 123384.01709097778 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 772.0, + "average_household_income_change_upper": 1052.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000003", "local_authority_name": "Local Authority 3", "x": 2, @@ -6248,6 +9513,11 @@ "population": 141131.81544042542 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1620.0, + "average_household_income_change_upper": 2200.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000004", "local_authority_name": "Local Authority 4", "x": 3, @@ -6257,6 +9527,11 @@ "population": 76099.80320995662 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": 821.0, + "average_household_income_change_upper": 1119.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "local_authority_code": "E06000000005", "local_authority_name": "Local Authority 5", "x": 4, @@ -6266,6 +9541,11 @@ "population": 72911.01548143946 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1392.0, + "average_household_income_change_upper": -1023.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "local_authority_code": "E06000000006", "local_authority_name": "Local Authority 6", "x": 5, @@ -6275,6 +9555,11 @@ "population": 100754.01422780073 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 496.0, + "average_household_income_change_upper": 680.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000007", "local_authority_name": "Local Authority 7", "x": 6, @@ -6284,15 +9569,25 @@ "population": 148197.15018666055 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -2050.0, + "average_household_income_change_upper": -1509.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000008", "local_authority_name": "Local Authority 8", - "x": null, - "y": null, + "x": 7, + "y": 0, "average_household_income_change": -1779.658218255996, "relative_household_income_change": 0.0, "population": 128556.48672377989 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 177.0, + "average_household_income_change_upper": 247.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000009", "local_authority_name": "Local Authority 9", "x": 8, @@ -6302,6 +9597,11 @@ "population": 115700.32594875956 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1589.0, + "average_household_income_change_upper": -1169.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000010", "local_authority_name": "Local Authority 10", "x": 9, @@ -6311,6 +9611,11 @@ "population": 73114.63274971377 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -720.0, + "average_household_income_change_upper": -526.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000011", "local_authority_name": "Local Authority 11", "x": 10, @@ -6320,6 +9625,11 @@ "population": 139342.8006351117 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1938.0, + "average_household_income_change_upper": -1427.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000012", "local_authority_name": "Local Authority 12", "x": 11, @@ -6329,6 +9639,11 @@ "population": 132067.73320383328 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -2066.0, + "average_household_income_change_upper": -1521.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000013", "local_authority_name": "Local Authority 13", "x": 12, @@ -6338,6 +9653,11 @@ "population": 104826.38130177911 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": -1121.0, + "average_household_income_change_upper": -823.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000014", "local_authority_name": "Local Authority 14", "x": 13, @@ -6347,15 +9667,25 @@ "population": 64127.86306468177 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1431.0, + "average_household_income_change_upper": 1944.0, + "relative_household_income_change_lower": 0.1688, + "relative_household_income_change_upper": 0.2295, "local_authority_code": "E06000000015", "local_authority_name": "Local Authority 15", - "x": null, - "y": null, + "x": 14, + "y": 0, "average_household_income_change": 1687.1904190190778, "relative_household_income_change": 0.19915732727299662, "population": 82930.81346214596 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -623.0, + "average_household_income_change_upper": -454.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000016", "local_authority_name": "Local Authority 16", "x": 15, @@ -6365,6 +9695,11 @@ "population": 102310.46935923983 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1480.0, + "average_household_income_change_upper": 2011.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000017", "local_authority_name": "Local Authority 17", "x": 16, @@ -6374,6 +9709,11 @@ "population": 110324.97681835851 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1859.0, + "average_household_income_change_upper": -1368.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000018", "local_authority_name": "Local Authority 18", "x": 17, @@ -6383,6 +9723,11 @@ "population": 88984.89875920078 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1947.0, + "average_household_income_change_upper": -1433.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000019", "local_authority_name": "Local Authority 19", "x": 18, @@ -6392,6 +9737,11 @@ "population": 72890.3783981163 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -185.0, + "average_household_income_change_upper": -131.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "local_authority_code": "E06000000020", "local_authority_name": "Local Authority 20", "x": 19, @@ -6401,6 +9751,11 @@ "population": 73478.18403793292 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 906.0, + "average_household_income_change_upper": 1234.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000021", "local_authority_name": "Local Authority 21", "x": 20, @@ -6410,15 +9765,25 @@ "population": 98666.90369402937 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1250.0, + "average_household_income_change_upper": -918.0, + "relative_household_income_change_lower": 0.7107, + "relative_household_income_change_upper": 0.9625, "local_authority_code": "E06000000022", "local_authority_name": "Local Authority 22", - "x": null, - "y": null, + "x": 21, + "y": 0, "average_household_income_change": -1084.190750741544, "relative_household_income_change": 0.836601005622632, "population": 83210.36408380332 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": 883.0, + "average_household_income_change_upper": 1203.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000023", "local_authority_name": "Local Authority 23", "x": 22, @@ -6428,6 +9793,11 @@ "population": 82189.76985415467 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -414.0, + "average_household_income_change_upper": -300.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000024", "local_authority_name": "Local Authority 24", "x": 23, @@ -6437,6 +9807,11 @@ "population": 74556.76041445452 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 214.0, + "average_household_income_change_upper": 297.0, + "relative_household_income_change_lower": 0.6143, + "relative_household_income_change_upper": 0.8322, "local_authority_code": "E06000000025", "local_authority_name": "Local Authority 25", "x": 24, @@ -6446,6 +9821,11 @@ "population": 127857.36052385914 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -650.0, + "average_household_income_change_upper": -474.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "local_authority_code": "E06000000026", "local_authority_name": "Local Authority 26", "x": 25, @@ -6455,6 +9835,11 @@ "population": 106980.91731680604 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -129.0, + "average_household_income_change_upper": -89.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "local_authority_code": "E06000000027", "local_authority_name": "Local Authority 27", "x": 26, @@ -6464,6 +9849,11 @@ "population": 109578.0521407703 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1576.0, + "average_household_income_change_upper": -1159.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "local_authority_code": "E06000000028", "local_authority_name": "Local Authority 28", "x": 27, @@ -6473,15 +9863,25 @@ "population": 58898.86324268766 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 482.0, + "average_household_income_change_upper": 660.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000029", "local_authority_name": "Local Authority 29", - "x": null, - "y": null, + "x": 28, + "y": 0, "average_household_income_change": 570.918963320222, "relative_household_income_change": 0.0, "population": 125338.41108172822 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -319.0, + "average_household_income_change_upper": -230.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000030", "local_authority_name": "Local Authority 30", "x": 29, @@ -6491,6 +9891,11 @@ "population": 64611.39147086428 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 611.0, + "average_household_income_change_upper": 835.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000031", "local_authority_name": "Local Authority 31", "x": 30, @@ -6500,2962 +9905,4607 @@ "population": 110356.63768942235 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": -612.0, + "average_household_income_change_upper": -446.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000032", "local_authority_name": "Local Authority 32", - "x": 0, - "y": 1, + "x": 31, + "y": 0, "average_household_income_change": -528.8110657531159, "relative_household_income_change": -3.5e-9, "population": 105587.30047688412 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -2187.0, + "average_household_income_change_upper": -1611.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "local_authority_code": "E06000000033", "local_authority_name": "Local Authority 33", - "x": 1, - "y": 1, + "x": 32, + "y": 0, "average_household_income_change": -1899.0443795165293, "relative_household_income_change": 1e-12, "population": 52173.26085032475 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1094.0, + "average_household_income_change_upper": -803.0, + "relative_household_income_change_lower": 0.7322, + "relative_household_income_change_upper": 0.9917, "local_authority_code": "E06000000034", "local_authority_name": "Local Authority 34", - "x": 2, - "y": 1, + "x": 33, + "y": 0, "average_household_income_change": -948.6511027706763, "relative_household_income_change": 0.861974368839776, "population": 108831.07934043322 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 504.0, + "average_household_income_change_upper": 690.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000035", "local_authority_name": "Local Authority 35", - "x": 3, - "y": 1, + "x": 34, + "y": 0, "average_household_income_change": 596.6157268316401, "relative_household_income_change": 0.0, "population": 102116.27736033645 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 173.0, + "average_household_income_change_upper": 243.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000036", "local_authority_name": "Local Authority 36", - "x": null, - "y": null, + "x": 35, + "y": 0, "average_household_income_change": 207.93735297858885, "relative_household_income_change": 0.0, "population": 116564.66422229337 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -118.0, + "average_household_income_change_upper": -81.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "local_authority_code": "E06000000037", "local_authority_name": "Local Authority 37", - "x": 5, - "y": 1, + "x": 36, + "y": 0, "average_household_income_change": -99.3150549349906, "relative_household_income_change": 1e-12, "population": 101593.40434133449 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -448.0, + "average_household_income_change_upper": -325.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000038", "local_authority_name": "Local Authority 38", - "x": 6, - "y": 1, + "x": 37, + "y": 0, "average_household_income_change": -386.4531583157946, "relative_household_income_change": 0.0, "population": 141472.1770422101 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 277.0, + "average_household_income_change_upper": 383.0, + "relative_household_income_change_lower": 0.0439, + "relative_household_income_change_upper": 0.0604, "local_authority_code": "E06000000039", "local_authority_name": "Local Authority 39", - "x": 7, - "y": 1, + "x": 38, + "y": 0, "average_household_income_change": 330.0627465742383, "relative_household_income_change": 0.05215779997016934, "population": 141852.21151584186 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1307.0, + "average_household_income_change_upper": -960.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000040", "local_authority_name": "Local Authority 40", - "x": 8, - "y": 1, + "x": 39, + "y": 0, "average_household_income_change": -1133.1155149702777, "relative_household_income_change": 0.0, "population": 90600.31790542022 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": -969.0, + "average_household_income_change_upper": -710.0, + "relative_household_income_change_lower": 0.115, + "relative_household_income_change_upper": 0.1567, "local_authority_code": "E06000000041", "local_authority_name": "Local Authority 41", - "x": 9, + "x": 0, "y": 1, "average_household_income_change": -839.5358563959885, "relative_household_income_change": 0.13584478762195062, "population": 88141.137590001 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1344.0, + "average_household_income_change_upper": -987.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000042", "local_authority_name": "Local Authority 42", - "x": 10, + "x": 1, "y": 1, "average_household_income_change": -1165.481582988086, "relative_household_income_change": -3.5e-9, "population": 73433.4816768881 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -433.0, + "average_household_income_change_upper": -314.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000043", "local_authority_name": "Local Authority 43", - "x": null, - "y": null, + "x": 2, + "y": 1, "average_household_income_change": -373.5052701686232, "relative_household_income_change": -3.5e-9, "population": 79419.4013814455 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1338.0, + "average_household_income_change_upper": -983.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000044", "local_authority_name": "Local Authority 44", - "x": 12, + "x": 3, "y": 1, "average_household_income_change": -1160.1562975452566, "relative_household_income_change": -3.5e-9, "population": 85899.06902370857 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 641.0, + "average_household_income_change_upper": 876.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000045", "local_authority_name": "Local Authority 45", - "x": 13, + "x": 4, "y": 1, "average_household_income_change": 758.790098109745, "relative_household_income_change": -3.5e-9, "population": 63063.28444224117 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1188.0, + "average_household_income_change_upper": -872.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000046", "local_authority_name": "Local Authority 46", - "x": 14, + "x": 5, "y": 1, "average_household_income_change": -1029.720675973574, "relative_household_income_change": -0.0, "population": 104506.66479956872 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -597.0, + "average_household_income_change_upper": -435.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000047", "local_authority_name": "Local Authority 47", - "x": 15, + "x": 6, "y": 1, "average_household_income_change": -516.1419060292656, "relative_household_income_change": -3.5e-9, "population": 72118.73988243361 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1505.0, + "average_household_income_change_upper": -1107.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000048", "local_authority_name": "Local Authority 48", - "x": 16, + "x": 7, "y": 1, "average_household_income_change": -1305.9071114052686, "relative_household_income_change": 0.0, "population": 83866.0479801991 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 282.0, + "average_household_income_change_upper": 390.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000049", "local_authority_name": "Local Authority 49", - "x": 17, + "x": 8, "y": 1, "average_household_income_change": 336.04631080583937, "relative_household_income_change": -3.5e-9, "population": 143454.1556254162 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": -1982.0, + "average_household_income_change_upper": -1459.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000050", "local_authority_name": "Local Authority 50", - "x": null, - "y": null, + "x": 9, + "y": 1, "average_household_income_change": -1720.7042384504155, "relative_household_income_change": 0.0, "population": 60713.73636327979 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1216.0, + "average_household_income_change_upper": 1653.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000051", "local_authority_name": "Local Authority 51", - "x": 19, + "x": 10, "y": 1, "average_household_income_change": 1434.7514320345974, "relative_household_income_change": -3.5e-9, "population": 81076.07543203316 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 309.0, + "average_household_income_change_upper": 427.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000052", "local_authority_name": "Local Authority 52", - "x": 20, + "x": 11, "y": 1, "average_household_income_change": 367.94847637922425, "relative_household_income_change": 0.0, "population": 57169.51240739431 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -158.0, + "average_household_income_change_upper": -111.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000053", "local_authority_name": "Local Authority 53", - "x": 21, + "x": 12, "y": 1, "average_household_income_change": -134.27102983545325, "relative_household_income_change": -3.5e-9, "population": 112260.18240877741 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1507.0, + "average_household_income_change_upper": -1108.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "local_authority_code": "E06000000054", "local_authority_name": "Local Authority 54", - "x": 22, + "x": 13, "y": 1, "average_household_income_change": -1307.3113454330883, "relative_household_income_change": 1e-12, "population": 129712.91555041495 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1440.0, + "average_household_income_change_upper": 1956.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000055", "local_authority_name": "Local Authority 55", - "x": 23, + "x": 14, "y": 1, "average_household_income_change": 1698.0689767657648, "relative_household_income_change": 0.0, "population": 56651.85897650984 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -791.0, + "average_household_income_change_upper": -578.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000056", "local_authority_name": "Local Authority 56", - "x": 24, + "x": 15, "y": 1, "average_household_income_change": -684.5442861532538, "relative_household_income_change": 0.0, "population": 51961.63664619178 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1129.0, + "average_household_income_change_upper": -828.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000057", "local_authority_name": "Local Authority 57", - "x": null, - "y": null, + "x": 16, + "y": 1, "average_household_income_change": -978.7187202471532, "relative_household_income_change": -3.5e-9, "population": 97885.13067633384 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1502.0, + "average_household_income_change_upper": 2040.0, + "relative_household_income_change_lower": 0.3414, + "relative_household_income_change_upper": 0.463, "local_authority_code": "E06000000058", "local_authority_name": "Local Authority 58", - "x": 26, + "x": 17, "y": 1, "average_household_income_change": 1770.8198408401636, "relative_household_income_change": 0.4022130639378835, "population": 116710.80210949371 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": -265.0, + "average_household_income_change_upper": -190.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000059", "local_authority_name": "Local Authority 59", - "x": 27, + "x": 18, "y": 1, "average_household_income_change": -227.21024178206807, "relative_household_income_change": 0.0, "population": 148868.47538700586 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 342.0, + "average_household_income_change_upper": 471.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000060", "local_authority_name": "Local Authority 60", - "x": 28, + "x": 19, "y": 1, "average_household_income_change": 406.1970125350696, "relative_household_income_change": -0.0, "population": 69260.03618381429 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -90.0, + "average_household_income_change_upper": -60.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "local_authority_code": "E06000000061", "local_authority_name": "Local Authority 61", - "x": 29, + "x": 20, "y": 1, "average_household_income_change": -74.91285483834443, "relative_household_income_change": 1e-12, "population": 142780.21598839073 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1544.0, + "average_household_income_change_upper": -1135.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000062", "local_authority_name": "Local Authority 62", - "x": 30, + "x": 21, "y": 1, "average_household_income_change": -1339.6500922702558, "relative_household_income_change": -0.0, "population": 99488.94447212561 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1496.0, + "average_household_income_change_upper": -1100.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000063", "local_authority_name": "Local Authority 63", - "x": 0, - "y": 2, + "x": 22, + "y": 1, "average_household_income_change": -1298.0181141563762, "relative_household_income_change": -3.5e-9, "population": 55030.787258256365 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -66.0, + "average_household_income_change_upper": -43.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000064", "local_authority_name": "Local Authority 64", - "x": null, - "y": null, + "x": 23, + "y": 1, "average_household_income_change": -54.75236674179662, "relative_household_income_change": -0.0, "population": 138632.11137234024 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -2126.0, + "average_household_income_change_upper": -1565.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000065", "local_authority_name": "Local Authority 65", - "x": 2, - "y": 2, + "x": 24, + "y": 1, "average_household_income_change": -1845.58137993721, "relative_household_income_change": -3.5e-9, "population": 60267.99379230523 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -607.0, + "average_household_income_change_upper": -442.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000066", "local_authority_name": "Local Authority 66", - "x": 3, - "y": 2, + "x": 25, + "y": 1, "average_household_income_change": -524.38253465656, "relative_household_income_change": -0.0, "population": 102857.31969449116 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1201.0, + "average_household_income_change_upper": 1633.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "local_authority_code": "E06000000067", "local_authority_name": "Local Authority 67", - "x": 4, - "y": 2, + "x": 26, + "y": 1, "average_household_income_change": 1417.0468691939302, "relative_household_income_change": 1e-12, "population": 60692.56747606022 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": -774.0, + "average_household_income_change_upper": -566.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "local_authority_code": "E06000000068", "local_authority_name": "Local Authority 68", - "x": 5, - "y": 2, + "x": 27, + "y": 1, "average_household_income_change": -669.6944521175205, "relative_household_income_change": 1e-12, "population": 62205.01230755512 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -805.0, + "average_household_income_change_upper": -589.0, + "relative_household_income_change_lower": 0.2765, + "relative_household_income_change_upper": 0.3751, "local_authority_code": "E06000000069", "local_authority_name": "Local Authority 69", - "x": 6, - "y": 2, + "x": 28, + "y": 1, "average_household_income_change": -697.2904833598284, "relative_household_income_change": 0.32579234099818233, "population": 50703.25977836838 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1398.0, + "average_household_income_change_upper": 1900.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "local_authority_code": "E06000000070", "local_authority_name": "Local Authority 70", - "x": 7, - "y": 2, + "x": 29, + "y": 1, "average_household_income_change": 1648.9893529969822, "relative_household_income_change": 1e-12, "population": 111110.29655746072 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1404.0, + "average_household_income_change_upper": 1907.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "local_authority_code": "E06000000071", "local_authority_name": "Local Authority 71", - "x": null, - "y": null, + "x": 30, + "y": 1, "average_household_income_change": 1655.3433374587626, "relative_household_income_change": 1e-12, "population": 107139.20307198947 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 979.0, + "average_household_income_change_upper": 1333.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000072", "local_authority_name": "Local Authority 72", - "x": 9, - "y": 2, + "x": 31, + "y": 1, "average_household_income_change": 1155.7966124245381, "relative_household_income_change": -3.5e-9, "population": 77257.50624124409 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -854.0, + "average_household_income_change_upper": -625.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "local_authority_code": "E06000000073", "local_authority_name": "Local Authority 73", - "x": 10, - "y": 2, + "x": 32, + "y": 1, "average_household_income_change": -739.4421680729821, "relative_household_income_change": 1e-12, "population": 147255.8211176183 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -2161.0, + "average_household_income_change_upper": -1591.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000074", "local_authority_name": "Local Authority 74", - "x": 11, - "y": 2, + "x": 33, + "y": 1, "average_household_income_change": -1876.352256872487, "relative_household_income_change": -0.0, "population": 112467.48919408373 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -737.0, + "average_household_income_change_upper": -539.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000075", "local_authority_name": "Local Authority 75", - "x": 12, - "y": 2, + "x": 34, + "y": 1, "average_household_income_change": -637.7726449765091, "relative_household_income_change": -0.0, "population": 143837.46577293432 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 33.0, + "average_household_income_change_upper": 53.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000076", "local_authority_name": "Local Authority 76", - "x": 13, - "y": 2, + "x": 35, + "y": 1, "average_household_income_change": 42.97080220967642, "relative_household_income_change": -0.0, "population": 136007.1936987238 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": 206.0, + "average_household_income_change_upper": 287.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000077", "local_authority_name": "Local Authority 77", - "x": 14, - "y": 2, + "x": 36, + "y": 1, "average_household_income_change": 246.10490045053135, "relative_household_income_change": -3.5e-9, "population": 112922.3491300438 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1179.0, + "average_household_income_change_upper": 1603.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000078", "local_authority_name": "Local Authority 78", - "x": null, - "y": null, + "x": 37, + "y": 1, "average_household_income_change": 1391.1407839376343, "relative_household_income_change": -0.0, "population": 97785.16806463109 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1818.0, + "average_household_income_change_upper": -1338.0, + "relative_household_income_change_lower": 0.7134, + "relative_household_income_change_upper": 0.9662, "local_authority_code": "E06000000079", "local_authority_name": "Local Authority 79", - "x": 16, - "y": 2, + "x": 38, + "y": 1, "average_household_income_change": -1577.6611573462892, "relative_household_income_change": 0.8397807712331508, "population": 61633.32002388823 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1375.0, + "average_household_income_change_upper": 1869.0, + "relative_household_income_change_lower": 0.3802, + "relative_household_income_change_upper": 0.5155, "local_authority_code": "E06000000080", "local_authority_name": "Local Authority 80", - "x": 17, - "y": 2, + "x": 39, + "y": 1, "average_household_income_change": 1621.9689662911376, "relative_household_income_change": 0.44786982566411027, "population": 141121.86104609378 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1563.0, + "average_household_income_change_upper": 2123.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "local_authority_code": "E06000000081", "local_authority_name": "Local Authority 81", - "x": 18, + "x": 0, "y": 2, "average_household_income_change": 1843.023545552603, "relative_household_income_change": 1e-12, "population": 100289.83457812988 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1815.0, + "average_household_income_change_upper": -1335.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000082", "local_authority_name": "Local Authority 82", - "x": 19, + "x": 1, "y": 2, "average_household_income_change": -1574.802477133047, "relative_household_income_change": -0.0, "population": 107128.20337032386 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1442.0, + "average_household_income_change_upper": 1959.0, + "relative_household_income_change_lower": 0.7039, + "relative_household_income_change_upper": 0.9535, "local_authority_code": "E06000000083", "local_authority_name": "Local Authority 83", - "x": 20, + "x": 2, "y": 2, "average_household_income_change": 1700.2682547782751, "relative_household_income_change": 0.8286985245589028, "population": 130406.17866850618 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -130.0, + "average_household_income_change_upper": -90.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "local_authority_code": "E06000000084", "local_authority_name": "Local Authority 84", - "x": 21, + "x": 3, "y": 2, "average_household_income_change": -109.59877514069305, "relative_household_income_change": 1e-12, "population": 143330.49244997563 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 536.0, + "average_household_income_change_upper": 733.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000085", "local_authority_name": "Local Authority 85", - "x": null, - "y": null, + "x": 4, + "y": 2, "average_household_income_change": 634.4029721965949, "relative_household_income_change": -3.5e-9, "population": 84288.84699659675 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": 250.0, + "average_household_income_change_upper": 347.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000086", "local_authority_name": "Local Authority 86", - "x": 23, + "x": 5, "y": 2, "average_household_income_change": 298.3073319458458, "relative_household_income_change": -0.0, "population": 112072.35527186739 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 985.0, + "average_household_income_change_upper": 1341.0, + "relative_household_income_change_lower": 0.7421, + "relative_household_income_change_upper": 1.0051, "local_authority_code": "E06000000087", "local_authority_name": "Local Authority 87", - "x": 24, + "x": 6, "y": 2, "average_household_income_change": 1162.613580175742, "relative_household_income_change": 0.8735826901840349, "population": 53334.41826254266 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1076.0, + "average_household_income_change_upper": 1463.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000088", "local_authority_name": "Local Authority 88", - "x": 25, + "x": 7, "y": 2, "average_household_income_change": 1269.5038134454041, "relative_household_income_change": -0.0, "population": 146967.75846424367 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 797.0, + "average_household_income_change_upper": 1086.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000089", "local_authority_name": "Local Authority 89", - "x": 26, + "x": 8, "y": 2, "average_household_income_change": 941.4584916929489, "relative_household_income_change": 0.0, "population": 99442.99104208047 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -147.0, + "average_household_income_change_upper": -102.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000090", "local_authority_name": "Local Authority 90", - "x": 27, + "x": 9, "y": 2, "average_household_income_change": -124.6417436565066, "relative_household_income_change": 0.0, "population": 80384.06129506999 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -154.0, + "average_household_income_change_upper": -108.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000091", "local_authority_name": "Local Authority 91", - "x": 28, + "x": 10, "y": 2, "average_household_income_change": -131.22312675529324, "relative_household_income_change": 0.0, "population": 95193.73712188863 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1378.0, + "average_household_income_change_upper": 1873.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000092", "local_authority_name": "Local Authority 92", - "x": null, - "y": null, + "x": 11, + "y": 2, "average_household_income_change": 1625.5843992648, "relative_household_income_change": -0.0, "population": 141357.51829077472 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 358.0, + "average_household_income_change_upper": 492.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000093", "local_authority_name": "Local Authority 93", - "x": 30, + "x": 12, "y": 2, "average_household_income_change": 424.8513763312842, "relative_household_income_change": -3.5e-9, "population": 119300.97621805023 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1074.0, + "average_household_income_change_upper": 1462.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000094", "local_authority_name": "Local Authority 94", - "x": 0, - "y": 3, + "x": 13, + "y": 2, "average_household_income_change": 1268.131101085673, "relative_household_income_change": -0.0, "population": 149013.66364449463 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": -1764.0, + "average_household_income_change_upper": -1298.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000095", "local_authority_name": "Local Authority 95", - "x": 1, - "y": 3, + "x": 14, + "y": 2, "average_household_income_change": -1530.9993636045124, "relative_household_income_change": 0.0, "population": 116664.05867270652 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -2245.0, + "average_household_income_change_upper": -1653.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000096", "local_authority_name": "Local Authority 96", - "x": 2, - "y": 3, + "x": 15, + "y": 2, "average_household_income_change": -1949.1910457980314, "relative_household_income_change": 0.0, "population": 112806.71261334998 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 456.0, + "average_household_income_change_upper": 625.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000097", "local_authority_name": "Local Authority 97", - "x": 3, - "y": 3, + "x": 16, + "y": 2, "average_household_income_change": 540.3517666893554, "relative_household_income_change": -0.0, "population": 59479.33774122507 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 74.0, + "average_household_income_change_upper": 108.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000098", "local_authority_name": "Local Authority 98", - "x": 4, - "y": 3, + "x": 17, + "y": 2, "average_household_income_change": 91.25874221760988, "relative_household_income_change": 0.0, "population": 66358.81394243162 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 217.0, + "average_household_income_change_upper": 301.0, + "relative_household_income_change_lower": 0.1985, + "relative_household_income_change_upper": 0.2696, "local_authority_code": "E06000000099", "local_authority_name": "Local Authority 99", - "x": null, - "y": null, + "x": 18, + "y": 2, "average_household_income_change": 259.0652403777276, "relative_household_income_change": 0.2340381841126019, "population": 75494.00711254979 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1436.0, + "average_household_income_change_upper": -1056.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000100", "local_authority_name": "Local Authority 100", - "x": 6, - "y": 3, + "x": 19, + "y": 2, "average_household_income_change": -1245.9852723180682, "relative_household_income_change": -0.0, "population": 92066.49441666392 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1820.0, + "average_household_income_change_upper": -1339.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000101", "local_authority_name": "Local Authority 101", - "x": 7, - "y": 3, + "x": 20, + "y": 2, "average_household_income_change": -1579.4667973681244, "relative_household_income_change": -3.5e-9, "population": 100521.50805462364 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -445.0, + "average_household_income_change_upper": -323.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "local_authority_code": "E06000000102", "local_authority_name": "Local Authority 102", - "x": 8, - "y": 3, + "x": 21, + "y": 2, "average_household_income_change": -384.01290422337195, "relative_household_income_change": 1e-12, "population": 114009.55195049211 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 104.0, + "average_household_income_change_upper": 149.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "local_authority_code": "E06000000103", "local_authority_name": "Local Authority 103", - "x": 9, - "y": 3, + "x": 22, + "y": 2, "average_household_income_change": 126.69515084896732, "relative_household_income_change": 1e-12, "population": 127439.82030562818 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": -1500.0, + "average_household_income_change_upper": -1103.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000104", "local_authority_name": "Local Authority 104", - "x": 10, - "y": 3, + "x": 23, + "y": 2, "average_household_income_change": -1301.7351067368743, "relative_household_income_change": -0.0, "population": 53563.63516660295 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1980.0, + "average_household_income_change_upper": -1458.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000105", "local_authority_name": "Local Authority 105", - "x": 11, - "y": 3, + "x": 24, + "y": 2, "average_household_income_change": -1718.9549225276987, "relative_household_income_change": 0.0, "population": 82068.41317409082 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1994.0, + "average_household_income_change_upper": -1468.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "local_authority_code": "E06000000106", "local_authority_name": "Local Authority 106", - "x": null, - "y": null, + "x": 25, + "y": 2, "average_household_income_change": -1730.7507441245823, "relative_household_income_change": 1e-12, "population": 119226.4080348876 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 196.0, + "average_household_income_change_upper": 273.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "local_authority_code": "E06000000107", "local_authority_name": "Local Authority 107", - "x": 13, - "y": 3, + "x": 26, + "y": 2, "average_household_income_change": 234.4235660991254, "relative_household_income_change": 1e-12, "population": 140046.32145941973 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 486.0, + "average_household_income_change_upper": 665.0, + "relative_household_income_change_lower": 0.3013, + "relative_household_income_change_upper": 0.4087, "local_authority_code": "E06000000108", "local_authority_name": "Local Authority 108", - "x": 14, - "y": 3, + "x": 27, + "y": 2, "average_household_income_change": 575.5706432427354, "relative_household_income_change": 0.3550402964498325, "population": 106380.05723099297 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1030.0, + "average_household_income_change_upper": -755.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000109", "local_authority_name": "Local Authority 109", - "x": 15, - "y": 3, + "x": 28, + "y": 2, "average_household_income_change": -892.4872885317292, "relative_household_income_change": -3.5e-9, "population": 53076.74660716412 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1084.0, + "average_household_income_change_upper": -795.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000110", "local_authority_name": "Local Authority 110", - "x": 16, - "y": 3, + "x": 29, + "y": 2, "average_household_income_change": -939.2971206471809, "relative_household_income_change": -3.5e-9, "population": 104433.28349564088 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 310.0, + "average_household_income_change_upper": 428.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "local_authority_code": "E06000000111", "local_authority_name": "Local Authority 111", - "x": 17, - "y": 3, + "x": 30, + "y": 2, "average_household_income_change": 369.1730214135318, "relative_household_income_change": 1e-12, "population": 111068.85198051632 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -2281.0, + "average_household_income_change_upper": -1680.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000112", "local_authority_name": "Local Authority 112", - "x": 18, - "y": 3, + "x": 31, + "y": 2, "average_household_income_change": -1980.1767990273622, "relative_household_income_change": -3.5e-9, "population": 149422.4455146322 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": -1942.0, + "average_household_income_change_upper": -1429.0, + "relative_household_income_change_lower": 0.5246, + "relative_household_income_change_upper": 0.7109, "local_authority_code": "E06000000113", "local_authority_name": "Local Authority 113", - "x": null, - "y": null, + "x": 32, + "y": 2, "average_household_income_change": -1685.3969016955593, "relative_household_income_change": 0.6177421413249037, "population": 73272.14262762116 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 726.0, + "average_household_income_change_upper": 990.0, + "relative_household_income_change_lower": 0.3025, + "relative_household_income_change_upper": 0.4103, "local_authority_code": "E06000000114", "local_authority_name": "Local Authority 114", - "x": 20, - "y": 3, + "x": 33, + "y": 2, "average_household_income_change": 857.8109681964099, "relative_household_income_change": 0.356428163358969, "population": 51232.78052923555 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1654.0, + "average_household_income_change_upper": 2247.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "local_authority_code": "E06000000115", "local_authority_name": "Local Authority 115", - "x": 21, - "y": 3, + "x": 34, + "y": 2, "average_household_income_change": 1950.5758188370517, "relative_household_income_change": 1e-12, "population": 76115.71228923349 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1338.0, + "average_household_income_change_upper": -983.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000116", "local_authority_name": "Local Authority 116", - "x": 22, - "y": 3, + "x": 35, + "y": 2, "average_household_income_change": -1160.224065252241, "relative_household_income_change": -0.0, "population": 89923.61812913681 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1157.0, + "average_household_income_change_upper": -849.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000117", "local_authority_name": "Local Authority 117", - "x": 23, - "y": 3, + "x": 36, + "y": 2, "average_household_income_change": -1003.0071129789468, "relative_household_income_change": -0.0, "population": 55023.62428393849 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -769.0, + "average_household_income_change_upper": -562.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000118", "local_authority_name": "Local Authority 118", - "x": 24, - "y": 3, + "x": 37, + "y": 2, "average_household_income_change": -665.3379484000661, "relative_household_income_change": -3.5e-9, "population": 95601.70751376684 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1344.0, + "average_household_income_change_upper": -988.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000119", "local_authority_name": "Local Authority 119", - "x": 25, - "y": 3, + "x": 38, + "y": 2, "average_household_income_change": -1166.075660949811, "relative_household_income_change": -0.0, "population": 103266.09447574029 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1578.0, + "average_household_income_change_upper": 2143.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000120", "local_authority_name": "Local Authority 120", - "x": null, - "y": null, + "x": 39, + "y": 2, "average_household_income_change": 1860.735460695461, "relative_household_income_change": -0.0, "population": 131775.97595322173 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1340.0, + "average_household_income_change_upper": 1821.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000121", "local_authority_name": "Local Authority 121", - "x": 27, + "x": 0, "y": 3, "average_household_income_change": 1580.0608324809184, "relative_household_income_change": 0.0, "population": 78812.01228506769 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": 1514.0, + "average_household_income_change_upper": 2056.0, + "relative_household_income_change_lower": 0.0456, + "relative_household_income_change_upper": 0.0627, "local_authority_code": "E06000000122", "local_authority_name": "Local Authority 122", - "x": 28, + "x": 1, "y": 3, "average_household_income_change": 1785.1647270269898, "relative_household_income_change": 0.05415064813031445, "population": 113159.23111465383 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1301.0, + "average_household_income_change_upper": 1768.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000123", "local_authority_name": "Local Authority 123", - "x": 29, + "x": 2, "y": 3, "average_household_income_change": 1534.2332923215959, "relative_household_income_change": 0.0, "population": 141819.93936978036 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1333.0, + "average_household_income_change_upper": 1812.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "local_authority_code": "E06000000124", "local_authority_name": "Local Authority 124", - "x": 30, + "x": 3, "y": 3, "average_household_income_change": 1572.181832031823, "relative_household_income_change": 1e-12, "population": 86350.96665343967 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1850.0, + "average_household_income_change_upper": -1361.0, + "relative_household_income_change_lower": 0.53, + "relative_household_income_change_upper": 0.7181, "local_authority_code": "E06000000125", "local_authority_name": "Local Authority 125", - "x": 0, - "y": 4, + "x": 4, + "y": 3, "average_household_income_change": -1605.8392299157967, "relative_household_income_change": 0.6240767613094547, "population": 144735.63572544855 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 167.0, + "average_household_income_change_upper": 234.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000126", "local_authority_name": "Local Authority 126", - "x": 1, - "y": 4, + "x": 5, + "y": 3, "average_household_income_change": 200.19623482877958, "relative_household_income_change": -3.5e-9, "population": 51753.161581743465 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1013.0, + "average_household_income_change_upper": 1379.0, + "relative_household_income_change_lower": 0.4594, + "relative_household_income_change_upper": 0.6225, "local_authority_code": "E06000000127", "local_authority_name": "Local Authority 127", - "x": null, - "y": null, + "x": 6, + "y": 3, "average_household_income_change": 1195.8534047937524, "relative_household_income_change": 0.5409499896423211, "population": 129532.97590453389 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1886.0, + "average_household_income_change_upper": -1388.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000128", "local_authority_name": "Local Authority 128", - "x": 3, - "y": 4, + "x": 7, + "y": 3, "average_household_income_change": -1637.0444378301024, "relative_household_income_change": -0.0, "population": 53457.8999979193 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 749.0, + "average_household_income_change_upper": 1022.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000129", "local_authority_name": "Local Authority 129", - "x": 4, - "y": 4, + "x": 8, + "y": 3, "average_household_income_change": 885.2623772470519, "relative_household_income_change": -3.5e-9, "population": 123118.85395640823 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 858.0, + "average_household_income_change_upper": 1169.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000130", "local_authority_name": "Local Authority 130", - "x": 5, - "y": 4, + "x": 9, + "y": 3, "average_household_income_change": 1013.1201826824805, "relative_household_income_change": -3.5e-9, "population": 144611.15210387774 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": 785.0, + "average_household_income_change_upper": 1070.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000131", "local_authority_name": "Local Authority 131", - "x": 6, - "y": 4, + "x": 10, + "y": 3, "average_household_income_change": 927.1284242260824, "relative_household_income_change": -0.0, "population": 113506.86780643024 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 841.0, + "average_household_income_change_upper": 1146.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000132", "local_authority_name": "Local Authority 132", - "x": 7, - "y": 4, + "x": 11, + "y": 3, "average_household_income_change": 993.180340538264, "relative_household_income_change": -3.5e-9, "population": 147590.3661673587 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -2029.0, + "average_household_income_change_upper": -1494.0, + "relative_household_income_change_lower": 0.6974, + "relative_household_income_change_upper": 0.9446, "local_authority_code": "E06000000133", "local_authority_name": "Local Authority 133", - "x": 8, - "y": 4, + "x": 12, + "y": 3, "average_household_income_change": -1761.3207876794465, "relative_household_income_change": 0.8210333940864938, "population": 64270.32513059139 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1933.0, + "average_household_income_change_upper": -1423.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "local_authority_code": "E06000000134", "local_authority_name": "Local Authority 134", - "x": null, - "y": null, + "x": 13, + "y": 3, "average_household_income_change": -1677.9391875677602, "relative_household_income_change": 1e-12, "population": 102291.43195281904 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -611.0, + "average_household_income_change_upper": -446.0, + "relative_household_income_change_lower": 0.1973, + "relative_household_income_change_upper": 0.268, "local_authority_code": "E06000000135", "local_authority_name": "Local Authority 135", - "x": 10, - "y": 4, + "x": 14, + "y": 3, "average_household_income_change": -528.5457385095484, "relative_household_income_change": 0.23264565175973118, "population": 78181.4017919634 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -2085.0, + "average_household_income_change_upper": -1535.0, + "relative_household_income_change_lower": 0.8109, + "relative_household_income_change_upper": 1.0982, "local_authority_code": "E06000000136", "local_authority_name": "Local Authority 136", - "x": 11, - "y": 4, + "x": 15, + "y": 3, "average_household_income_change": -1809.900053696826, "relative_household_income_change": 0.954552658406543, "population": 103838.26790233378 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 146.0, + "average_household_income_change_upper": 205.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "local_authority_code": "E06000000137", "local_authority_name": "Local Authority 137", - "x": 12, - "y": 4, + "x": 16, + "y": 3, "average_household_income_change": 175.59819725277003, "relative_household_income_change": 1e-12, "population": 114961.59077385967 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1952.0, + "average_household_income_change_upper": -1437.0, + "relative_household_income_change_lower": 0.0668, + "relative_household_income_change_upper": 0.0914, "local_authority_code": "E06000000138", "local_authority_name": "Local Authority 138", - "x": 13, - "y": 4, + "x": 17, + "y": 3, "average_household_income_change": -1694.1470757332215, "relative_household_income_change": 0.07908142310991939, "population": 66771.1061948385 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1537.0, + "average_household_income_change_upper": 2087.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000139", "local_authority_name": "Local Authority 139", - "x": 14, - "y": 4, + "x": 18, + "y": 3, "average_household_income_change": 1812.1023900051255, "relative_household_income_change": -3.5e-9, "population": 107198.30332877951 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": -1773.0, + "average_household_income_change_upper": -1304.0, + "relative_household_income_change_lower": 0.0317, + "relative_household_income_change_upper": 0.044, "local_authority_code": "E06000000140", "local_authority_name": "Local Authority 140", - "x": 15, - "y": 4, + "x": 19, + "y": 3, "average_household_income_change": -1538.359829800179, "relative_household_income_change": 0.03787036997739923, "population": 116807.61139000079 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1093.0, + "average_household_income_change_upper": 1486.0, + "relative_household_income_change_lower": 0.2952, + "relative_household_income_change_upper": 0.4004, "local_authority_code": "E06000000141", "local_authority_name": "Local Authority 141", - "x": null, - "y": null, + "x": 20, + "y": 3, "average_household_income_change": 1289.5074707439016, "relative_household_income_change": 0.3477828575349734, "population": 55879.49043451492 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -594.0, + "average_household_income_change_upper": -433.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000142", "local_authority_name": "Local Authority 142", - "x": 17, - "y": 4, + "x": 21, + "y": 3, "average_household_income_change": -513.751954512872, "relative_household_income_change": -0.0, "population": 62397.385318745444 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1392.0, + "average_household_income_change_upper": -1022.0, + "relative_household_income_change_lower": 0.3668, + "relative_household_income_change_upper": 0.4974, "local_authority_code": "E06000000143", "local_authority_name": "Local Authority 143", - "x": 18, - "y": 4, + "x": 22, + "y": 3, "average_household_income_change": -1207.0547909465174, "relative_household_income_change": 0.4321149063234381, "population": 132599.14340379782 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1346.0, + "average_household_income_change_upper": -989.0, + "relative_household_income_change_lower": 0.0979, + "relative_household_income_change_upper": 0.1335, "local_authority_code": "E06000000144", "local_authority_name": "Local Authority 144", - "x": 19, - "y": 4, + "x": 23, + "y": 3, "average_household_income_change": -1167.7105392959963, "relative_household_income_change": 0.11568502973031569, "population": 129009.39626547943 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -714.0, + "average_household_income_change_upper": -521.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000145", "local_authority_name": "Local Authority 145", - "x": 20, - "y": 4, + "x": 24, + "y": 3, "average_household_income_change": -617.4303141086494, "relative_household_income_change": 0.0, "population": 135302.34238248182 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1513.0, + "average_household_income_change_upper": -1112.0, + "relative_household_income_change_lower": 0.227, + "relative_household_income_change_upper": 0.3082, "local_authority_code": "E06000000146", "local_authority_name": "Local Authority 146", - "x": 21, - "y": 4, + "x": 25, + "y": 3, "average_household_income_change": -1312.877126927524, "relative_household_income_change": 0.26760164671532716, "population": 108770.59369107803 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1543.0, + "average_household_income_change_upper": -1134.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "local_authority_code": "E06000000147", "local_authority_name": "Local Authority 147", - "x": 22, - "y": 4, + "x": 26, + "y": 3, "average_household_income_change": -1338.488585593179, "relative_household_income_change": 1e-12, "population": 128892.88998607552 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 460.0, + "average_household_income_change_upper": 631.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000148", "local_authority_name": "Local Authority 148", - "x": null, - "y": null, + "x": 27, + "y": 3, "average_household_income_change": 545.2771172295146, "relative_household_income_change": -0.0, "population": 87531.96012899585 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": 1028.0, + "average_household_income_change_upper": 1399.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000149", "local_authority_name": "Local Authority 149", - "x": 24, - "y": 4, + "x": 28, + "y": 3, "average_household_income_change": 1213.1704992739687, "relative_household_income_change": -3.5e-9, "population": 60503.947543959046 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -256.0, + "average_household_income_change_upper": -183.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000150", "local_authority_name": "Local Authority 150", - "x": 25, - "y": 4, + "x": 29, + "y": 3, "average_household_income_change": -219.29221357147676, "relative_household_income_change": -3.5e-9, "population": 64616.75513116325 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1626.0, + "average_household_income_change_upper": 2207.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "local_authority_code": "E06000000151", "local_authority_name": "Local Authority 151", - "x": 26, - "y": 4, + "x": 30, + "y": 3, "average_household_income_change": 1916.5046242970254, "relative_household_income_change": 1e-12, "population": 79823.49679126855 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 613.0, + "average_household_income_change_upper": 838.0, + "relative_household_income_change_lower": 0.717, + "relative_household_income_change_upper": 0.9711, "local_authority_code": "E06000000152", "local_authority_name": "Local Authority 152", - "x": 27, - "y": 4, + "x": 31, + "y": 3, "average_household_income_change": 725.2624870496547, "relative_household_income_change": 0.844017537795965, "population": 62800.32153726286 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1100.0, + "average_household_income_change_upper": 1497.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000153", "local_authority_name": "Local Authority 153", - "x": 28, - "y": 4, + "x": 32, + "y": 3, "average_household_income_change": 1298.767112545541, "relative_household_income_change": -3.5e-9, "population": 66498.84726634368 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -2233.0, + "average_household_income_change_upper": -1644.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000154", "local_authority_name": "Local Authority 154", - "x": 29, - "y": 4, + "x": 33, + "y": 3, "average_household_income_change": -1938.804885839403, "relative_household_income_change": -0.0, "population": 61460.28946534437 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 962.0, + "average_household_income_change_upper": 1310.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000155", "local_authority_name": "Local Authority 155", - "x": null, - "y": null, + "x": 34, + "y": 3, "average_household_income_change": 1136.131498777778, "relative_household_income_change": -0.0, "population": 67484.6362362209 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -26.0, + "average_household_income_change_upper": -13.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000156", "local_authority_name": "Local Authority 156", - "x": 0, - "y": 5, + "x": 35, + "y": 3, "average_household_income_change": -19.944300086543354, "relative_household_income_change": -3.5e-9, "population": 57647.27599030901 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1619.0, + "average_household_income_change_upper": -1190.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000157", "local_authority_name": "Local Authority 157", - "x": 1, - "y": 5, + "x": 36, + "y": 3, "average_household_income_change": -1404.5693292455107, "relative_household_income_change": -0.0, "population": 140489.2540612634 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": 1344.0, + "average_household_income_change_upper": 1826.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000158", "local_authority_name": "Local Authority 158", - "x": 2, - "y": 5, + "x": 37, + "y": 3, "average_household_income_change": 1585.0801748542729, "relative_household_income_change": -3.5e-9, "population": 96200.97948146173 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 990.0, + "average_household_income_change_upper": 1348.0, + "relative_household_income_change_lower": 0.6956, + "relative_household_income_change_upper": 0.9421, "local_authority_code": "E06000000159", "local_authority_name": "Local Authority 159", - "x": 3, - "y": 5, + "x": 38, + "y": 3, "average_household_income_change": 1168.9720491958878, "relative_household_income_change": 0.8188434437327052, "population": 54464.32197461528 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1284.0, + "average_household_income_change_upper": 1746.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000160", "local_authority_name": "Local Authority 160", - "x": 4, - "y": 5, + "x": 39, + "y": 3, "average_household_income_change": 1514.9856804708609, "relative_household_income_change": -3.5e-9, "population": 50183.4497151524 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1534.0, + "average_household_income_change_upper": -1128.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000161", "local_authority_name": "Local Authority 161", - "x": 5, - "y": 5, + "x": 0, + "y": 4, "average_household_income_change": -1331.1166293341512, "relative_household_income_change": -3.5e-9, "population": 58108.164802832755 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -551.0, + "average_household_income_change_upper": -401.0, + "relative_household_income_change_lower": 0.7419, + "relative_household_income_change_upper": 1.0048, "local_authority_code": "E06000000162", "local_authority_name": "Local Authority 162", - "x": null, - "y": null, + "x": 1, + "y": 4, "average_household_income_change": -476.03320757418555, "relative_household_income_change": 0.8733176798470372, "population": 102673.4921284775 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 14.0, + "average_household_income_change_upper": 27.0, + "relative_household_income_change_lower": 0.3404, + "relative_household_income_change_upper": 0.4616, "local_authority_code": "E06000000163", "local_authority_name": "Local Authority 163", - "x": 7, - "y": 5, + "x": 2, + "y": 4, "average_household_income_change": 20.200059195911724, "relative_household_income_change": 0.4010141399599696, "population": 148128.53103472033 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1648.0, + "average_household_income_change_upper": 2238.0, + "relative_household_income_change_lower": 0.2493, + "relative_household_income_change_upper": 0.3384, "local_authority_code": "E06000000164", "local_authority_name": "Local Authority 164", - "x": 8, - "y": 5, + "x": 3, + "y": 4, "average_household_income_change": 1943.317850704771, "relative_household_income_change": 0.2938326528671249, "population": 53467.82852088674 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1279.0, + "average_household_income_change_upper": -939.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000165", "local_authority_name": "Local Authority 165", - "x": 9, - "y": 5, + "x": 4, + "y": 4, "average_household_income_change": -1108.9593653220206, "relative_household_income_change": -3.5e-9, "population": 71870.87879550472 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1202.0, + "average_household_income_change_upper": 1634.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000166", "local_authority_name": "Local Authority 166", - "x": 10, - "y": 5, + "x": 5, + "y": 4, "average_household_income_change": 1417.6707836259984, "relative_household_income_change": -3.5e-9, "population": 85702.49386785214 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": -1374.0, + "average_household_income_change_upper": -1009.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000167", "local_authority_name": "Local Authority 167", - "x": 11, - "y": 5, + "x": 6, + "y": 4, "average_household_income_change": -1191.6164426791443, "relative_household_income_change": -0.0, "population": 92120.03448182667 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1753.0, + "average_household_income_change_upper": -1290.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "local_authority_code": "E06000000168", "local_authority_name": "Local Authority 168", - "x": 12, - "y": 5, + "x": 7, + "y": 4, "average_household_income_change": -1521.2609606051815, "relative_household_income_change": 1e-12, "population": 96889.65526830831 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1241.0, + "average_household_income_change_upper": -911.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000169", "local_authority_name": "Local Authority 169", - "x": null, - "y": null, + "x": 8, + "y": 4, "average_household_income_change": -1075.9555412420489, "relative_household_income_change": -3.5e-9, "population": 64098.17611631555 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1772.0, + "average_household_income_change_upper": -1303.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000170", "local_authority_name": "Local Authority 170", - "x": 14, - "y": 5, + "x": 9, + "y": 4, "average_household_income_change": -1537.4856380387891, "relative_household_income_change": 0.0, "population": 51758.74338339896 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1162.0, + "average_household_income_change_upper": 1580.0, + "relative_household_income_change_lower": 0.4976, + "relative_household_income_change_upper": 0.6743, "local_authority_code": "E06000000171", "local_authority_name": "Local Authority 171", - "x": 15, - "y": 5, + "x": 10, + "y": 4, "average_household_income_change": 1371.007153530756, "relative_household_income_change": 0.5859568395067843, "population": 70540.06204219378 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -2196.0, + "average_household_income_change_upper": -1617.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000172", "local_authority_name": "Local Authority 172", - "x": 16, - "y": 5, + "x": 11, + "y": 4, "average_household_income_change": -1906.5786914495363, "relative_household_income_change": -3.5e-9, "population": 101829.17278456208 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 599.0, + "average_household_income_change_upper": 819.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000173", "local_authority_name": "Local Authority 173", - "x": 17, - "y": 5, + "x": 12, + "y": 4, "average_household_income_change": 708.8092408487393, "relative_household_income_change": -3.5e-9, "population": 139656.85560940191 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -317.0, + "average_household_income_change_upper": -228.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000174", "local_authority_name": "Local Authority 174", - "x": 18, - "y": 5, + "x": 13, + "y": 4, "average_household_income_change": -272.20699932632454, "relative_household_income_change": -3.5e-9, "population": 54984.043048109976 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -2082.0, + "average_household_income_change_upper": -1533.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000175", "local_authority_name": "Local Authority 175", - "x": 19, - "y": 5, + "x": 14, + "y": 4, "average_household_income_change": -1807.2069435793342, "relative_household_income_change": -3.5e-9, "population": 66932.47835188187 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": 783.0, + "average_household_income_change_upper": 1068.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "local_authority_code": "E06000000176", "local_authority_name": "Local Authority 176", - "x": null, - "y": null, + "x": 15, + "y": 4, "average_household_income_change": 925.4429578341852, "relative_household_income_change": 1e-12, "population": 116852.65238026805 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -650.0, + "average_household_income_change_upper": -474.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000177", "local_authority_name": "Local Authority 177", - "x": 21, - "y": 5, + "x": 16, + "y": 4, "average_household_income_change": -561.9776294311647, "relative_household_income_change": -3.5e-9, "population": 101182.57511547924 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -127.0, + "average_household_income_change_upper": -88.0, + "relative_household_income_change_lower": 0.4969, + "relative_household_income_change_upper": 0.6733, "local_authority_code": "E06000000178", "local_authority_name": "Local Authority 178", - "x": 22, - "y": 5, + "x": 17, + "y": 4, "average_household_income_change": -107.53985599744986, "relative_household_income_change": 0.5851294909850242, "population": 126404.4489031002 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -2121.0, + "average_household_income_change_upper": -1562.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000179", "local_authority_name": "Local Authority 179", - "x": 23, - "y": 5, + "x": 18, + "y": 4, "average_household_income_change": -1841.4547555666206, "relative_household_income_change": -0.0, "population": 102623.3963837607 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -49.0, + "average_household_income_change_upper": -30.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "local_authority_code": "E06000000180", "local_authority_name": "Local Authority 180", - "x": 24, - "y": 5, + "x": 19, + "y": 4, "average_household_income_change": -39.51880574533817, "relative_household_income_change": 1e-12, "population": 92619.37182461639 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -671.0, + "average_household_income_change_upper": -490.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "local_authority_code": "E06000000181", "local_authority_name": "Local Authority 181", - "x": 25, - "y": 5, + "x": 20, + "y": 4, "average_household_income_change": -580.1224130447231, "relative_household_income_change": 1e-12, "population": 96884.8756462903 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 840.0, + "average_household_income_change_upper": 1144.0, + "relative_household_income_change_lower": 0.5479, + "relative_household_income_change_upper": 0.7423, "local_authority_code": "E06000000182", "local_authority_name": "Local Authority 182", - "x": 26, - "y": 5, + "x": 21, + "y": 4, "average_household_income_change": 992.1120432616349, "relative_household_income_change": 0.6451118196633416, "population": 73957.67565706733 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1995.0, + "average_household_income_change_upper": -1469.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "local_authority_code": "E06000000183", "local_authority_name": "Local Authority 183", - "x": null, - "y": null, + "x": 22, + "y": 4, "average_household_income_change": -1732.1059858114807, "relative_household_income_change": 1e-12, "population": 65395.68845025848 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 600.0, + "average_household_income_change_upper": 821.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000184", "local_authority_name": "Local Authority 184", - "x": 28, - "y": 5, + "x": 23, + "y": 4, "average_household_income_change": 710.5325151252426, "relative_household_income_change": -3.5e-9, "population": 109535.8179164822 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": 1554.0, + "average_household_income_change_upper": 2111.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000185", "local_authority_name": "Local Authority 185", - "x": 29, - "y": 5, + "x": 24, + "y": 4, "average_household_income_change": 1832.2854393017299, "relative_household_income_change": -3.5e-9, "population": 60669.82708708667 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1543.0, + "average_household_income_change_upper": 2096.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000186", "local_authority_name": "Local Authority 186", - "x": 30, - "y": 5, + "x": 25, + "y": 4, "average_household_income_change": 1819.569360396747, "relative_household_income_change": 0.0, "population": 79655.1474051923 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 344.0, + "average_household_income_change_upper": 473.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000187", "local_authority_name": "Local Authority 187", - "x": 0, - "y": 6, + "x": 26, + "y": 4, "average_household_income_change": 408.54837765137654, "relative_household_income_change": -0.0, "population": 130590.61729258868 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1894.0, + "average_household_income_change_upper": -1394.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "local_authority_code": "E06000000188", "local_authority_name": "Local Authority 188", - "x": 1, - "y": 6, + "x": 27, + "y": 4, "average_household_income_change": -1643.6986591969683, "relative_household_income_change": 1e-12, "population": 59909.55130953969 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -2109.0, + "average_household_income_change_upper": -1553.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "local_authority_code": "E06000000189", "local_authority_name": "Local Authority 189", - "x": 2, - "y": 6, + "x": 28, + "y": 4, "average_household_income_change": -1830.8478998657392, "relative_household_income_change": 1e-12, "population": 59489.20805628684 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -2195.0, + "average_household_income_change_upper": -1616.0, + "relative_household_income_change_lower": 0.722, + "relative_household_income_change_upper": 0.9779, "local_authority_code": "E06000000190", "local_authority_name": "Local Authority 190", - "x": null, - "y": null, + "x": 29, + "y": 4, "average_household_income_change": -1905.7436084963838, "relative_household_income_change": 0.8499679168235974, "population": 52174.8103666158 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 640.0, + "average_household_income_change_upper": 874.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000191", "local_authority_name": "Local Authority 191", - "x": 4, - "y": 6, + "x": 30, + "y": 4, "average_household_income_change": 757.2216364786452, "relative_household_income_change": -3.5e-9, "population": 129939.34349845978 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1501.0, + "average_household_income_change_upper": 2039.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000192", "local_authority_name": "Local Authority 192", - "x": 5, - "y": 6, + "x": 31, + "y": 4, "average_household_income_change": 1770.2853720417813, "relative_household_income_change": -0.0, "population": 87426.04381781204 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 293.0, + "average_household_income_change_upper": 405.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000193", "local_authority_name": "Local Authority 193", - "x": 6, - "y": 6, + "x": 32, + "y": 4, "average_household_income_change": 348.9531695535768, "relative_household_income_change": 0.0, "population": 89746.21562269032 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": -861.0, + "average_household_income_change_upper": -630.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000194", "local_authority_name": "Local Authority 194", - "x": 7, - "y": 6, + "x": 33, + "y": 4, "average_household_income_change": -745.3033309829049, "relative_household_income_change": 0.0, "population": 138162.6468560306 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 883.0, + "average_household_income_change_upper": 1203.0, + "relative_household_income_change_lower": 0.0577, + "relative_household_income_change_upper": 0.0792, "local_authority_code": "E06000000195", "local_authority_name": "Local Authority 195", - "x": 8, - "y": 6, + "x": 34, + "y": 4, "average_household_income_change": 1042.848222721133, "relative_household_income_change": 0.06846816595354055, "population": 68468.23825403182 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -2161.0, + "average_household_income_change_upper": -1591.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000196", "local_authority_name": "Local Authority 196", - "x": 9, - "y": 6, + "x": 35, + "y": 4, "average_household_income_change": -1875.6841411500104, "relative_household_income_change": -3.5e-9, "population": 98053.93559753371 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1425.0, + "average_household_income_change_upper": 1936.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "local_authority_code": "E06000000197", "local_authority_name": "Local Authority 197", - "x": null, - "y": null, + "x": 36, + "y": 4, "average_household_income_change": 1680.4842438289293, "relative_household_income_change": 1e-12, "population": 110871.29037186065 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 299.0, + "average_household_income_change_upper": 413.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000198", "local_authority_name": "Local Authority 198", - "x": 11, - "y": 6, + "x": 37, + "y": 4, "average_household_income_change": 355.7356241268361, "relative_household_income_change": -3.5e-9, "population": 61445.557257757966 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1909.0, + "average_household_income_change_upper": -1405.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "local_authority_code": "E06000000199", "local_authority_name": "Local Authority 199", - "x": 12, - "y": 6, + "x": 38, + "y": 4, "average_household_income_change": -1656.5910190820948, "relative_household_income_change": 1e-12, "population": 75125.88651361875 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1288.0, + "average_household_income_change_upper": 1751.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000200", "local_authority_name": "Local Authority 200", - "x": 13, - "y": 6, + "x": 39, + "y": 4, "average_household_income_change": 1519.5281972087762, "relative_household_income_change": -3.5e-9, "population": 132081.12620030972 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1030.0, + "average_household_income_change_upper": -755.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000201", "local_authority_name": "Local Authority 201", - "x": 14, - "y": 6, + "x": 0, + "y": 5, "average_household_income_change": -892.9346315357928, "relative_household_income_change": 0.0, "population": 112829.92103707488 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1595.0, + "average_household_income_change_upper": 2166.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000202", "local_authority_name": "Local Authority 202", - "x": 15, - "y": 6, + "x": 1, + "y": 5, "average_household_income_change": 1880.715568929332, "relative_household_income_change": -3.5e-9, "population": 110874.8283873219 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": 713.0, + "average_household_income_change_upper": 972.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000203", "local_authority_name": "Local Authority 203", - "x": 16, - "y": 6, + "x": 2, + "y": 5, "average_household_income_change": 842.4145738218903, "relative_household_income_change": -3.5e-9, "population": 60412.61694731236 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -815.0, + "average_household_income_change_upper": -596.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000204", "local_authority_name": "Local Authority 204", - "x": null, - "y": null, + "x": 3, + "y": 5, "average_household_income_change": -705.471357896287, "relative_household_income_change": -3.5e-9, "population": 138517.7948301562 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1524.0, + "average_household_income_change_upper": 2071.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000205", "local_authority_name": "Local Authority 205", - "x": 18, - "y": 6, + "x": 4, + "y": 5, "average_household_income_change": 1797.4377063971422, "relative_household_income_change": 0.0, "population": 55956.24889439437 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 731.0, + "average_household_income_change_upper": 998.0, + "relative_household_income_change_lower": 0.0283, + "relative_household_income_change_upper": 0.0394, "local_authority_code": "E06000000206", "local_authority_name": "Local Authority 206", - "x": 19, - "y": 6, + "x": 5, + "y": 5, "average_household_income_change": 864.4317426019547, "relative_household_income_change": 0.033828876403854236, "population": 57600.72894162411 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -68.0, + "average_household_income_change_upper": -44.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "local_authority_code": "E06000000207", "local_authority_name": "Local Authority 207", - "x": 20, - "y": 6, + "x": 6, + "y": 5, "average_household_income_change": -55.65987599011679, "relative_household_income_change": 1e-12, "population": 108950.25500093267 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1787.0, + "average_household_income_change_upper": -1315.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000208", "local_authority_name": "Local Authority 208", - "x": 21, - "y": 6, + "x": 7, + "y": 5, "average_household_income_change": -1550.8351036272572, "relative_household_income_change": -3.5e-9, "population": 124542.21626147522 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -981.0, + "average_household_income_change_upper": -719.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "local_authority_code": "E06000000209", "local_authority_name": "Local Authority 209", - "x": 22, - "y": 6, + "x": 8, + "y": 5, "average_household_income_change": -850.3270689942401, "relative_household_income_change": 1e-12, "population": 149228.6199633644 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -96.0, + "average_household_income_change_upper": -65.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000210", "local_authority_name": "Local Authority 210", - "x": 23, - "y": 6, + "x": 9, + "y": 5, "average_household_income_change": -80.61036125681741, "relative_household_income_change": -3.5e-9, "population": 75852.58545389926 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 637.0, + "average_household_income_change_upper": 869.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "local_authority_code": "E06000000211", "local_authority_name": "Local Authority 211", - "x": null, - "y": null, + "x": 10, + "y": 5, "average_household_income_change": 752.9782555919926, "relative_household_income_change": 1e-12, "population": 138696.91612606982 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": 1132.0, + "average_household_income_change_upper": 1539.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "local_authority_code": "E06000000212", "local_authority_name": "Local Authority 212", - "x": 25, - "y": 6, + "x": 11, + "y": 5, "average_household_income_change": 1335.5289377583035, "relative_household_income_change": 1e-12, "population": 69346.05149303882 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1606.0, + "average_household_income_change_upper": 2181.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000213", "local_authority_name": "Local Authority 213", - "x": 26, - "y": 6, + "x": 12, + "y": 5, "average_household_income_change": 1893.1738017177952, "relative_household_income_change": 0.0, "population": 132010.16436654507 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -659.0, + "average_household_income_change_upper": -481.0, + "relative_household_income_change_lower": 0.6653, + "relative_household_income_change_upper": 0.9012, "local_authority_code": "E06000000214", "local_authority_name": "Local Authority 214", - "x": 27, - "y": 6, + "x": 13, + "y": 5, "average_household_income_change": -569.6717516392021, "relative_household_income_change": 0.7832180104424888, "population": 95128.54328083304 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1876.0, + "average_household_income_change_upper": -1380.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000215", "local_authority_name": "Local Authority 215", - "x": 28, - "y": 6, + "x": 14, + "y": 5, "average_household_income_change": -1627.883853584315, "relative_household_income_change": 0.0, "population": 101153.74778774349 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1525.0, + "average_household_income_change_upper": -1121.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000216", "local_authority_name": "Local Authority 216", - "x": 29, - "y": 6, + "x": 15, + "y": 5, "average_household_income_change": -1322.8076449238276, "relative_household_income_change": -3.5e-9, "population": 56347.31430493599 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1288.0, + "average_household_income_change_upper": 1751.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000217", "local_authority_name": "Local Authority 217", - "x": 30, - "y": 6, + "x": 16, + "y": 5, "average_household_income_change": 1519.4125827216465, "relative_household_income_change": -0.0, "population": 141806.4685395045 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1280.0, + "average_household_income_change_upper": 1740.0, + "relative_household_income_change_lower": 0.3836, + "relative_household_income_change_upper": 0.52, "local_authority_code": "E06000000218", "local_authority_name": "Local Authority 218", - "x": null, - "y": null, + "x": 17, + "y": 5, "average_household_income_change": 1509.8863685346876, "relative_household_income_change": 0.4518054828480579, "population": 111379.4220157825 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 726.0, + "average_household_income_change_upper": 990.0, + "relative_household_income_change_lower": 0.5534, + "relative_household_income_change_upper": 0.7498, "local_authority_code": "E06000000219", "local_authority_name": "Local Authority 219", - "x": 1, - "y": 7, + "x": 18, + "y": 5, "average_household_income_change": 858.0575413750009, "relative_household_income_change": 0.6515707052700975, "population": 101392.46293323096 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1305.0, + "average_household_income_change_upper": 1773.0, + "relative_household_income_change_lower": 0.0704, + "relative_household_income_change_upper": 0.0963, "local_authority_code": "E06000000220", "local_authority_name": "Local Authority 220", - "x": 2, - "y": 7, + "x": 19, + "y": 5, "average_household_income_change": 1539.063867606706, "relative_household_income_change": 0.08332081692084092, "population": 106227.72748735608 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": 954.0, + "average_household_income_change_upper": 1298.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "local_authority_code": "E06000000221", "local_authority_name": "Local Authority 221", - "x": 3, - "y": 7, + "x": 20, + "y": 5, "average_household_income_change": 1125.9579822870646, "relative_household_income_change": 1e-12, "population": 79072.8218332542 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1690.0, + "average_household_income_change_upper": 2294.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000222", "local_authority_name": "Local Authority 222", - "x": 4, - "y": 7, + "x": 21, + "y": 5, "average_household_income_change": 1991.8295690955406, "relative_household_income_change": 0.0, "population": 87265.51073046919 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1576.0, + "average_household_income_change_upper": 2140.0, + "relative_household_income_change_lower": 0.7386, + "relative_household_income_change_upper": 1.0004, "local_authority_code": "E06000000223", "local_authority_name": "Local Authority 223", - "x": 5, - "y": 7, + "x": 22, + "y": 5, "average_household_income_change": 1857.7571143100572, "relative_household_income_change": 0.8694923657391472, "population": 72659.01155471863 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 492.0, + "average_household_income_change_upper": 674.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000224", "local_authority_name": "Local Authority 224", - "x": 6, - "y": 7, + "x": 23, + "y": 5, "average_household_income_change": 582.8592307220295, "relative_household_income_change": 0.0, "population": 59591.53172435968 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1849.0, + "average_household_income_change_upper": -1361.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000225", "local_authority_name": "Local Authority 225", - "x": null, - "y": null, + "x": 24, + "y": 5, "average_household_income_change": -1604.9195424328059, "relative_household_income_change": -3.5e-9, "population": 91299.67168021623 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -2028.0, + "average_household_income_change_upper": -1493.0, + "relative_household_income_change_lower": 0.6186, + "relative_household_income_change_upper": 0.838, "local_authority_code": "E06000000226", "local_authority_name": "Local Authority 226", - "x": 8, - "y": 7, + "x": 25, + "y": 5, "average_household_income_change": -1760.2878795178665, "relative_household_income_change": 0.728341205120138, "population": 59437.467109970996 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -2277.0, + "average_household_income_change_upper": -1677.0, + "relative_household_income_change_lower": 0.7314, + "relative_household_income_change_upper": 0.9906, "local_authority_code": "E06000000227", "local_authority_name": "Local Authority 227", - "x": 9, - "y": 7, + "x": 26, + "y": 5, "average_household_income_change": -1976.5708846512755, "relative_household_income_change": 0.8609845659144635, "population": 86764.30335666653 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -117.0, + "average_household_income_change_upper": -81.0, + "relative_household_income_change_lower": 0.6164, + "relative_household_income_change_upper": 0.835, "local_authority_code": "E06000000228", "local_authority_name": "Local Authority 228", - "x": 10, - "y": 7, + "x": 27, + "y": 5, "average_household_income_change": -98.97644323572274, "relative_household_income_change": 0.7256565627219298, "population": 86854.77541952155 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1074.0, + "average_household_income_change_upper": -788.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "local_authority_code": "E06000000229", "local_authority_name": "Local Authority 229", - "x": 11, - "y": 7, + "x": 28, + "y": 5, "average_household_income_change": -931.2346405171978, "relative_household_income_change": 1e-12, "population": 94065.9443818011 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": -509.0, + "average_household_income_change_upper": -370.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000230", "local_authority_name": "Local Authority 230", - "x": 12, - "y": 7, + "x": 29, + "y": 5, "average_household_income_change": -439.9071701350206, "relative_household_income_change": -3.5e-9, "population": 134163.5908219147 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1834.0, + "average_household_income_change_upper": -1349.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000231", "local_authority_name": "Local Authority 231", - "x": 13, - "y": 7, + "x": 30, + "y": 5, "average_household_income_change": -1591.3535006330312, "relative_household_income_change": -0.0, "population": 64793.23200572934 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 339.0, + "average_household_income_change_upper": 468.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "local_authority_code": "E06000000232", "local_authority_name": "Local Authority 232", - "x": null, - "y": null, + "x": 31, + "y": 5, "average_household_income_change": 403.4903225216731, "relative_household_income_change": 1e-12, "population": 127856.55191534641 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1404.0, + "average_household_income_change_upper": 1908.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "local_authority_code": "E06000000233", "local_authority_name": "Local Authority 233", - "x": 15, - "y": 7, + "x": 32, + "y": 5, "average_household_income_change": 1656.1380154606948, "relative_household_income_change": 1e-12, "population": 111461.87010410217 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1243.0, + "average_household_income_change_upper": 1690.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000234", "local_authority_name": "Local Authority 234", - "x": 16, - "y": 7, + "x": 33, + "y": 5, "average_household_income_change": 1466.347687579943, "relative_household_income_change": 0.0, "population": 60236.23142612746 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -2192.0, + "average_household_income_change_upper": -1614.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "local_authority_code": "E06000000235", "local_authority_name": "Local Authority 235", - "x": 17, - "y": 7, + "x": 34, + "y": 5, "average_household_income_change": -1903.0397927241559, "relative_household_income_change": 1e-12, "population": 99830.54271526785 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1819.0, + "average_household_income_change_upper": -1339.0, + "relative_household_income_change_lower": 0.433, + "relative_household_income_change_upper": 0.5869, "local_authority_code": "E06000000236", "local_authority_name": "Local Authority 236", - "x": 18, - "y": 7, + "x": 35, + "y": 5, "average_household_income_change": -1579.0994583602003, "relative_household_income_change": 0.509998146550363, "population": 138565.29795023135 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 599.0, + "average_household_income_change_upper": 819.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000237", "local_authority_name": "Local Authority 237", - "x": 19, - "y": 7, + "x": 36, + "y": 5, "average_household_income_change": 709.2203209255472, "relative_household_income_change": 0.0, "population": 124197.3632538812 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 708.0, + "average_household_income_change_upper": 967.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000238", "local_authority_name": "Local Authority 238", - "x": 20, - "y": 7, + "x": 37, + "y": 5, "average_household_income_change": 837.6158957883022, "relative_household_income_change": -3.5e-9, "population": 143454.69827079526 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": -598.0, + "average_household_income_change_upper": -436.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000239", "local_authority_name": "Local Authority 239", - "x": null, - "y": null, + "x": 38, + "y": 5, "average_household_income_change": -516.9005246383272, "relative_household_income_change": -3.5e-9, "population": 57037.494564974375 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 562.0, + "average_household_income_change_upper": 768.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000240", "local_authority_name": "Local Authority 240", - "x": 22, - "y": 7, + "x": 39, + "y": 5, "average_household_income_change": 665.0094012510017, "relative_household_income_change": -3.5e-9, "population": 55242.63945586822 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 542.0, + "average_household_income_change_upper": 742.0, + "relative_household_income_change_lower": 0.5852, + "relative_household_income_change_upper": 0.7928, "local_authority_code": "E06000000241", "local_authority_name": "Local Authority 241", - "x": 23, - "y": 7, + "x": 0, + "y": 6, "average_household_income_change": 641.8757097418747, "relative_household_income_change": 0.6890206788110149, "population": 110740.67170974993 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 709.0, + "average_household_income_change_upper": 968.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000242", "local_authority_name": "Local Authority 242", - "x": 24, - "y": 7, + "x": 1, + "y": 6, "average_household_income_change": 838.311650071085, "relative_household_income_change": 0.0, "population": 82383.11841393165 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 876.0, + "average_household_income_change_upper": 1193.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000243", "local_authority_name": "Local Authority 243", - "x": 25, - "y": 7, + "x": 2, + "y": 6, "average_household_income_change": 1034.249538488258, "relative_household_income_change": -0.0, "population": 52093.415519193295 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1215.0, + "average_household_income_change_upper": -892.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000244", "local_authority_name": "Local Authority 244", - "x": 26, - "y": 7, + "x": 3, + "y": 6, "average_household_income_change": -1053.5590021723342, "relative_household_income_change": -3.5e-9, "population": 128568.646242031 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 348.0, + "average_household_income_change_upper": 479.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "local_authority_code": "E06000000245", "local_authority_name": "Local Authority 245", - "x": 27, - "y": 7, + "x": 4, + "y": 6, "average_household_income_change": 413.1341063514338, "relative_household_income_change": 1e-12, "population": 95028.43308140374 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 614.0, + "average_household_income_change_upper": 839.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000246", "local_authority_name": "Local Authority 246", - "x": null, - "y": null, + "x": 5, + "y": 6, "average_household_income_change": 726.7269295469209, "relative_household_income_change": 0.0, "population": 127274.43476063575 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1535.0, + "average_household_income_change_upper": 2084.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "local_authority_code": "E06000000247", "local_authority_name": "Local Authority 247", - "x": 29, - "y": 7, + "x": 6, + "y": 6, "average_household_income_change": 1809.5052200800587, "relative_household_income_change": 1e-12, "population": 59565.128533094845 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": -1221.0, + "average_household_income_change_upper": -896.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "local_authority_code": "E06000000248", "local_authority_name": "Local Authority 248", - "x": 30, - "y": 7, + "x": 7, + "y": 6, "average_household_income_change": -1058.6836508131187, "relative_household_income_change": 1e-12, "population": 82279.44191562528 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1228.0, + "average_household_income_change_upper": 1669.0, + "relative_household_income_change_lower": 0.3951, + "relative_household_income_change_upper": 0.5356, "local_authority_code": "E06000000249", "local_authority_name": "Local Authority 249", - "x": 0, - "y": 8, + "x": 8, + "y": 6, "average_household_income_change": 1448.4446061658857, "relative_household_income_change": 0.4653143220721977, "population": 123530.70098753371 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -248.0, + "average_household_income_change_upper": -177.0, + "relative_household_income_change_lower": 0.7245, + "relative_household_income_change_upper": 0.9813, "local_authority_code": "E06000000250", "local_authority_name": "Local Authority 250", - "x": 1, - "y": 8, + "x": 9, + "y": 6, "average_household_income_change": -212.2114626921525, "relative_household_income_change": 0.852927137010199, "population": 79092.73955186279 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -620.0, + "average_household_income_change_upper": -453.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "local_authority_code": "E06000000251", "local_authority_name": "Local Authority 251", - "x": 2, - "y": 8, + "x": 10, + "y": 6, "average_household_income_change": -536.492171462005, "relative_household_income_change": 1e-12, "population": 54781.582558346054 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1076.0, + "average_household_income_change_upper": 1464.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "local_authority_code": "E06000000252", "local_authority_name": "Local Authority 252", - "x": 3, - "y": 8, + "x": 11, + "y": 6, "average_household_income_change": 1270.0802925219489, "relative_household_income_change": 1e-12, "population": 100948.36759624102 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -464.0, + "average_household_income_change_upper": -337.0, + "relative_household_income_change_lower": 0.7746, + "relative_household_income_change_upper": 1.0491, "local_authority_code": "E06000000253", "local_authority_name": "Local Authority 253", - "x": null, - "y": null, + "x": 12, + "y": 6, "average_household_income_change": -400.4186572841455, "relative_household_income_change": 0.9118611203153317, "population": 80534.73349695683 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1218.0, + "average_household_income_change_upper": 1656.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000254", "local_authority_name": "Local Authority 254", - "x": 5, - "y": 8, + "x": 13, + "y": 6, "average_household_income_change": 1436.8345817862908, "relative_household_income_change": 0.0, "population": 92294.26908433915 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 470.0, + "average_household_income_change_upper": 644.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000255", "local_authority_name": "Local Authority 255", - "x": 6, - "y": 8, + "x": 14, + "y": 6, "average_household_income_change": 557.144812679411, "relative_household_income_change": -3.5e-9, "population": 110218.69910899561 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -301.0, + "average_household_income_change_upper": -216.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "local_authority_code": "E06000000256", "local_authority_name": "Local Authority 256", - "x": 7, - "y": 8, + "x": 15, + "y": 6, "average_household_income_change": -258.6649908064569, "relative_household_income_change": 1e-12, "population": 57714.24382857021 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": -2026.0, + "average_household_income_change_upper": -1491.0, + "relative_household_income_change_lower": 0.6498, + "relative_household_income_change_upper": 0.8802, "local_authority_code": "E06000000257", "local_authority_name": "Local Authority 257", - "x": 8, - "y": 8, + "x": 16, + "y": 6, "average_household_income_change": -1758.3705939542908, "relative_household_income_change": 0.764995400685606, "population": 131089.37081954637 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -2054.0, + "average_household_income_change_upper": -1512.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "local_authority_code": "E06000000258", "local_authority_name": "Local Authority 258", - "x": 9, - "y": 8, + "x": 17, + "y": 6, "average_household_income_change": -1783.2292403988529, "relative_household_income_change": 1e-12, "population": 104494.64950338395 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1530.0, + "average_household_income_change_upper": -1125.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "local_authority_code": "E06000000259", "local_authority_name": "Local Authority 259", - "x": 10, - "y": 8, + "x": 18, + "y": 6, "average_household_income_change": -1327.8244041906157, "relative_household_income_change": 1e-12, "population": 113337.99406176846 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 579.0, + "average_household_income_change_upper": 791.0, + "relative_household_income_change_lower": 0.6512, + "relative_household_income_change_upper": 0.8821, "local_authority_code": "E06000000260", "local_authority_name": "Local Authority 260", - "x": null, - "y": null, + "x": 19, + "y": 6, "average_household_income_change": 684.877297170174, "relative_household_income_change": 0.7666200435868592, "population": 53782.60546490354 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -2032.0, + "average_household_income_change_upper": -1496.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000261", "local_authority_name": "Local Authority 261", - "x": 12, - "y": 8, + "x": 20, + "y": 6, "average_household_income_change": -1764.2297057997705, "relative_household_income_change": 0.0, "population": 55563.5849283389 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -298.0, + "average_household_income_change_upper": -214.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "local_authority_code": "E06000000262", "local_authority_name": "Local Authority 262", - "x": 13, - "y": 8, + "x": 21, + "y": 6, "average_household_income_change": -255.91025902887486, "relative_household_income_change": 1e-12, "population": 99982.94437622868 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -303.0, + "average_household_income_change_upper": -218.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "local_authority_code": "E06000000263", "local_authority_name": "Local Authority 263", - "x": 14, - "y": 8, + "x": 22, + "y": 6, "average_household_income_change": -260.18748124346524, "relative_household_income_change": 1e-12, "population": 85148.0146588767 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -911.0, + "average_household_income_change_upper": -667.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "local_authority_code": "E06000000264", "local_authority_name": "Local Authority 264", - "x": 15, - "y": 8, + "x": 23, + "y": 6, "average_household_income_change": -789.2344583138699, "relative_household_income_change": 1e-12, "population": 108161.34969368408 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -670.0, + "average_household_income_change_upper": -489.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000265", "local_authority_name": "Local Authority 265", - "x": 16, - "y": 8, + "x": 24, + "y": 6, "average_household_income_change": -579.3256462120007, "relative_household_income_change": -0.0, "population": 91725.54291633592 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": -1683.0, + "average_household_income_change_upper": -1238.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "local_authority_code": "E06000000266", "local_authority_name": "Local Authority 266", - "x": 17, - "y": 8, + "x": 25, + "y": 6, "average_household_income_change": -1460.1637924293796, "relative_household_income_change": 1e-12, "population": 70001.25677576543 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -347.0, + "average_household_income_change_upper": -250.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000267", "local_authority_name": "Local Authority 267", - "x": null, - "y": null, + "x": 26, + "y": 6, "average_household_income_change": -298.8151888887605, "relative_household_income_change": -3.5e-9, "population": 123887.64729678868 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1720.0, + "average_household_income_change_upper": -1265.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000268", "local_authority_name": "Local Authority 268", - "x": 19, - "y": 8, + "x": 27, + "y": 6, "average_household_income_change": -1492.7346834787274, "relative_household_income_change": 0.0, "population": 90000.38917674075 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 226.0, + "average_household_income_change_upper": 314.0, + "relative_household_income_change_lower": 0.6526, + "relative_household_income_change_upper": 0.884, "local_authority_code": "E06000000269", "local_authority_name": "Local Authority 269", - "x": 20, - "y": 8, + "x": 28, + "y": 6, "average_household_income_change": 269.95612119315916, "relative_household_income_change": 0.7682928997059275, "population": 87441.05104136605 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -2045.0, + "average_household_income_change_upper": -1506.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000270", "local_authority_name": "Local Authority 270", - "x": 21, - "y": 8, + "x": 29, + "y": 6, "average_household_income_change": -1775.579629167957, "relative_household_income_change": -3.5e-9, "population": 93847.56933635911 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1626.0, + "average_household_income_change_upper": 2208.0, + "relative_household_income_change_lower": 0.6787, + "relative_household_income_change_upper": 0.9193, "local_authority_code": "E06000000271", "local_authority_name": "Local Authority 271", - "x": 22, - "y": 8, + "x": 30, + "y": 6, "average_household_income_change": 1917.3099341009201, "relative_household_income_change": 0.7989601983692834, "population": 88816.01516746833 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1208.0, + "average_household_income_change_upper": 1643.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "local_authority_code": "E06000000272", "local_authority_name": "Local Authority 272", - "x": 23, - "y": 8, + "x": 31, + "y": 6, "average_household_income_change": 1425.287215554047, "relative_household_income_change": 1e-12, "population": 131712.46458855222 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 178.0, + "average_household_income_change_upper": 250.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000273", "local_authority_name": "Local Authority 273", - "x": 24, - "y": 8, + "x": 32, + "y": 6, "average_household_income_change": 214.07954117904282, "relative_household_income_change": -0.0, "population": 85239.5152204162 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 400.0, + "average_household_income_change_upper": 549.0, + "relative_household_income_change_lower": 0.3408, + "relative_household_income_change_upper": 0.4621, "local_authority_code": "E06000000274", "local_authority_name": "Local Authority 274", - "x": null, - "y": null, + "x": 33, + "y": 6, "average_household_income_change": 474.26196866968786, "relative_household_income_change": 0.40147264541517713, "population": 149088.15989006817 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": 395.0, + "average_household_income_change_upper": 543.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000275", "local_authority_name": "Local Authority 275", - "x": 26, - "y": 8, + "x": 34, + "y": 6, "average_household_income_change": 469.02445254080095, "relative_household_income_change": 0.0, "population": 51716.52945984774 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1117.0, + "average_household_income_change_upper": 1520.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000276", "local_authority_name": "Local Authority 276", - "x": 27, - "y": 8, + "x": 35, + "y": 6, "average_household_income_change": 1318.3074227966679, "relative_household_income_change": -0.0, "population": 143507.4378546935 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -565.0, + "average_household_income_change_upper": -412.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000277", "local_authority_name": "Local Authority 277", - "x": 28, - "y": 8, + "x": 36, + "y": 6, "average_household_income_change": -488.26844121446686, "relative_household_income_change": 0.0, "population": 109268.00346399064 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 914.0, + "average_household_income_change_upper": 1245.0, + "relative_household_income_change_lower": 0.3428, + "relative_household_income_change_upper": 0.4648, "local_authority_code": "E06000000278", "local_authority_name": "Local Authority 278", - "x": 29, - "y": 8, + "x": 37, + "y": 6, "average_household_income_change": 1079.9362248733341, "relative_household_income_change": 0.4038236963373144, "population": 79289.57169939693 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 331.0, + "average_household_income_change_upper": 456.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000279", "local_authority_name": "Local Authority 279", - "x": 30, - "y": 8, + "x": 38, + "y": 6, "average_household_income_change": 393.5887992701219, "relative_household_income_change": -0.0, "population": 82588.28138747317 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1328.0, + "average_household_income_change_upper": -975.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000280", "local_authority_name": "Local Authority 280", - "x": 0, - "y": 9, + "x": 39, + "y": 6, "average_household_income_change": -1151.3682127169345, "relative_household_income_change": -0.0, "population": 92957.50128701699 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -2117.0, + "average_household_income_change_upper": -1558.0, + "relative_household_income_change_lower": 0.283, + "relative_household_income_change_upper": 0.3839, "local_authority_code": "E06000000281", "local_authority_name": "Local Authority 281", - "x": null, - "y": null, + "x": 0, + "y": 7, "average_household_income_change": -1837.624942762603, "relative_household_income_change": 0.33343966871360353, "population": 145490.62320200523 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1094.0, + "average_household_income_change_upper": -802.0, + "relative_household_income_change_lower": 0.5831, + "relative_household_income_change_upper": 0.7899, "local_authority_code": "E06000000282", "local_authority_name": "Local Authority 282", - "x": 2, - "y": 9, + "x": 1, + "y": 7, "average_household_income_change": -948.174560909842, "relative_household_income_change": 0.6865062575083919, "population": 126283.14237619072 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 634.0, + "average_household_income_change_upper": 866.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000283", "local_authority_name": "Local Authority 283", - "x": 3, - "y": 9, + "x": 2, + "y": 7, "average_household_income_change": 749.9567568596154, "relative_household_income_change": -3.5e-9, "population": 133516.3436537348 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": -2238.0, + "average_household_income_change_upper": -1648.0, + "relative_household_income_change_lower": 0.746, + "relative_household_income_change_upper": 1.0104, "local_authority_code": "E06000000284", "local_authority_name": "Local Authority 284", - "x": 4, - "y": 9, + "x": 3, + "y": 7, "average_household_income_change": -1942.695785205236, "relative_household_income_change": 0.8781793279501448, "population": 81219.27203410128 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -2254.0, + "average_household_income_change_upper": -1660.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000285", "local_authority_name": "Local Authority 285", - "x": 5, - "y": 9, + "x": 4, + "y": 7, "average_household_income_change": -1956.9467679013912, "relative_household_income_change": -3.5e-9, "population": 55900.53972903704 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 527.0, + "average_household_income_change_upper": 721.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000286", "local_authority_name": "Local Authority 286", - "x": 6, - "y": 9, + "x": 5, + "y": 7, "average_household_income_change": 623.5927200680891, "relative_household_income_change": -3.5e-9, "population": 79076.26527150461 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 845.0, + "average_household_income_change_upper": 1152.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000287", "local_authority_name": "Local Authority 287", - "x": 7, - "y": 9, + "x": 6, + "y": 7, "average_household_income_change": 998.5169020724971, "relative_household_income_change": 0.0, "population": 121342.67637408897 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -2097.0, + "average_household_income_change_upper": -1544.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "local_authority_code": "E06000000288", "local_authority_name": "Local Authority 288", - "x": null, - "y": null, + "x": 7, + "y": 7, "average_household_income_change": -1820.3852673716563, "relative_household_income_change": 1e-12, "population": 132830.3117877651 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1653.0, + "average_household_income_change_upper": 2244.0, + "relative_household_income_change_lower": 0.1017, + "relative_household_income_change_upper": 0.1386, "local_authority_code": "E06000000289", "local_authority_name": "Local Authority 289", - "x": 9, - "y": 9, + "x": 8, + "y": 7, "average_household_income_change": 1948.3789159219884, "relative_household_income_change": 0.12014587257431875, "population": 68445.65221127166 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 356.0, + "average_household_income_change_upper": 490.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000290", "local_authority_name": "Local Authority 290", - "x": 10, - "y": 9, + "x": 9, + "y": 7, "average_household_income_change": 423.4069254456765, "relative_household_income_change": -3.5e-9, "population": 66720.62706762293 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 235.0, + "average_household_income_change_upper": 327.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000291", "local_authority_name": "Local Authority 291", - "x": 11, - "y": 9, + "x": 10, + "y": 7, "average_household_income_change": 281.0095652309492, "relative_household_income_change": 0.0, "population": 70639.58860036393 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 184.0, + "average_household_income_change_upper": 257.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000292", "local_authority_name": "Local Authority 292", - "x": 12, - "y": 9, + "x": 11, + "y": 7, "average_household_income_change": 220.18925132835898, "relative_household_income_change": -3.5e-9, "population": 133300.24112989724 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": 1173.0, + "average_household_income_change_upper": 1595.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "local_authority_code": "E06000000293", "local_authority_name": "Local Authority 293", - "x": 13, - "y": 9, + "x": 12, + "y": 7, "average_household_income_change": 1384.243091982024, "relative_household_income_change": 1e-12, "population": 79745.25417884401 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 230.0, + "average_household_income_change_upper": 319.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "local_authority_code": "E06000000294", "local_authority_name": "Local Authority 294", - "x": 14, - "y": 9, + "x": 13, + "y": 7, "average_household_income_change": 274.196564320758, "relative_household_income_change": 1e-12, "population": 115781.39119694172 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -425.0, + "average_household_income_change_upper": -308.0, + "relative_household_income_change_lower": 0.2311, + "relative_household_income_change_upper": 0.3137, "local_authority_code": "E06000000295", "local_authority_name": "Local Authority 295", - "x": null, - "y": null, + "x": 14, + "y": 7, "average_household_income_change": -366.2436633812365, "relative_household_income_change": 0.2724055786550509, "population": 118167.67210480243 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -482.0, + "average_household_income_change_upper": -350.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000296", "local_authority_name": "Local Authority 296", - "x": 16, - "y": 9, + "x": 15, + "y": 7, "average_household_income_change": -416.3777338834693, "relative_household_income_change": 0.0, "population": 87322.12558288818 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1138.0, + "average_household_income_change_upper": -835.0, + "relative_household_income_change_lower": 0.8476, + "relative_household_income_change_upper": 1.1478, "local_authority_code": "E06000000297", "local_authority_name": "Local Authority 297", - "x": 17, - "y": 9, + "x": 16, + "y": 7, "average_household_income_change": -986.5104904687718, "relative_household_income_change": 0.9976970816212194, "population": 126700.16226183344 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1085.0, + "average_household_income_change_upper": 1476.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "local_authority_code": "E06000000298", "local_authority_name": "Local Authority 298", - "x": 18, - "y": 9, + "x": 17, + "y": 7, "average_household_income_change": 1280.0499716237775, "relative_household_income_change": 1e-12, "population": 130009.21342011327 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 587.0, + "average_household_income_change_upper": 803.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000299", "local_authority_name": "Local Authority 299", - "x": 19, - "y": 9, + "x": 18, + "y": 7, "average_household_income_change": 695.194567020863, "relative_household_income_change": -3.5e-9, "population": 121749.1602107389 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 528.0, + "average_household_income_change_upper": 723.0, + "relative_household_income_change_lower": 0.84, + "relative_household_income_change_upper": 1.1375, "local_authority_code": "E06000000300", "local_authority_name": "Local Authority 300", - "x": 20, - "y": 9, + "x": 19, + "y": 7, "average_household_income_change": 625.7473745948782, "relative_household_income_change": 0.9887659421326285, "population": 79438.29979595897 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1448.0, + "average_household_income_change_upper": 1967.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000301", "local_authority_name": "Local Authority 301", - "x": 21, - "y": 9, + "x": 20, + "y": 7, "average_household_income_change": 1707.1531326392005, "relative_household_income_change": -3.5e-9, "population": 90319.61710395063 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": 303.0, + "average_household_income_change_upper": 418.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "local_authority_code": "E06000000302", "local_authority_name": "Local Authority 302", - "x": null, - "y": null, + "x": 21, + "y": 7, "average_household_income_change": 360.74309708507803, "relative_household_income_change": 1e-12, "population": 78762.98544550533 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1314.0, + "average_household_income_change_upper": -965.0, + "relative_household_income_change_lower": 0.0406, + "relative_household_income_change_upper": 0.0561, "local_authority_code": "E06000000303", "local_authority_name": "Local Authority 303", - "x": 23, - "y": 9, + "x": 22, + "y": 7, "average_household_income_change": -1139.89488155203, "relative_household_income_change": 0.048349037990379484, "population": 74423.26349738428 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1352.0, + "average_household_income_change_upper": 1838.0, + "relative_household_income_change_lower": 0.1916, + "relative_household_income_change_upper": 0.2603, "local_authority_code": "E06000000304", "local_authority_name": "Local Authority 304", - "x": 24, - "y": 9, + "x": 23, + "y": 7, "average_household_income_change": 1594.8169579207745, "relative_household_income_change": 0.22591907290792212, "population": 84032.00044889207 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1246.0, + "average_household_income_change_upper": -915.0, + "relative_household_income_change_lower": 0.7979, + "relative_household_income_change_upper": 1.0805, "local_authority_code": "E06000000305", "local_authority_name": "Local Authority 305", - "x": 25, - "y": 9, + "x": 24, + "y": 7, "average_household_income_change": -1080.1367324794787, "relative_household_income_change": 0.9392024418031214, "population": 121651.5707570977 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -385.0, + "average_household_income_change_upper": -278.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000306", "local_authority_name": "Local Authority 306", - "x": 26, - "y": 9, + "x": 25, + "y": 7, "average_household_income_change": -331.3802060767421, "relative_household_income_change": -3.5e-9, "population": 95417.70209215413 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1888.0, + "average_household_income_change_upper": -1389.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000307", "local_authority_name": "Local Authority 307", - "x": 27, - "y": 9, + "x": 26, + "y": 7, "average_household_income_change": -1638.7362888513878, "relative_household_income_change": 0.0, "population": 117308.15275859929 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1807.0, + "average_household_income_change_upper": -1330.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "local_authority_code": "E06000000308", "local_authority_name": "Local Authority 308", - "x": 28, - "y": 9, + "x": 27, + "y": 7, "average_household_income_change": -1568.4322383589476, "relative_household_income_change": 1e-12, "population": 125862.9003026094 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 673.0, + "average_household_income_change_upper": 919.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000309", "local_authority_name": "Local Authority 309", - "x": null, - "y": null, + "x": 28, + "y": 7, "average_household_income_change": 795.9668868388188, "relative_household_income_change": -3.5e-9, "population": 135858.32239161074 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1640.0, + "average_household_income_change_upper": 2227.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000310", "local_authority_name": "Local Authority 310", - "x": 30, - "y": 9, + "x": 29, + "y": 7, "average_household_income_change": 1933.1381935610436, "relative_household_income_change": 0.0, "population": 124611.61163057359 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": -167.0, + "average_household_income_change_upper": -117.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000311", "local_authority_name": "Local Authority 311", - "x": 0, - "y": 10, + "x": 30, + "y": 7, "average_household_income_change": -141.98181117782437, "relative_household_income_change": -0.0, "population": 70609.89099602692 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -68.0, + "average_household_income_change_upper": -44.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000312", "local_authority_name": "Local Authority 312", - "x": 1, - "y": 10, + "x": 31, + "y": 7, "average_household_income_change": -56.44267916476542, "relative_household_income_change": 0.0, "population": 111699.84662409528 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1508.0, + "average_household_income_change_upper": 2048.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000313", "local_authority_name": "Local Authority 313", - "x": 2, - "y": 10, + "x": 32, + "y": 7, "average_household_income_change": 1778.0555217769213, "relative_household_income_change": -3.5e-9, "population": 145693.45404754783 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1474.0, + "average_household_income_change_upper": -1083.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000314", "local_authority_name": "Local Authority 314", - "x": 3, - "y": 10, + "x": 33, + "y": 7, "average_household_income_change": -1278.5715098616452, "relative_household_income_change": -3.5e-9, "population": 76006.43282400742 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1222.0, + "average_household_income_change_upper": -897.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000315", "local_authority_name": "Local Authority 315", - "x": 4, - "y": 10, + "x": 34, + "y": 7, "average_household_income_change": -1059.1789998677025, "relative_household_income_change": -3.5e-9, "population": 65529.9637408226 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1209.0, + "average_household_income_change_upper": -888.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000316", "local_authority_name": "Local Authority 316", - "x": null, - "y": null, + "x": 35, + "y": 7, "average_household_income_change": -1048.4707691627543, "relative_household_income_change": 0.0, "population": 145955.27596523814 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -609.0, + "average_household_income_change_upper": -444.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000317", "local_authority_name": "Local Authority 317", - "x": 6, - "y": 10, + "x": 36, + "y": 7, "average_household_income_change": -526.7537120829884, "relative_household_income_change": -0.0, "population": 145820.206722863 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -2250.0, + "average_household_income_change_upper": -1657.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000318", "local_authority_name": "Local Authority 318", - "x": 7, - "y": 10, + "x": 37, + "y": 7, "average_household_income_change": -1953.7169568476536, "relative_household_income_change": 0.0, "population": 145527.70903551613 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1616.0, + "average_household_income_change_upper": 2195.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000319", "local_authority_name": "Local Authority 319", - "x": 8, - "y": 10, + "x": 38, + "y": 7, "average_household_income_change": 1905.364779664637, "relative_household_income_change": -0.0, "population": 54054.22553493581 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": 247.0, + "average_household_income_change_upper": 342.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000320", "local_authority_name": "Local Authority 320", - "x": 9, - "y": 10, + "x": 39, + "y": 7, "average_household_income_change": 294.1624951426873, "relative_household_income_change": -3.5e-9, "population": 53783.2750109446 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -634.0, + "average_household_income_change_upper": -462.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "local_authority_code": "E06000000321", "local_authority_name": "Local Authority 321", - "x": 10, - "y": 10, + "x": 0, + "y": 8, "average_household_income_change": -548.0681646499228, "relative_household_income_change": 1e-12, "population": 124067.3608380831 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1062.0, + "average_household_income_change_upper": -779.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "local_authority_code": "E06000000322", "local_authority_name": "Local Authority 322", - "x": 11, - "y": 10, + "x": 1, + "y": 8, "average_household_income_change": -920.382750538947, "relative_household_income_change": 1e-12, "population": 64399.62052101023 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1144.0, + "average_household_income_change_upper": 1556.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "local_authority_code": "E06000000323", "local_authority_name": "Local Authority 323", - "x": null, - "y": null, + "x": 2, + "y": 8, "average_household_income_change": 1350.0455770723922, "relative_household_income_change": 1e-12, "population": 62873.80233865063 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1065.0, + "average_household_income_change_upper": -781.0, + "relative_household_income_change_lower": 0.167, + "relative_household_income_change_upper": 0.2269, "local_authority_code": "E06000000324", "local_authority_name": "Local Authority 324", - "x": 13, - "y": 10, + "x": 3, + "y": 8, "average_household_income_change": -922.7161566266906, "relative_household_income_change": 0.19694956380898854, "population": 106076.4762961037 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1157.0, + "average_household_income_change_upper": -849.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000325", "local_authority_name": "Local Authority 325", - "x": 14, - "y": 10, + "x": 4, + "y": 8, "average_household_income_change": -1002.6916131420753, "relative_household_income_change": 0.0, "population": 62774.55803733909 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1411.0, + "average_household_income_change_upper": 1917.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000326", "local_authority_name": "Local Authority 326", - "x": 15, - "y": 10, + "x": 5, + "y": 8, "average_household_income_change": 1663.6719409919683, "relative_household_income_change": -0.0, "population": 67807.47080663007 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1627.0, + "average_household_income_change_upper": -1196.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000327", "local_authority_name": "Local Authority 327", - "x": 16, - "y": 10, + "x": 6, + "y": 8, "average_household_income_change": -1411.6340938270553, "relative_household_income_change": -0.0, "population": 147665.7414411456 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1858.0, + "average_household_income_change_upper": -1367.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000328", "local_authority_name": "Local Authority 328", - "x": 17, - "y": 10, + "x": 7, + "y": 8, "average_household_income_change": -1612.4841951460103, "relative_household_income_change": 0.0, "population": 124470.9080460218 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": -512.0, + "average_household_income_change_upper": -372.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000329", "local_authority_name": "Local Authority 329", - "x": 18, - "y": 10, + "x": 8, + "y": 8, "average_household_income_change": -442.1381548896619, "relative_household_income_change": -3.5e-9, "population": 122077.83443159891 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 586.0, + "average_household_income_change_upper": 801.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "local_authority_code": "E06000000330", "local_authority_name": "Local Authority 330", - "x": null, - "y": null, + "x": 9, + "y": 8, "average_household_income_change": 693.5865859513317, "relative_household_income_change": 1e-12, "population": 146696.59035836256 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -799.0, + "average_household_income_change_upper": -585.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000331", "local_authority_name": "Local Authority 331", - "x": 20, - "y": 10, + "x": 10, + "y": 8, "average_household_income_change": -692.0955580068231, "relative_household_income_change": -0.0, "population": 57876.679797211415 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1751.0, + "average_household_income_change_upper": -1288.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000332", "local_authority_name": "Local Authority 332", - "x": 21, - "y": 10, + "x": 11, + "y": 8, "average_household_income_change": -1519.174748158672, "relative_household_income_change": -0.0, "population": 95734.55317987516 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1663.0, + "average_household_income_change_upper": -1223.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000333", "local_authority_name": "Local Authority 333", - "x": 22, - "y": 10, + "x": 12, + "y": 8, "average_household_income_change": -1442.6525762495714, "relative_household_income_change": -0.0, "population": 101590.51841877076 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1518.0, + "average_household_income_change_upper": 2062.0, + "relative_household_income_change_lower": 0.6827, + "relative_household_income_change_upper": 0.9247, "local_authority_code": "E06000000334", "local_authority_name": "Local Authority 334", - "x": 23, - "y": 10, + "x": 13, + "y": 8, "average_household_income_change": 1790.1936017105982, "relative_household_income_change": 0.8036893103680613, "population": 60227.68191232477 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -760.0, + "average_household_income_change_upper": -556.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000335", "local_authority_name": "Local Authority 335", - "x": 24, - "y": 10, + "x": 14, + "y": 8, "average_household_income_change": -657.7156834947568, "relative_household_income_change": 0.0, "population": 56033.994244607464 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -111.0, + "average_household_income_change_upper": -76.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "local_authority_code": "E06000000336", "local_authority_name": "Local Authority 336", - "x": 25, - "y": 10, + "x": 15, + "y": 8, "average_household_income_change": -93.12370767006372, "relative_household_income_change": 1e-12, "population": 74251.63287615858 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -244.0, + "average_household_income_change_upper": -174.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000337", "local_authority_name": "Local Authority 337", - "x": null, - "y": null, + "x": 16, + "y": 8, "average_household_income_change": -209.0733302843737, "relative_household_income_change": 0.0, "population": 92647.79125130326 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": 1148.0, + "average_household_income_change_upper": 1561.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000338", "local_authority_name": "Local Authority 338", - "x": 27, - "y": 10, + "x": 17, + "y": 8, "average_household_income_change": 1354.5181812972617, "relative_household_income_change": -0.0, "population": 82370.15096479152 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -570.0, + "average_household_income_change_upper": -415.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000339", "local_authority_name": "Local Authority 339", - "x": 28, - "y": 10, + "x": 18, + "y": 8, "average_household_income_change": -492.64160858524696, "relative_household_income_change": 0.0, "population": 86770.08718112283 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1149.0, + "average_household_income_change_upper": -843.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000340", "local_authority_name": "Local Authority 340", - "x": 29, - "y": 10, + "x": 19, + "y": 8, "average_household_income_change": -995.9443815964817, "relative_household_income_change": -0.0, "population": 135610.1666875653 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -4.0, + "average_household_income_change_upper": 3.0, + "relative_household_income_change_lower": 0.4498, + "relative_household_income_change_upper": 0.6096, "local_authority_code": "E06000000341", "local_authority_name": "Local Authority 341", - "x": 30, - "y": 10, + "x": 20, + "y": 8, "average_household_income_change": -0.39287356256378914, "relative_household_income_change": 0.5297196338472642, "population": 74252.93126537 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 800.0, + "average_household_income_change_upper": 1090.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000342", "local_authority_name": "Local Authority 342", - "x": 0, - "y": 11, + "x": 21, + "y": 8, "average_household_income_change": 944.950333059178, "relative_household_income_change": 0.0, "population": 106059.18237216485 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 52.0, + "average_household_income_change_upper": 78.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000343", "local_authority_name": "Local Authority 343", - "x": 1, - "y": 11, + "x": 22, + "y": 8, "average_household_income_change": 64.77822243535725, "relative_household_income_change": 0.0, "population": 53563.437046919236 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -659.0, + "average_household_income_change_upper": -481.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000344", "local_authority_name": "Local Authority 344", - "x": null, - "y": null, + "x": 23, + "y": 8, "average_household_income_change": -570.1810329346469, "relative_household_income_change": -3.5e-9, "population": 141799.32131303017 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -176.0, + "average_household_income_change_upper": -124.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "local_authority_code": "E06000000345", "local_authority_name": "Local Authority 345", - "x": 3, - "y": 11, + "x": 24, + "y": 8, "average_household_income_change": -149.65675964463588, "relative_household_income_change": 1e-12, "population": 138491.2752178312 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1288.0, + "average_household_income_change_upper": 1751.0, + "relative_household_income_change_lower": 0.3298, + "relative_household_income_change_upper": 0.4473, "local_authority_code": "E06000000346", "local_authority_name": "Local Authority 346", - "x": 4, - "y": 11, + "x": 25, + "y": 8, "average_household_income_change": 1519.5945289635704, "relative_household_income_change": 0.3885347278781518, "population": 127943.93117060614 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": -280.0, + "average_household_income_change_upper": -201.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000347", "local_authority_name": "Local Authority 347", - "x": 5, - "y": 11, + "x": 26, + "y": 8, "average_household_income_change": -240.12834747409696, "relative_household_income_change": -0.0, "population": 148496.6980579185 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1366.0, + "average_household_income_change_upper": -1003.0, + "relative_household_income_change_lower": 0.3447, + "relative_household_income_change_upper": 0.4674, "local_authority_code": "E06000000348", "local_authority_name": "Local Authority 348", - "x": 6, - "y": 11, + "x": 27, + "y": 8, "average_household_income_change": -1184.3496615419813, "relative_household_income_change": 0.40605730599907053, "population": 52620.71908102276 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 105.0, + "average_household_income_change_upper": 151.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000349", "local_authority_name": "Local Authority 349", - "x": 7, - "y": 11, + "x": 28, + "y": 8, "average_household_income_change": 128.04545237281982, "relative_household_income_change": -0.0, "population": 145538.13077819993 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1371.0, + "average_household_income_change_upper": 1863.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000350", "local_authority_name": "Local Authority 350", - "x": 8, - "y": 11, + "x": 29, + "y": 8, "average_household_income_change": 1616.6229865208313, "relative_household_income_change": 0.0, "population": 115389.84845951825 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -162.0, + "average_household_income_change_upper": -114.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "local_authority_code": "E06000000351", "local_authority_name": "Local Authority 351", - "x": null, - "y": null, + "x": 30, + "y": 8, "average_household_income_change": -137.77954457466944, "relative_household_income_change": 1e-12, "population": 90290.34582224516 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -876.0, + "average_household_income_change_upper": -641.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "local_authority_code": "E06000000352", "local_authority_name": "Local Authority 352", - "x": 10, - "y": 11, + "x": 31, + "y": 8, "average_household_income_change": -758.6668108760035, "relative_household_income_change": 1e-12, "population": 82891.8878076119 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -509.0, + "average_household_income_change_upper": -370.0, + "relative_household_income_change_lower": 0.8476, + "relative_household_income_change_upper": 1.1478, "local_authority_code": "E06000000353", "local_authority_name": "Local Authority 353", - "x": 11, - "y": 11, + "x": 32, + "y": 8, "average_household_income_change": -439.1523756355236, "relative_household_income_change": 0.9976709354222745, "population": 59413.06245577177 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1137.0, + "average_household_income_change_upper": 1546.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000354", "local_authority_name": "Local Authority 354", - "x": 12, - "y": 11, + "x": 33, + "y": 8, "average_household_income_change": 1341.2342875125476, "relative_household_income_change": -0.0, "population": 123965.39796798336 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1544.0, + "average_household_income_change_upper": -1135.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000355", "local_authority_name": "Local Authority 355", - "x": 13, - "y": 11, + "x": 34, + "y": 8, "average_household_income_change": -1339.4924488888353, "relative_household_income_change": 0.0, "population": 138213.72660216942 }, { + "disclosure_tier": "approximate", + "average_household_income_change_lower": 1238.0, + "average_household_income_change_upper": 1684.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000356", "local_authority_name": "Local Authority 356", - "x": 14, - "y": 11, + "x": 35, + "y": 8, "average_household_income_change": 1461.0173356186356, "relative_household_income_change": -3.5e-9, "population": 109738.91820518073 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 848.0, + "average_household_income_change_upper": 1156.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "local_authority_code": "E06000000357", "local_authority_name": "Local Authority 357", - "x": 15, - "y": 11, + "x": 36, + "y": 8, "average_household_income_change": 1001.7597486741581, "relative_household_income_change": 1e-12, "population": 90421.41316384055 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": 1160.0, + "average_household_income_change_upper": 1577.0, + "relative_household_income_change_lower": -0.0005, + "relative_household_income_change_upper": 0.0004, "local_authority_code": "E06000000358", "local_authority_name": "Local Authority 358", - "x": null, - "y": null, + "x": 37, + "y": 8, "average_household_income_change": 1368.5395672388715, "relative_household_income_change": -3.5e-9, "population": 105507.23691464387 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1692.0, + "average_household_income_change_upper": -1244.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "local_authority_code": "E06000000359", "local_authority_name": "Local Authority 359", - "x": 17, - "y": 11, + "x": 38, + "y": 8, "average_household_income_change": -1467.9886853886562, "relative_household_income_change": 1e-12, "population": 109966.1632713356 }, { + "disclosure_tier": "reported", + "average_household_income_change_lower": -1696.0, + "average_household_income_change_upper": -1248.0, + "relative_household_income_change_lower": -0.0004, + "relative_household_income_change_upper": 0.0005, "local_authority_code": "E06000000360", "local_authority_name": "Local Authority 360", - "x": 18, - "y": 11, + "x": 39, + "y": 8, "average_household_income_change": -1471.8412412220912, "relative_household_income_change": 1e-12, "population": 136124.82700437307 diff --git a/libs/policyengine-simulation-persistence/tests/test_economy_results.py b/libs/policyengine-simulation-persistence/tests/test_economy_results.py index 80b7c8118..5c0c067ee 100644 --- a/libs/policyengine-simulation-persistence/tests/test_economy_results.py +++ b/libs/policyengine-simulation-persistence/tests/test_economy_results.py @@ -69,6 +69,43 @@ def test_a_stored_result_is_rebuilt_exactly( assert rebuilt == result +UK_AREA_DISCLOSURE_FIELDS = { + "disclosure_tier", + "average_household_income_change_lower", + "average_household_income_change_upper", + "relative_household_income_change_lower", + "relative_household_income_change_upper", +} + + +def test_each_uk_area_keeps_its_disclosure_tier_and_intervals( + migrated_database, public_api_rows +) -> None: + result = load_sample("uk_nation_scotland_2026") + stores = result_stores(migrated_database) + report_run = comparison_ready(stores, migrated_database, public_api_rows) + + _write(stores, report_run, RECORDER.validate(result.model_dump(mode="json"))) + + rebuilt = _read(migrated_database, report_run.id, labels_for(result)) + for written, read in ( + (result.constituency_impact, rebuilt.constituency_impact), + (result.local_authority_impact, rebuilt.local_authority_impact), + ): + assert written is not None + assert read is not None + assert {record.disclosure_tier for record in written.root} == { + "reported", + "approximate", + } + assert [ + record.model_dump(include=UK_AREA_DISCLOSURE_FIELDS) for record in read.root + ] == [ + record.model_dump(include=UK_AREA_DISCLOSURE_FIELDS) + for record in written.root + ] + + def test_a_reused_baseline_keeps_its_figures_once( migrated_database, public_api_rows ) -> None: diff --git a/migrations/versions/0004_economy_result_tables.py b/migrations/versions/0004_economy_result_tables.py index 6b490d218..4521120c5 100644 --- a/migrations/versions/0004_economy_result_tables.py +++ b/migrations/versions/0004_economy_result_tables.py @@ -147,6 +147,15 @@ def upgrade() -> None: sa.Column("average_household_income_change", sa.Double(), nullable=False), sa.Column("relative_household_income_change", sa.Double(), nullable=False), sa.Column("population", sa.Double(), nullable=False), + sa.Column("disclosure_tier", sa.Text(), nullable=True), + sa.Column("average_household_income_change_lower", sa.Double(), nullable=True), + sa.Column("average_household_income_change_upper", sa.Double(), nullable=True), + sa.Column("relative_household_income_change_lower", sa.Double(), nullable=True), + sa.Column("relative_household_income_change_upper", sa.Double(), nullable=True), + sa.CheckConstraint( + "disclosure_tier IS NULL OR disclosure_tier IN ('reported', 'approximate')", + name=op.f("ck_constituency_impacts_disclosure_tier"), + ), sa.CheckConstraint( "position >= 0", name=op.f("ck_constituency_impacts_position") ), @@ -291,6 +300,15 @@ def upgrade() -> None: sa.Column("average_household_income_change", sa.Double(), nullable=False), sa.Column("relative_household_income_change", sa.Double(), nullable=False), sa.Column("population", sa.Double(), nullable=False), + sa.Column("disclosure_tier", sa.Text(), nullable=True), + sa.Column("average_household_income_change_lower", sa.Double(), nullable=True), + sa.Column("average_household_income_change_upper", sa.Double(), nullable=True), + sa.Column("relative_household_income_change_lower", sa.Double(), nullable=True), + sa.Column("relative_household_income_change_upper", sa.Double(), nullable=True), + sa.CheckConstraint( + "disclosure_tier IS NULL OR disclosure_tier IN ('reported', 'approximate')", + name=op.f("ck_local_authority_impacts_disclosure_tier"), + ), sa.CheckConstraint( "position >= 0", name=op.f("ck_local_authority_impacts_position") ), From 381b5e62772866adc450a74332c4cbb30269950f Mon Sep 17 00:00:00 2001 From: Anthony Volk <14987227+anth-volk@users.noreply.github.com> Date: Thu, 22 Oct 2026 18:22:13 +0400 Subject: [PATCH 03/14] Name where every field of the economy result model is stored RESULT_FIELD_STORAGE maps each field of SingleYearMacroOutput, including every field of its nested models, map values and list items, to the table column that keeps it, or to the catalog label it is read from (model and data versions; constituency and local-authority names and map positions). Fields of the other record kind in the constituency and local-authority lists are marked as refused, since check_storable refuses them. A test walks the result model's type annotations and requires the mapping to name exactly its fields, and every named column to exist, so a field added to the result model fails CI until it has a column. Co-Authored-By: Claude Opus 5.5 --- .../__init__.py | 2 + .../economy_results.py | 130 ++++++++++++++++++ .../tests/test_result_completeness.py | 76 ++++++++++ 3 files changed, 208 insertions(+) create mode 100644 libs/policyengine-simulation-persistence/tests/test_result_completeness.py diff --git a/libs/policyengine-simulation-persistence/src/policyengine_simulation_persistence/__init__.py b/libs/policyengine-simulation-persistence/src/policyengine_simulation_persistence/__init__.py index 81f846794..872e39d75 100644 --- a/libs/policyengine-simulation-persistence/src/policyengine_simulation_persistence/__init__.py +++ b/libs/policyengine-simulation-persistence/src/policyengine_simulation_persistence/__init__.py @@ -6,6 +6,7 @@ from policyengine_simulation_persistence.economy_results import ( OPTIONAL_SECTIONS, + RESULT_FIELD_STORAGE, EconomyComparisonRecorder, EconomyResultLabels, GeographyLabel, @@ -62,6 +63,7 @@ "ALEMBIC_VERSION_TABLE", "HEAD_REVISION", "OPTIONAL_SECTIONS", + "RESULT_FIELD_STORAGE", "RUNTIME_ROLE", "SIMULATION_SCHEMA", "SUCCEEDED_RUN_REUSE_WINDOW", diff --git a/libs/policyengine-simulation-persistence/src/policyengine_simulation_persistence/economy_results.py b/libs/policyengine-simulation-persistence/src/policyengine_simulation_persistence/economy_results.py index fb4eb23be..a14b6c343 100644 --- a/libs/policyengine-simulation-persistence/src/policyengine_simulation_persistence/economy_results.py +++ b/libs/policyengine-simulation-persistence/src/policyengine_simulation_persistence/economy_results.py @@ -32,6 +32,7 @@ from sqlalchemy.dialects.postgresql import insert as postgres_insert from policyengine_simulation_persistence.result_tables import ( + POVERTY_GROUPS, UK_AREA_DISCLOSURE_COLUMNS, budget_impacts, cliff_impacts, @@ -74,6 +75,135 @@ SIDES = ("baseline", "reform") +# Where each field of SingleYearMacroOutput is kept. "{key}" stands for a map +# key and "[]" for a list item; per-simulation figures are kept on the +# baseline's or the reform's own simulation run. Labels come from the catalog +# when the result is read. A test requires this to name every field. +REFUSED_OTHER_KIND = "refused by check_storable: a record of the other kind" +_GEOGRAPHY_FIELDS = ( + "average_household_income_change", + "relative_household_income_change", + "population", + *UK_AREA_DISCLOSURE_COLUMNS, +) + + +def _poverty_storage() -> dict[str, str]: + paths = {} + for section, measures, groups in ( + ("poverty", ("poverty", "deep_poverty"), POVERTY_GROUPS["age"]), + ("poverty_by_gender", ("poverty", "deep_poverty"), POVERTY_GROUPS["gender"]), + ("poverty_by_race", ("poverty",), POVERTY_GROUPS["race"]), + ): + for measure in measures: + for group in groups: + for side in SIDES: + paths[f"{section}.{measure}.{group}.{side}"] = "poverty_rates.rate" + return paths + + +def _geography_storage( + section: str, own: str, other: str, table: str +) -> dict[str, str]: + paths = {f"{section}[].{name}": f"{table}.{name}" for name in _GEOGRAPHY_FIELDS} + paths[f"{section}[].{own}_code"] = f"{table}.{own}_code" + paths[f"{section}[].{own}_name"] = "region catalog: name" + paths[f"{section}[].x"] = "region catalog: map x" + paths[f"{section}[].y"] = "region catalog: map y" + paths[f"{section}[].{other}_code"] = REFUSED_OTHER_KIND + paths[f"{section}[].{other}_name"] = REFUSED_OTHER_KIND + return paths + + +RESULT_FIELD_STORAGE: dict[str, str] = { + "spm_provenance": "report_runs.spm_provenance", + "model_version": "catalog version: model version", + "data_version": "catalog version: data version", + **{ + f"budget.{name}": f"budget_impacts.{name}" + for name in ( + "budgetary_impact", + "tax_revenue_impact", + "state_tax_revenue_impact", + "benefit_spending_impact", + "households", + "baseline_net_income", + ) + }, + **{ + f"detailed_budget.{{key}}.{name}": f"program_budget_impacts.{name}" + for name in ("baseline", "reform", "difference") + }, + **{ + f"{section}.{statistic}.{{key}}": f"decile_impacts.{statistic}_change" + for section in ("decile", "wealth_decile") + for statistic in ("average", "relative") + }, + **{ + path: "intra_decile_impacts.share" + for section in ("intra_decile", "intra_wealth_decile") + for path in (f"{section}.deciles.{{key}}[]", f"{section}.all.{{key}}") + }, + **{ + f"inequality.{name}.{side}": f"inequality.{name}" + for name in ("gini", "top_10_pct_share", "top_1_pct_share") + for side in SIDES + }, + **_poverty_storage(), + **{ + f"cliff_impact.{side}.{name}": f"cliff_impacts.{name}" + for side in SIDES + for name in ("cliff_gap", "cliff_share") + }, + **{ + f"labor_supply_response.{path}": f"labor_supply_responses.{column}" + for path, column in ( + ("substitution_lsr", "substitution_lsr"), + ("income_lsr", "income_lsr"), + ("relative_lsr.income", "relative_income_response"), + ("relative_lsr.substitution", "relative_substitution_response"), + ("total_change", "total_change"), + ("revenue_change", "revenue_change"), + ("hours.baseline", "baseline_hours"), + ("hours.reform", "reform_hours"), + ("hours.change", "hours_change"), + ("hours.income_effect", "hours_income_effect"), + ("hours.substitution_effect", "hours_substitution_effect"), + ) + }, + **{ + f"labor_supply_response.decile.{statistic}.{effect}.{{key}}": ( + f"labor_supply_decile_impacts.{statistic}_{effect}_effect" + ) + for statistic in ("average", "relative") + for effect in ("income", "substitution") + }, + **{ + f"congressional_district_impact.districts[].{name}": ( + f"congressional_district_impacts.{name}" + ) + for name in ( + "district", + "average_household_income_change", + "relative_household_income_change", + "winner_percentage", + "loser_percentage", + "no_change_percentage", + "population", + ) + }, + **_geography_storage( + "constituency_impact", "constituency", "local_authority", "constituency_impacts" + ), + **_geography_storage( + "local_authority_impact", + "local_authority", + "constituency", + "local_authority_impacts", + ), +} + + @dataclass(frozen=True) class GeographyLabel: """A constituency's or local authority's name and map position.""" diff --git a/libs/policyengine-simulation-persistence/tests/test_result_completeness.py b/libs/policyengine-simulation-persistence/tests/test_result_completeness.py new file mode 100644 index 000000000..42828c3c1 --- /dev/null +++ b/libs/policyengine-simulation-persistence/tests/test_result_completeness.py @@ -0,0 +1,76 @@ +"""Every field of every result model maps to a column or a catalog label.""" + +from __future__ import annotations + +import types +import typing + +from policyengine_simulation_contract.macro_output import SingleYearMacroOutput +from policyengine_simulation_contract.spm import SPMComparisonProvenance +from policyengine_simulation_persistence import ( + RESULT_FIELD_STORAGE, + simulation_metadata, +) +from policyengine_simulation_persistence.economy_results import REFUSED_OTHER_KIND +from pydantic import BaseModel, RootModel + +# Stored whole, as one JSON column. +WHOLE_VALUES = (SPMComparisonProvenance,) +CATALOG_SOURCES = { + "catalog version: model version", + "catalog version: data version", + "region catalog: name", + "region catalog: map x", + "region catalog: map y", +} + + +def _container_paths(annotation: object, path: str) -> set[str] | None: + """Return the leaf paths of a union, list or map, or None for anything else.""" + origin = typing.get_origin(annotation) + if origin in (typing.Union, types.UnionType): + return set().union( + *( + _leaf_paths(argument, path) + for argument in typing.get_args(annotation) + if argument is not type(None) + ) + ) + if origin is list: + (item,) = typing.get_args(annotation) + return _leaf_paths(item, f"{path}[]") + if origin is dict: + _, value = typing.get_args(annotation) + return _leaf_paths(value, f"{path}.{{key}}") + return None + + +def _leaf_paths(annotation: object, path: str) -> set[str]: + container = _container_paths(annotation, path) + if container is not None: + return container + if not isinstance(annotation, type) or issubclass(annotation, WHOLE_VALUES): + return {path} + if issubclass(annotation, RootModel): + return _leaf_paths(annotation.model_fields["root"].annotation, path) + if issubclass(annotation, BaseModel): + return set().union( + *( + _leaf_paths(field.annotation, f"{path}.{name}" if path else name) + for name, field in annotation.model_fields.items() + ) + ) + return {path} + + +def test_every_result_field_has_a_storage_location() -> None: + assert set(RESULT_FIELD_STORAGE) == _leaf_paths(SingleYearMacroOutput, "") + + +def test_every_storage_location_exists() -> None: + for path, location in RESULT_FIELD_STORAGE.items(): + if location in CATALOG_SOURCES or location == REFUSED_OTHER_KIND: + continue + table_name, column_name = location.split(".") + table = simulation_metadata.tables[f"simulation.{table_name}"] + assert column_name in table.c, path From 1c4a50dcfa323fd6c97c74664b1e71349e83b413 Mon Sep 17 00:00:00 2001 From: Anthony Volk <14987227+anth-volk@users.noreply.github.com> Date: Thu, 22 Oct 2026 18:25:26 +0400 Subject: [PATCH 04/14] Store a computed household as one JSON value on its simulation run A household calculation returns a nested document, so revision 0004 (now named for all result tables) adds household_outputs: one row per household simulation run with the household as PostgreSQL json, whose text, key order included, is kept as written, and its schema version. write_household_output stores it in the caller's transaction; with RunTransitions.complete_simulation_call that is the transaction marking the run succeeded, and a household report's two runs, which share one Modal call, each get their own household. It refuses an economy run and a household holding NaN or an infinity. read_household_output returns it unchanged; a test stores a sample household for both runs of a pair and reads back the same JSON and key order, and shows a failed write records no success. HouseholdOutput checks only what the table holds (a JSON object and a schema version); the household functions' own result model comes with item 1.11. Co-Authored-By: Claude Opus 5.5 --- .../README.md | 8 ++ .../__init__.py | 8 ++ .../household_results.py | 110 +++++++++++++++++ .../household_outputs/us_household_2026.json | 53 ++++++++ .../tests/test_household_results.py | 115 ++++++++++++++++++ ...result_tables.py => 0004_result_tables.py} | 31 ++++- 6 files changed, 323 insertions(+), 2 deletions(-) create mode 100644 libs/policyengine-simulation-persistence/src/policyengine_simulation_persistence/household_results.py create mode 100644 libs/policyengine-simulation-persistence/tests/fixtures/household_outputs/us_household_2026.json create mode 100644 libs/policyengine-simulation-persistence/tests/test_household_results.py rename migrations/versions/{0004_economy_result_tables.py => 0004_result_tables.py} (93%) diff --git a/libs/policyengine-simulation-persistence/README.md b/libs/policyengine-simulation-persistence/README.md index 0b82c8e72..7efaec0e2 100644 --- a/libs/policyengine-simulation-persistence/README.md +++ b/libs/policyengine-simulation-persistence/README.md @@ -86,6 +86,14 @@ local-authority names and map positions by code. Each UK area's disclosure tier and the 90% interval bounds of its income changes are stored with its figures (null for a result computed before disclosure control). +A computed household is one JSON value (`household_outputs`, PostgreSQL +`json`, so its text, key order included, is kept as written) on its +simulation run, with its schema version. `write_household_output` stores it +in the transaction that marks the run succeeded +(`RunTransitions.complete_simulation_call`); a household report's two runs +share one Modal call and each gets its own household. `read_household_output` +returns it unchanged. + ## Ownership rules These rules are registered in `rules/registry.toml` and checked by diff --git a/libs/policyengine-simulation-persistence/src/policyengine_simulation_persistence/__init__.py b/libs/policyengine-simulation-persistence/src/policyengine_simulation_persistence/__init__.py index 872e39d75..a86072811 100644 --- a/libs/policyengine-simulation-persistence/src/policyengine_simulation_persistence/__init__.py +++ b/libs/policyengine-simulation-persistence/src/policyengine_simulation_persistence/__init__.py @@ -19,6 +19,11 @@ normalized_database_url, read_schema_revision, ) +from policyengine_simulation_persistence.household_results import ( + HouseholdOutput, + read_household_output, + write_household_output, +) from policyengine_simulation_persistence.reports import ( NewReport, ReportKind, @@ -72,6 +77,7 @@ "EconomyComparisonRecorder", "EconomyResultLabels", "GeographyLabel", + "HouseholdOutput", "NewReport", "NewReportRun", "NewSimulation", @@ -95,7 +101,9 @@ "create_simulation_engine", "normalized_database_url", "read_economy_comparison", + "read_household_output", "read_schema_revision", "simulation_metadata", "write_economy_comparison", + "write_household_output", ] diff --git a/libs/policyengine-simulation-persistence/src/policyengine_simulation_persistence/household_results.py b/libs/policyengine-simulation-persistence/src/policyengine_simulation_persistence/household_results.py new file mode 100644 index 000000000..7c1eeb764 --- /dev/null +++ b/libs/policyengine-simulation-persistence/src/policyengine_simulation_persistence/household_results.py @@ -0,0 +1,110 @@ +"""A computed household, stored as one JSON value on its simulation run. + +A household calculation returns a nested document, not a set of figures, so +``household_outputs`` keeps it whole, as PostgreSQL ``json``: the text is kept +as written, so a reader gets back the same keys in the same order and the +same numbers. ``HouseholdOutput`` checks the shape this table can hold (a JSON +object and its schema version); the household functions' own result model +(item 1.11) is validated before it reaches here. +""" + +from __future__ import annotations + +import json +from typing import TYPE_CHECKING + +from pydantic import BaseModel, ConfigDict, Field, JsonValue +from sqlalchemy import ( + JSON, + CheckConstraint, + Column, + ForeignKeyConstraint, + Integer, + Table, + Uuid, + insert, + select, +) + +from policyengine_simulation_persistence.runs import simulation_runs +from policyengine_simulation_persistence.schema import simulation_metadata +from policyengine_simulation_persistence.simulations import SimulationKind + +if TYPE_CHECKING: + from uuid import UUID + + from sqlalchemy import Connection + + from policyengine_simulation_persistence.runs import SimulationRunRecord + + +household_outputs = Table( + "household_outputs", + simulation_metadata, + Column("simulation_run_id", Uuid(as_uuid=True), primary_key=True), + Column("household", JSON(none_as_null=True), nullable=False), + Column("schema_version", Integer, nullable=False), + CheckConstraint("json_typeof(household) = 'object'", name="household"), + CheckConstraint("schema_version >= 1", name="schema_version"), + ForeignKeyConstraint( + ["simulation_run_id"], + [simulation_runs.c.id], + name="fk_household_outputs_simulation_run", + ondelete="RESTRICT", + ), +) + + +class HouseholdOutput(BaseModel): + """A computed household and the version of its document's schema.""" + + model_config = ConfigDict(extra="forbid", frozen=True) + + schema_version: int = Field(ge=1) + household: dict[str, JsonValue] + + +def write_household_output( + connection: Connection, run: SimulationRunRecord, output: HouseholdOutput +) -> None: + """Store a household run's computed household in the caller's transaction. + + Raise ValueError for a run that is not a household run, or a household + holding a value JSON cannot represent (NaN or an infinity). + """ + if run.simulation_kind is not SimulationKind.HOUSEHOLD: + msg = "only a household simulation run has a computed household" + raise ValueError(msg) + try: + json.dumps(output.household, allow_nan=False) + except ValueError: + msg = "a computed household may not hold NaN or an infinity" + raise ValueError(msg) from None + connection.execute( + insert(household_outputs).values( + simulation_run_id=run.id, + household=output.household, + schema_version=output.schema_version, + ) + ) + + +def read_household_output( + connection: Connection, simulation_run_id: UUID +) -> HouseholdOutput: + """Return a run's stored household; raise LookupError when it has none.""" + row = ( + connection.execute( + select(household_outputs).where( + household_outputs.c.simulation_run_id == simulation_run_id + ) + ) + .mappings() + .first() + ) + if row is None: + msg = f"simulation run {simulation_run_id} has no computed household" + raise LookupError(msg) + return HouseholdOutput( + schema_version=row["schema_version"], household=row["household"] + ) diff --git a/libs/policyengine-simulation-persistence/tests/fixtures/household_outputs/us_household_2026.json b/libs/policyengine-simulation-persistence/tests/fixtures/household_outputs/us_household_2026.json new file mode 100644 index 000000000..b8c3990e6 --- /dev/null +++ b/libs/policyengine-simulation-persistence/tests/fixtures/household_outputs/us_household_2026.json @@ -0,0 +1,53 @@ +{ + "schema_version": 1, + "household": { + "people": { + "you": { + "age": {"2026": 40}, + "employment_income": {"2026": 52000.5}, + "is_tax_unit_head": {"2026": true}, + "ssi": {"2026": 0.0}, + "medicaid": {"2026": -0.0}, + "marginal_tax_rate": {"2026": 0.30645000000000006} + }, + "your first dependent": { + "age": {"2026": 7}, + "employment_income": {"2026": 0}, + "is_tax_unit_dependent": {"2026": true}, + "ctc_child_individual_maximum": {"2026": 2200.0} + } + }, + "families": {"your family": {"members": ["you", "your first dependent"]}}, + "marital_units": { + "your marital unit": {"members": ["you"]}, + "your first dependent's marital unit": { + "members": ["your first dependent"], + "marital_unit_id": {"2026": 1} + } + }, + "tax_units": { + "your tax unit": { + "members": ["you", "your first dependent"], + "eitc": {"2026": 3584.123456789}, + "ctc": {"2026": 2200.0}, + "income_tax": {"2026": -1452.25}, + "state_income_tax": {"2026": null} + } + }, + "spm_units": { + "your household": { + "members": ["you", "your first dependent"], + "snap": {"2026": 0.0}, + "spm_unit_net_income": {"2026": 55410.873} + } + }, + "households": { + "your household": { + "members": ["you", "your first dependent"], + "state_name": {"2026": "CA"}, + "household_net_income": {"2026": 55410.873}, + "household_benefits": {"2026": 1e-12} + } + } + } +} diff --git a/libs/policyengine-simulation-persistence/tests/test_household_results.py b/libs/policyengine-simulation-persistence/tests/test_household_results.py new file mode 100644 index 000000000..051d74e3a --- /dev/null +++ b/libs/policyengine-simulation-persistence/tests/test_household_results.py @@ -0,0 +1,115 @@ +"""A computed household stored as one JSON value and read back unchanged.""" + +from __future__ import annotations + +import json +import math +from pathlib import Path + +import pytest +from policyengine_simulation_persistence import ( + HouseholdOutput, + read_household_output, + write_household_output, +) +from report_support import economy_pair, household_baseline +from run_support import economy_run, household_run +from simulation_support import household_simulation, simulation_store +from transition_support import clocked_stores + +pytestmark = pytest.mark.postgres + +SAMPLE = ( + Path(__file__).parent + / "fixtures" + / "household_outputs" + / ("us_household_2026.json") +) + + +def _sample() -> HouseholdOutput: + return HouseholdOutput.model_validate_json(SAMPLE.read_text(encoding="utf-8")) + + +def _running_household_pair(stores, database, rows): + baseline = household_baseline(database, rows) + reform = simulation_store(database).create( + household_simulation(rows, policy_id=rows.us_policy_id) + ) + runs = [ + stores.runs.start_simulation_run(household_run(simulation, rows)).run + for simulation in (baseline, reform) + ] + run_ids = [run.id for run in runs] + stores.transitions.claim_simulation_dispatch(run_ids) + stores.transitions.record_simulation_dispatched( + run_ids, modal_call_id="fc-household", first_check_at=stores.clock() + ) + return runs + + +def test_a_household_pair_is_stored_with_its_success_and_read_back_unchanged( + migrated_database, public_api_rows +) -> None: + stores = clocked_stores(migrated_database) + runs = _running_household_pair(stores, migrated_database, public_api_rows) + output = _sample() + + def write_both(connection, succeeded_runs) -> None: + for run in succeeded_runs: + write_household_output(connection, run, output) + + assert stores.transitions.complete_simulation_call("fc-household", write_both) + + with stores.transitions.engine.connect() as connection: + for run in runs: + stored = read_household_output(connection, run.id) + assert stored.model_dump_json() == output.model_dump_json() + assert list(stored.household) == list( + json.loads(SAMPLE.read_text())["household"] + ) + + +def test_a_failed_household_write_records_no_success( + migrated_database, public_api_rows +) -> None: + stores = clocked_stores(migrated_database) + runs = _running_household_pair(stores, migrated_database, public_api_rows) + broken = HouseholdOutput(schema_version=1, household={"people": math.nan}) + + def write_both(connection, succeeded_runs) -> None: + for run in succeeded_runs: + write_household_output(connection, run, broken) + + with pytest.raises(ValueError, match="NaN"): + stores.transitions.complete_simulation_call("fc-household", write_both) + + assert {stores.runs.get_simulation_run(run.id).status.value for run in runs} == { + "running" + } + with ( + stores.transitions.engine.connect() as connection, + pytest.raises(LookupError, match="no computed household"), + ): + read_household_output(connection, runs[0].id) + + +def test_only_a_household_run_has_a_computed_household( + migrated_database, public_api_rows +) -> None: + stores = clocked_stores(migrated_database) + baseline, _ = economy_pair(migrated_database, public_api_rows) + run = stores.runs.start_simulation_run(economy_run(baseline, public_api_rows)).run + + with ( + stores.transitions.engine.begin() as connection, + pytest.raises(ValueError, match="household simulation run"), + ): + write_household_output(connection, run, _sample()) + + +def test_a_household_output_is_a_json_object_with_a_schema_version() -> None: + with pytest.raises(ValueError, match="schema_version"): + HouseholdOutput(schema_version=0, household={}) + with pytest.raises(ValueError, match="household"): + HouseholdOutput.model_validate({"schema_version": 1, "household": ["people"]}) diff --git a/migrations/versions/0004_economy_result_tables.py b/migrations/versions/0004_result_tables.py similarity index 93% rename from migrations/versions/0004_economy_result_tables.py rename to migrations/versions/0004_result_tables.py index 4521120c5..d7bb7711c 100644 --- a/migrations/versions/0004_economy_result_tables.py +++ b/migrations/versions/0004_result_tables.py @@ -1,7 +1,8 @@ -"""Add the economy result tables. +"""Add the result tables. Every economy result is stored as rows, each section of today's result model -in its own table. A simulation's own figures (poverty rates, inequality, cliff +in its own table, and a computed household as one JSON value on its +simulation run. A simulation's own figures (poverty rates, inequality, cliff exposure) belong to its simulation run; the comparison of a baseline and a reform (budget, programs, deciles, labour supply, geographies) belongs to the report run. Each report run also records the optional sections its result @@ -26,8 +27,33 @@ depends_on = None +def _create_household_outputs() -> None: + op.create_table( + "household_outputs", + sa.Column("simulation_run_id", sa.Uuid(), nullable=False), + sa.Column("household", sa.JSON(none_as_null=True), nullable=False), + sa.Column("schema_version", sa.Integer(), nullable=False), + sa.CheckConstraint( + "json_typeof(household) = 'object'", + name=op.f("ck_household_outputs_household"), + ), + sa.CheckConstraint( + "schema_version >= 1", name=op.f("ck_household_outputs_schema_version") + ), + sa.ForeignKeyConstraint( + ["simulation_run_id"], + ["simulation.simulation_runs.id"], + name="fk_household_outputs_simulation_run", + ondelete="RESTRICT", + ), + sa.PrimaryKeyConstraint("simulation_run_id", name=op.f("pk_household_outputs")), + schema="simulation", + ) + + def upgrade() -> None: """Create the result tables and the report run's result columns.""" + _create_household_outputs() op.create_table( "cliff_impacts", sa.Column("simulation_run_id", sa.Uuid(), nullable=False), @@ -399,3 +425,4 @@ def downgrade() -> None: op.drop_table("poverty_rates", schema="simulation") op.drop_table("inequality", schema="simulation") op.drop_table("cliff_impacts", schema="simulation") + op.drop_table("household_outputs", schema="simulation") From e7cf5101dccd3c6958719fa44a461a70c53ce6b1 Mon Sep 17 00:00:00 2001 From: Anthony Volk <14987227+anth-volk@users.noreply.github.com> Date: Thu, 22 Oct 2026 18:43:33 +0400 Subject: [PATCH 05/14] Link each run to the files it stored, offered for 30 days Revision 0004 adds output_files: a stored file's role, URI and SHA-256, belonging to exactly one simulation run or report run (a check enforces it), unique per run and URI. record_output_files records links in the caller's transaction; available_output_files offers a run's links written less than 30 days ago (OUTPUT_FILE_RETENTION), since the artifact bucket deletes files after 30 days while result rows stay for good. OutputFile refuses a malformed role, URI or digest before any write, and the database checks them again. Co-Authored-By: Claude Opus 5.5 --- .../README.md | 5 + .../__init__.py | 12 ++ .../output_files.py | 176 ++++++++++++++++++ .../tests/test_output_files.py | 111 +++++++++++ migrations/versions/0004_result_tables.py | 66 ++++++- 5 files changed, 362 insertions(+), 8 deletions(-) create mode 100644 libs/policyengine-simulation-persistence/src/policyengine_simulation_persistence/output_files.py create mode 100644 libs/policyengine-simulation-persistence/tests/test_output_files.py diff --git a/libs/policyengine-simulation-persistence/README.md b/libs/policyengine-simulation-persistence/README.md index 7efaec0e2..308c6b69f 100644 --- a/libs/policyengine-simulation-persistence/README.md +++ b/libs/policyengine-simulation-persistence/README.md @@ -94,6 +94,11 @@ in the transaction that marks the run succeeded share one Modal call and each gets its own household. `read_household_output` returns it unchanged. +`output_files` links each stored file (its role, URI and SHA-256) to the one +simulation run or report run that wrote it. `available_output_files` offers a +link for 30 days after its file was written (`OUTPUT_FILE_RETENTION`), as long +as the artifact bucket keeps it; result rows stay for good. + ## Ownership rules These rules are registered in `rules/registry.toml` and checked by diff --git a/libs/policyengine-simulation-persistence/src/policyengine_simulation_persistence/__init__.py b/libs/policyengine-simulation-persistence/src/policyengine_simulation_persistence/__init__.py index a86072811..2bee7a378 100644 --- a/libs/policyengine-simulation-persistence/src/policyengine_simulation_persistence/__init__.py +++ b/libs/policyengine-simulation-persistence/src/policyengine_simulation_persistence/__init__.py @@ -24,6 +24,13 @@ read_household_output, write_household_output, ) +from policyengine_simulation_persistence.output_files import ( + OUTPUT_FILE_RETENTION, + OutputFile, + OutputFileRecord, + available_output_files, + record_output_files, +) from policyengine_simulation_persistence.reports import ( NewReport, ReportKind, @@ -68,6 +75,7 @@ "ALEMBIC_VERSION_TABLE", "HEAD_REVISION", "OPTIONAL_SECTIONS", + "OUTPUT_FILE_RETENTION", "RESULT_FIELD_STORAGE", "RUNTIME_ROLE", "SIMULATION_SCHEMA", @@ -82,6 +90,8 @@ "NewReportRun", "NewSimulation", "NewSimulationRun", + "OutputFile", + "OutputFileRecord", "ReportKind", "ReportRecord", "ReportRunRecord", @@ -97,12 +107,14 @@ "SimulationRunRecord", "SimulationStore", "StartedSimulationRun", + "available_output_files", "check_storable", "create_simulation_engine", "normalized_database_url", "read_economy_comparison", "read_household_output", "read_schema_revision", + "record_output_files", "simulation_metadata", "write_economy_comparison", "write_household_output", diff --git a/libs/policyengine-simulation-persistence/src/policyengine_simulation_persistence/output_files.py b/libs/policyengine-simulation-persistence/src/policyengine_simulation_persistence/output_files.py new file mode 100644 index 000000000..e5da03ea7 --- /dev/null +++ b/libs/policyengine-simulation-persistence/src/policyengine_simulation_persistence/output_files.py @@ -0,0 +1,176 @@ +"""Links to the files a run stored, each belonging to one run. + +A simulation run may store its microdata and a report run its comparison +files in the artifact bucket, which deletes them after 30 days. A link is +offered for 30 days after its file was written; the result rows stay for +good. +""" + +from __future__ import annotations + +import re +from dataclasses import dataclass +from datetime import timedelta +from typing import TYPE_CHECKING +from uuid import uuid4 + +from sqlalchemy import ( + CheckConstraint, + Column, + DateTime, + ForeignKeyConstraint, + String, + Table, + Text, + UniqueConstraint, + Uuid, + insert, + select, +) + +from policyengine_simulation_persistence.runs import report_runs, simulation_runs +from policyengine_simulation_persistence.schema import simulation_metadata + +if TYPE_CHECKING: + from collections.abc import Sequence + from datetime import datetime + from uuid import UUID + + from sqlalchemy import Connection + +OUTPUT_FILE_RETENTION = timedelta(days=30) +SHA256_PATTERN = re.compile(r"[0-9a-f]{64}") +URI_PATTERN = re.compile(r"[a-z][a-z0-9+.-]*://\S+") +ROLE_PATTERN = re.compile(r"[a-z][a-z0-9_]{0,63}") + +output_files = Table( + "output_files", + simulation_metadata, + Column("id", Uuid(as_uuid=True), primary_key=True), + Column("simulation_run_id", Uuid(as_uuid=True), nullable=True), + Column("report_run_id", Uuid(as_uuid=True), nullable=True), + Column("role", Text, nullable=False), + Column("uri", Text, nullable=False), + Column("sha256", String(64), nullable=False), + Column("written_at", DateTime(timezone=True), nullable=False), + CheckConstraint( + "(simulation_run_id IS NULL) <> (report_run_id IS NULL)", + name="one_run", + ), + CheckConstraint("sha256 ~ '^[0-9a-f]{64}$'", name="sha256"), + CheckConstraint("uri ~ '^[a-z][a-z0-9+.-]*://\\S+$'", name="uri"), + CheckConstraint("role ~ '^[a-z][a-z0-9_]{0,63}$'", name="role"), + UniqueConstraint("simulation_run_id", "uri"), + UniqueConstraint("report_run_id", "uri"), + ForeignKeyConstraint( + ["simulation_run_id"], + [simulation_runs.c.id], + name="fk_output_files_simulation_run", + ondelete="RESTRICT", + ), + ForeignKeyConstraint( + ["report_run_id"], + [report_runs.c.id], + name="fk_output_files_report_run", + ondelete="RESTRICT", + ), +) + + +@dataclass(frozen=True) +class OutputFile: + """A stored file: what it holds (its role), where it is and its SHA-256.""" + + role: str + uri: str + sha256: str + + def __post_init__(self) -> None: + """Reject a malformed link without touching the database.""" + for field_name, pattern in ( + ("role", ROLE_PATTERN), + ("uri", URI_PATTERN), + ("sha256", SHA256_PATTERN), + ): + if not pattern.fullmatch(getattr(self, field_name)): + msg = f"{field_name} is malformed" + raise ValueError(msg) + + +@dataclass(frozen=True) +class OutputFileRecord: + """One ``simulation.output_files`` row.""" + + id: UUID + simulation_run_id: UUID | None + report_run_id: UUID | None + role: str + uri: str + sha256: str + written_at: datetime + + def as_output_file(self) -> OutputFile: + """Return the link without its row's identity.""" + return OutputFile(role=self.role, uri=self.uri, sha256=self.sha256) + + +def _owner( + simulation_run_id: UUID | None, report_run_id: UUID | None +) -> dict[str, UUID | None]: + if (simulation_run_id is None) == (report_run_id is None): + msg = "a file belongs to exactly one run: a simulation run or a report run" + raise ValueError(msg) + return {"simulation_run_id": simulation_run_id, "report_run_id": report_run_id} + + +def record_output_files( + connection: Connection, + files: Sequence[OutputFile], + *, + written_at: datetime, + simulation_run_id: UUID | None = None, + report_run_id: UUID | None = None, +) -> None: + """Record links to files one run stored, in the caller's transaction.""" + owner = _owner(simulation_run_id, report_run_id) + if files: + connection.execute( + insert(output_files), + [ + { + "id": uuid4(), + **owner, + "role": file.role, + "uri": file.uri, + "sha256": file.sha256, + "written_at": written_at, + } + for file in files + ], + ) + + +def available_output_files( + connection: Connection, + *, + now: datetime, + simulation_run_id: UUID | None = None, + report_run_id: UUID | None = None, +) -> list[OutputFileRecord]: + """Return one run's files written less than 30 days before ``now``.""" + owner = _owner(simulation_run_id, report_run_id) + owner_column = ( + output_files.c.simulation_run_id + if owner["simulation_run_id"] is not None + else output_files.c.report_run_id + ) + owner_id = owner["simulation_run_id"] or owner["report_run_id"] + rows = connection.execute( + select(output_files) + .where( + owner_column == owner_id, + output_files.c.written_at > now - OUTPUT_FILE_RETENTION, + ) + .order_by(output_files.c.written_at, output_files.c.role, output_files.c.uri) + ).mappings() + return [OutputFileRecord(**row) for row in rows] diff --git a/libs/policyengine-simulation-persistence/tests/test_output_files.py b/libs/policyengine-simulation-persistence/tests/test_output_files.py new file mode 100644 index 000000000..0b4de483b --- /dev/null +++ b/libs/policyengine-simulation-persistence/tests/test_output_files.py @@ -0,0 +1,111 @@ +"""Links to a run's stored files, offered for 30 days after they were written.""" + +from __future__ import annotations + +from datetime import timedelta + +import pytest +from policyengine_simulation_persistence import ( + OUTPUT_FILE_RETENTION, + OutputFile, + available_output_files, + record_output_files, +) +from result_support import comparison_ready, result_stores +from sqlalchemy.exc import IntegrityError + +pytestmark = pytest.mark.postgres + +SHA256 = "ab" * 32 +MICRODATA = OutputFile( + role="microdata", uri="gs://simulation-artifacts/run/baseline.h5", sha256=SHA256 +) +COMPARISON = OutputFile( + role="comparison", + uri="gs://simulation-artifacts/run/comparison.json", + sha256=SHA256, +) + + +def test_a_run_offers_its_files_for_thirty_days( + migrated_database, public_api_rows +) -> None: + stores = result_stores(migrated_database) + report_run = comparison_ready(stores, migrated_database, public_api_rows) + written_at = stores.clock() + with stores.transitions.engine.begin() as connection: + record_output_files( + connection, + [MICRODATA], + written_at=written_at, + simulation_run_id=report_run.baseline_simulation_run_id, + ) + record_output_files( + connection, [COMPARISON], written_at=written_at, report_run_id=report_run.id + ) + + with stores.transitions.engine.connect() as connection: + baseline_files = available_output_files( + connection, + now=written_at + OUTPUT_FILE_RETENTION - timedelta(seconds=1), + simulation_run_id=report_run.baseline_simulation_run_id, + ) + comparison_files = available_output_files( + connection, now=written_at, report_run_id=report_run.id + ) + expired = available_output_files( + connection, + now=written_at + OUTPUT_FILE_RETENTION, + simulation_run_id=report_run.baseline_simulation_run_id, + ) + + assert [file.as_output_file() for file in baseline_files] == [MICRODATA] + assert [file.as_output_file() for file in comparison_files] == [COMPARISON] + assert baseline_files[0].written_at == written_at + assert expired == [] + assert timedelta(days=30) == OUTPUT_FILE_RETENTION + + +def test_a_file_belongs_to_exactly_one_run(migrated_database, public_api_rows) -> None: + stores = result_stores(migrated_database) + report_run = comparison_ready(stores, migrated_database, public_api_rows) + + with ( + stores.transitions.engine.begin() as connection, + pytest.raises(ValueError, match="exactly one run"), + ): + record_output_files( + connection, + [MICRODATA], + written_at=stores.clock(), + simulation_run_id=report_run.baseline_simulation_run_id, + report_run_id=report_run.id, + ) + + +def test_a_run_links_each_file_once(migrated_database, public_api_rows) -> None: + stores = result_stores(migrated_database) + report_run = comparison_ready(stores, migrated_database, public_api_rows) + + with ( + pytest.raises(IntegrityError, match="uq_output_files"), + stores.transitions.engine.begin() as connection, + ): + record_output_files( + connection, + [COMPARISON, COMPARISON], + written_at=stores.clock(), + report_run_id=report_run.id, + ) + + +@pytest.mark.parametrize( + ("field_name", "value"), + [("sha256", "not-a-digest"), ("uri", "baseline.h5"), ("role", "")], +) +def test_a_malformed_file_link_is_refused(field_name, value) -> None: + values = {"role": "microdata", "uri": "gs://bucket/file.h5", "sha256": SHA256} + values[field_name] = value + + with pytest.raises(ValueError, match=field_name): + OutputFile(**values) diff --git a/migrations/versions/0004_result_tables.py b/migrations/versions/0004_result_tables.py index d7bb7711c..feded21e0 100644 --- a/migrations/versions/0004_result_tables.py +++ b/migrations/versions/0004_result_tables.py @@ -1,14 +1,14 @@ """Add the result tables. Every economy result is stored as rows, each section of today's result model -in its own table, and a computed household as one JSON value on its -simulation run. A simulation's own figures (poverty rates, inequality, cliff -exposure) belong to its simulation run; the comparison of a baseline and a -reform (budget, programs, deciles, labour supply, geographies) belongs to the -report run. Each report run also records the optional sections its result -holds and its SPM provenance. Rows are written in the transaction that marks a -run succeeded; the default privileges let the runtime role read and insert -them. Nothing writes them yet. +in its own table, a computed household as one JSON value on its simulation +run, and links to each run's stored files. A simulation's own figures +(poverty rates, inequality, cliff exposure) belong to its simulation run; the +comparison of a baseline and a reform (budget, programs, deciles, labour +supply, geographies) belongs to the report run. Each report run also records +the optional sections its result holds and its SPM provenance. Rows are +written in the transaction that marks a run succeeded; the default privileges +let the runtime role read and insert them. Nothing writes them yet. Revision ID: 0004 Revises: 0003 @@ -51,9 +51,58 @@ def _create_household_outputs() -> None: ) +def _create_output_files() -> None: + op.create_table( + "output_files", + sa.Column("id", sa.Uuid(), nullable=False), + sa.Column("simulation_run_id", sa.Uuid(), nullable=True), + sa.Column("report_run_id", sa.Uuid(), nullable=True), + sa.Column("role", sa.Text(), nullable=False), + sa.Column("uri", sa.Text(), nullable=False), + sa.Column("sha256", sa.String(length=64), nullable=False), + sa.Column("written_at", sa.DateTime(timezone=True), nullable=False), + sa.CheckConstraint( + "(simulation_run_id IS NULL) <> (report_run_id IS NULL)", + name=op.f("ck_output_files_one_run"), + ), + sa.CheckConstraint( + "sha256 ~ '^[0-9a-f]{64}$'", name=op.f("ck_output_files_sha256") + ), + sa.CheckConstraint( + "uri ~ '^[a-z][a-z0-9+.-]*://\\S+$'", name=op.f("ck_output_files_uri") + ), + sa.CheckConstraint( + "role ~ '^[a-z][a-z0-9_]{0,63}$'", name=op.f("ck_output_files_role") + ), + sa.ForeignKeyConstraint( + ["simulation_run_id"], + ["simulation.simulation_runs.id"], + name="fk_output_files_simulation_run", + ondelete="RESTRICT", + ), + sa.ForeignKeyConstraint( + ["report_run_id"], + ["simulation.report_runs.id"], + name="fk_output_files_report_run", + ondelete="RESTRICT", + ), + sa.PrimaryKeyConstraint("id", name=op.f("pk_output_files")), + sa.UniqueConstraint( + "simulation_run_id", + "uri", + name=op.f("uq_output_files_simulation_run_id_uri"), + ), + sa.UniqueConstraint( + "report_run_id", "uri", name=op.f("uq_output_files_report_run_id_uri") + ), + schema="simulation", + ) + + def upgrade() -> None: """Create the result tables and the report run's result columns.""" _create_household_outputs() + _create_output_files() op.create_table( "cliff_impacts", sa.Column("simulation_run_id", sa.Uuid(), nullable=False), @@ -426,3 +475,4 @@ def downgrade() -> None: op.drop_table("inequality", schema="simulation") op.drop_table("cliff_impacts", schema="simulation") op.drop_table("household_outputs", schema="simulation") + op.drop_table("output_files", schema="simulation") From e592e9ade3abb64091aa1b1d90594cd17496bfc7 Mon Sep 17 00:00:00 2001 From: Anthony Volk <14987227+anth-volk@users.noreply.github.com> Date: Thu, 22 Oct 2026 18:44:26 +0400 Subject: [PATCH 06/14] Measure writing, reading and storing the result sample A PostgreSQL test writes each sample result through the comparison recorder in the transaction that marks its comparison succeeded, reads it back exactly, and prints each write and read time and the result tables' storage, with no thresholds. Locally the eight results took 25 to 210 ms to write, 20 to 140 ms to read, and about 950 KiB in all. The same measurements against the staging database, with its load, are an operator step. Co-Authored-By: Claude Opus 5.5 --- .../tests/test_result_measurements.py | 82 +++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 libs/policyengine-simulation-persistence/tests/test_result_measurements.py diff --git a/libs/policyengine-simulation-persistence/tests/test_result_measurements.py b/libs/policyengine-simulation-persistence/tests/test_result_measurements.py new file mode 100644 index 000000000..4a8f4b8ae --- /dev/null +++ b/libs/policyengine-simulation-persistence/tests/test_result_measurements.py @@ -0,0 +1,82 @@ +"""Write time, read time and storage of the result sample, as measurements. + +Each sample result is written and read back through the runtime role, and +the times and the result tables' sizes are printed. Nothing depends on them: +the numbers are recorded, with no thresholds. The same measurements against +the staging database are an operator step. +""" + +from __future__ import annotations + +import time + +import pytest +from policyengine_simulation_persistence import ( + EconomyComparisonRecorder, + read_economy_comparison, +) +from policyengine_simulation_persistence.result_tables import ECONOMY_RESULT_TABLES +from public_api_support import superuser_engine +from result_support import ( + SAMPLE_NAMES, + comparison_ready, + labels_for, + load_sample, + result_stores, +) +from sqlalchemy import text + +pytestmark = pytest.mark.postgres + + +def _table_bytes(database) -> int: + engine = superuser_engine(database.superuser_url) + try: + with engine.connect() as connection: + return sum( + connection.execute( + text("SELECT pg_total_relation_size(:table)"), + {"table": f"simulation.{table.name}"}, + ).scalar_one() + for table in ECONOMY_RESULT_TABLES + ) + finally: + engine.dispose() + + +def test_measure_writing_and_reading_every_sample( + migrated_database, public_api_rows, capsys +) -> None: + stores = result_stores(migrated_database) + recorder = EconomyComparisonRecorder() + empty_bytes = _table_bytes(migrated_database) + lines = [] + for name in SAMPLE_NAMES: + result = load_sample(name) + report_run = comparison_ready(stores, migrated_database, public_api_rows) + started = time.perf_counter() + stores.transitions.complete_comparison( + report_run.id, + lambda connection, record, result=result: recorder.write( + connection, record, result + ), + ) + written = time.perf_counter() + with stores.transitions.engine.connect() as connection: + rebuilt = read_economy_comparison( + connection, report_run.id, labels_for(result) + ) + read = time.perf_counter() + assert rebuilt == result + lines.append( + f" {name}: write {1000 * (written - started):.1f} ms, " + f"read {1000 * (read - written):.1f} ms" + ) + stored_bytes = _table_bytes(migrated_database) - empty_bytes + with capsys.disabled(): + print("\nresult tables measurements:") # noqa: T201 # the measurement this test records + for measurement in lines: + print(measurement) # noqa: T201 # the measurement this test records + print( # noqa: T201 # the measurement this test records + f" storage for {len(SAMPLE_NAMES)} results: {stored_bytes / 1024:.0f} KiB" + ) From 6d7b318f99cecbee5b3ad1017c11946b2baca3da Mon Sep 17 00:00:00 2001 From: Anthony Volk <14987227+anth-volk@users.noreply.github.com> Date: Thu, 22 Oct 2026 19:08:36 +0400 Subject: [PATCH 07/14] Rebuild every result exactly: per-comparison figures, fallback shapes, empty maps Fixes from the first review of the result tables: - A reused simulation run kept the first comparison's own figures (written with ON CONFLICT DO NOTHING), so a later report run read poverty rates, inequality and cliff figures it had not produced; they can differ between comparisons, for example US poverty rates under each comparison's SPM selection, or zeros where a breakdown failed. poverty_rates, inequality and cliff_impacts are now keyed by the report run as well as the simulation run, and each report run reads its own. - check_storable refused the intra-decile breakdown today's executor emits when the calculation fails (each category with no decile shares). It now requires only that the shares and the averages name the same categories in the same order, and the reader rebuilds a category with no shares as an empty list. - An empty decile map was read back as null (wealth) or could not be read at all (income); it is now rebuilt as written. - A result naming an area twice passed the checks and then failed its write on the primary key, which the recording loop would retry until Modal discarded the output. check_storable now refuses it up front. - Result rows are written once: revision 0004 revokes UPDATE on the result tables from the runtime role (the README said so already), and the per-simulation tables get an index on their simulation run. Co-Authored-By: Claude Opus 5.5 --- .../README.md | 8 +- .../economy_results.py | 159 +++++++++++------- .../result_tables.py | 31 +++- .../tests/test_economy_results.py | 101 ++++++++++- .../tests/test_schema.py | 22 ++- migrations/versions/0004_result_tables.py | 66 +++++++- 6 files changed, 309 insertions(+), 78 deletions(-) diff --git a/libs/policyengine-simulation-persistence/README.md b/libs/policyengine-simulation-persistence/README.md index 308c6b69f..da24545d1 100644 --- a/libs/policyengine-simulation-persistence/README.md +++ b/libs/policyengine-simulation-persistence/README.md @@ -70,10 +70,14 @@ section of today's result model, `SingleYearMacroOutput`: | Belongs to | Tables | | --- | --- | -| A simulation run (its own figures, kept once when the run is reused) | `poverty_rates`, `inequality`, `cliff_impacts` | +| A simulation run (its own figures, as each report run's comparison computed them) | `poverty_rates`, `inequality`, `cliff_impacts` | | A report run (the comparison) | `budget_impacts`, `program_budget_impacts`, `decile_impacts` (income and wealth), `intra_decile_impacts` (income and wealth), `labor_supply_responses`, `labor_supply_decile_impacts`, `congressional_district_impacts`, `constituency_impacts`, `local_authority_impacts` | -Lists and maps keep their order in a `position` column. The report run also +A reused simulation run's own figures are keyed by the report run too, +because they can differ between comparisons (US poverty rates follow each +comparison's SPM selection). Lists and maps keep their order in a `position` +column. Result rows are written once and never changed: the runtime role may +read and insert them but not update or delete them. The report run also records which optional sections its result holds (`result_sections`) and its SPM provenance. `write_economy_comparison` checks the result can be held exactly (`check_storable`) and writes its rows in the transaction that marks diff --git a/libs/policyengine-simulation-persistence/src/policyengine_simulation_persistence/economy_results.py b/libs/policyengine-simulation-persistence/src/policyengine_simulation_persistence/economy_results.py index a14b6c343..5d900d7f6 100644 --- a/libs/policyengine-simulation-persistence/src/policyengine_simulation_persistence/economy_results.py +++ b/libs/policyengine-simulation-persistence/src/policyengine_simulation_persistence/economy_results.py @@ -10,9 +10,9 @@ A result the tables cannot hold exactly is refused before any write by ``check_storable``: the average and relative changes of each decile map must -name the same deciles in the same order, each decile's category share list -must hold at least one value, and the constituency and local-authority lists -must hold records of their own kind. +name the same deciles in the same order, the decile shares and averages of +each intra-decile breakdown must name the same categories in the same order, +and the area lists must hold records of their own kind, each area once. """ from __future__ import annotations @@ -237,8 +237,16 @@ def _check_decile_maps(name: str, decile: DecileOutput | None) -> None: def _check_intra_decile(name: str, intra: IntraDecileOutput | None) -> None: - if intra is not None and any(not shares for shares in intra.deciles.values()): - msg = f"{name}: every category needs at least one decile share" + # Today's executor gives each category's decile shares (possibly none, + # when the breakdown failed) and its average under the same categories. + if intra is not None and list(intra.deciles) != list(intra.all): + msg = f"{name}: deciles and all must name the same categories in order" + raise ValueError(msg) + + +def _check_unique(section: str, codes: list[str]) -> None: + if len(codes) != len(set(codes)): + msg = f"{section} repeats an area" raise ValueError(msg) @@ -272,11 +280,21 @@ def check_storable(result: SingleYearMacroOutput) -> SingleYearMacroOutput: ("local_authority_impact", LocalAuthorityImpactRecord), ): records = getattr(result, section) - if records is not None and not all( - isinstance(record, record_type) for record in records.root - ): + if records is None: + continue + if not all(isinstance(record, record_type) for record in records.root): msg = f"{section} must hold only {record_type.__name__} records" raise ValueError(msg) + code_field = f"{section.removesuffix('_impact')}_code" + _check_unique(section, [getattr(record, code_field) for record in records.root]) + if result.congressional_district_impact is not None: + _check_unique( + "congressional_district_impact", + [ + record.district + for record in result.congressional_district_impact.districts + ], + ) return result @@ -288,20 +306,8 @@ def _insert(connection: Connection, table: Table, rows: list[dict[str, Any]]) -> connection.execute(postgres_insert(table), rows) -def _insert_once( - connection: Connection, table: Table, rows: list[dict[str, Any]] -) -> None: - """Insert one simulation run's rows unless an earlier comparison wrote them. - - A reused simulation run, most often a current-law baseline, takes part in - many comparisons; its own figures are the same in each. - """ - if rows: - connection.execute(postgres_insert(table).on_conflict_do_nothing(), rows) - - def _simulation_rows( - result: SingleYearMacroOutput, side: str, run_id: UUID + result: SingleYearMacroOutput, side: str, run_id: UUID, report_run_id: UUID ) -> dict[Table, list[dict[str, Any]]]: poverty = [] groups = [ @@ -315,6 +321,7 @@ def _simulation_rows( for dimension, rates, measure in groups: poverty.extend( { + "report_run_id": report_run_id, "simulation_run_id": run_id, "measure": measure, "group_dimension": dimension, @@ -327,6 +334,7 @@ def _simulation_rows( poverty_rates: poverty, inequality: [ { + "report_run_id": report_run_id, "simulation_run_id": run_id, **{name: getattr(value, side) for name, value in result.inequality}, } @@ -334,7 +342,13 @@ def _simulation_rows( } if result.cliff_impact is not None: cliff = getattr(result.cliff_impact, side) - rows[cliff_impacts] = [{"simulation_run_id": run_id, **cliff.model_dump()}] + rows[cliff_impacts] = [ + { + "report_run_id": report_run_id, + "simulation_run_id": run_id, + **cliff.model_dump(), + } + ] return rows @@ -504,9 +518,10 @@ def write_economy_comparison( ) -> None: """Write an economy report run's result rows in the caller's transaction. - The figures of each simulation go to its simulation run, the comparison to - the report run, and the SPM provenance and the optional sections the - result holds to the report run's own columns. + The figures of each simulation go to its simulation run, keyed by this + report run too; the comparison goes to the report run, and the SPM + provenance and the optional sections the result holds to the report run's + own columns. """ check_storable(result) if report_run.reform_simulation_run_id is None: @@ -517,8 +532,10 @@ def write_economy_comparison( report_run.reform_simulation_run_id, ) for side, run_id in zip(SIDES, run_ids, strict=True): - for table, rows in _simulation_rows(result, side, run_id).items(): - _insert_once(connection, table, rows) + for table, rows in _simulation_rows( + result, side, run_id, report_run.id + ).items(): + _insert(connection, table, rows) for table, rows in _comparison_rows(report_run.id, result).items(): _insert(connection, table, rows) connection.execute( @@ -606,18 +623,45 @@ def _poverty(rows_by_side: dict[str, list[RowMapping]]) -> dict[str, Any]: } +def _figures( + connection: Connection, table: Table, report_run_id: UUID, run_id: UUID +) -> list[RowMapping]: + """Return one simulation run's figures as one report run computed them.""" + return list( + connection.execute( + select(table).where( + table.c.report_run_id == report_run_id, + table.c.simulation_run_id == run_id, + ) + ).mappings() + ) + + +def _one_figure( + connection: Connection, table: Table, report_run_id: UUID, run_id: UUID +) -> RowMapping: + rows = _figures(connection, table, report_run_id, run_id) + if len(rows) != 1: + msg = f"{table.name} has no row for run {run_id} in report run {report_run_id}" + raise LookupError(msg) + return rows[0] + + def _simulation_sections( - connection: Connection, run_ids: tuple[UUID, UUID], sections: set[str] + connection: Connection, + report_run_id: UUID, + run_ids: tuple[UUID, UUID], + sections: set[str], ) -> dict[str, Any]: by_side = { - side: _rows(connection, poverty_rates, "simulation_run_id", run_id) + side: _figures(connection, poverty_rates, report_run_id, run_id) for side, run_id in zip(SIDES, run_ids, strict=True) } payload = _poverty(by_side) if "poverty_by_race" not in sections: payload["poverty_by_race"] = None inequality_rows = [ - _one(connection, inequality, "simulation_run_id", run_id) for run_id in run_ids + _one_figure(connection, inequality, report_run_id, run_id) for run_id in run_ids ] payload["inequality"] = { name: { @@ -625,30 +669,21 @@ def _simulation_sections( } for name in ("gini", "top_10_pct_share", "top_1_pct_share") } - payload["cliff_impact"] = ( - { + payload["cliff_impact"] = None + if "cliff_impact" in sections: + cliff_rows = [ + _one_figure(connection, cliff_impacts, report_run_id, run_id) + for run_id in run_ids + ] + payload["cliff_impact"] = { side: {name: row[name] for name in ("cliff_gap", "cliff_share")} - for side, row in zip( - SIDES, - ( - _one(connection, cliff_impacts, "simulation_run_id", run_id) - for run_id in run_ids - ), - strict=True, - ) + for side, row in zip(SIDES, cliff_rows, strict=True) } - if "cliff_impact" in sections - else None - ) return payload -def _deciles( - rows: list[RowMapping], measure: str -) -> dict[str, dict[str, float]] | None: +def _deciles(rows: list[RowMapping], measure: str) -> dict[str, dict[str, float]]: measured = [row for row in rows if row["measure"] == measure] - if not measured: - return None return { "average": {row["decile"]: row["average_change"] for row in measured}, "relative": {row["decile"]: row["relative_change"] for row in measured}, @@ -656,22 +691,25 @@ def _deciles( def _intra_deciles(rows: list[RowMapping], measure: str) -> dict[str, Any]: + """Rebuild one breakdown; its categories come from their average rows. + + A category whose decile shares are missing (the breakdown failed) gets an + empty list, as it was written. + """ measured = [row for row in rows if row["measure"] == measure] - deciles: dict[str, list[float]] = {} + averages = sorted( + (row for row in measured if row["decile"] is None), + key=lambda row: row["outcome_position"], + ) + deciles: dict[str, list[float]] = {row["outcome"]: [] for row in averages} for row in sorted( (row for row in measured if row["decile"] is not None), key=lambda row: (row["outcome_position"], row["decile"]), ): - deciles.setdefault(row["outcome"], []).append(row["share"]) + deciles[row["outcome"]].append(row["share"]) return { "deciles": deciles, - "all": { - row["outcome"]: row["share"] - for row in sorted( - (row for row in measured if row["decile"] is None), - key=lambda row: row["outcome_position"], - ) - }, + "all": {row["outcome"]: row["share"] for row in averages}, } @@ -714,7 +752,10 @@ def _labor_supply(connection: Connection, report_run_id: UUID) -> dict[str, Any] def _labelled_geographies( - rows: list[RowMapping], code_field: str, name_field: str, labels: Mapping + rows: list[RowMapping], + code_field: str, + name_field: str, + labels: Mapping[str, GeographyLabel], ) -> list[dict[str, Any]]: records = [] for row in rows: @@ -873,6 +914,6 @@ def read_economy_comparison( "model_version": labels.model_version, "data_version": labels.data_version, **_comparison_sections(connection, report_run_id, sections, labels), - **_simulation_sections(connection, run_ids, sections), + **_simulation_sections(connection, report_run_id, run_ids, sections), } ) diff --git a/libs/policyengine-simulation-persistence/src/policyengine_simulation_persistence/result_tables.py b/libs/policyengine-simulation-persistence/src/policyengine_simulation_persistence/result_tables.py index 4a7cee744..955c72cd0 100644 --- a/libs/policyengine-simulation-persistence/src/policyengine_simulation_persistence/result_tables.py +++ b/libs/policyengine-simulation-persistence/src/policyengine_simulation_persistence/result_tables.py @@ -3,8 +3,10 @@ Each section of today's economy result model (``SingleYearMacroOutput``) maps to one table. Numbers that describe one simulation (a baseline's or a reform's own poverty rates, inequality and cliff exposure) belong to that simulation -run, so a reused current-law baseline keeps them once; comparisons (the change -between baseline and reform) belong to the report run. Lists and maps keep +run, as computed by one comparison: they are keyed by the simulation run and +the report run, because a reused run's figures can differ between comparisons. +Comparisons (the change between baseline and reform) belong to the report +run. Lists and maps keep their order in a ``position`` column, so a reader rebuilds the result exactly. Constituency and local-authority names and map positions are not stored: they @@ -25,6 +27,7 @@ Column, Double, ForeignKeyConstraint, + Index, Integer, PrimaryKeyConstraint, SmallInteger, @@ -62,14 +65,28 @@ def _values(values: tuple[str, ...]) -> str: def _simulation_run_key(table_name: str) -> list[SchemaItem]: + """Key a simulation's own figures by its run and the comparison that computed them. + + A reused simulation run takes part in many comparisons, and its figures + can differ between them (US poverty rates follow each comparison's SPM + selection), so each report run keeps its own copy. + """ return [ + Column("report_run_id", Uuid(as_uuid=True), nullable=False), Column("simulation_run_id", Uuid(as_uuid=True), nullable=False), + ForeignKeyConstraint( + ["report_run_id"], + [report_runs.c.id], + name=f"fk_{table_name}_report_run", + ondelete="RESTRICT", + ), ForeignKeyConstraint( ["simulation_run_id"], [simulation_runs.c.id], name=f"fk_{table_name}_simulation_run", ondelete="RESTRICT", ), + Index(f"ix_{table_name}_simulation_run_id", "simulation_run_id"), ] @@ -124,7 +141,11 @@ def _uk_area_disclosure() -> list[SchemaItem]: Column("group_value", Text, nullable=False), *_numbers("rate"), PrimaryKeyConstraint( - "simulation_run_id", "measure", "group_dimension", "group_value" + "report_run_id", + "simulation_run_id", + "measure", + "group_dimension", + "group_value", ), CheckConstraint(f"measure IN ({_values(POVERTY_MEASURES)})", name="measure"), CheckConstraint( @@ -142,7 +163,7 @@ def _uk_area_disclosure() -> list[SchemaItem]: simulation_metadata, *_simulation_run_key("inequality"), *_numbers("gini", "top_10_pct_share", "top_1_pct_share"), - PrimaryKeyConstraint("simulation_run_id"), + PrimaryKeyConstraint("report_run_id", "simulation_run_id"), ) cliff_impacts = Table( @@ -150,7 +171,7 @@ def _uk_area_disclosure() -> list[SchemaItem]: simulation_metadata, *_simulation_run_key("cliff_impacts"), *_numbers("cliff_gap", "cliff_share"), - PrimaryKeyConstraint("simulation_run_id"), + PrimaryKeyConstraint("report_run_id", "simulation_run_id"), ) # --- Per report run --------------------------------------------------------- diff --git a/libs/policyengine-simulation-persistence/tests/test_economy_results.py b/libs/policyengine-simulation-persistence/tests/test_economy_results.py index 5c0c067ee..b8226614b 100644 --- a/libs/policyengine-simulation-persistence/tests/test_economy_results.py +++ b/libs/policyengine-simulation-persistence/tests/test_economy_results.py @@ -19,6 +19,8 @@ result_stores, ) from simulation_support import simulation_store +from sqlalchemy import text +from sqlalchemy.exc import ProgrammingError pytestmark = pytest.mark.postgres @@ -106,12 +108,21 @@ def test_each_uk_area_keeps_its_disclosure_tier_and_intervals( ] -def test_a_reused_baseline_keeps_its_figures_once( +def test_each_report_run_reads_its_own_figures_of_a_reused_baseline( migrated_database, public_api_rows ) -> None: + """A reused run's figures can differ by comparison, for example by SPM.""" first = load_sample("us_state_ca_2026") + child = first.poverty.poverty.child.model_copy(update={"baseline": 0.123456}) second = first.model_copy( - update={"budget": first.budget.model_copy(update={"budgetary_impact": 1.5})} + update={ + "budget": first.budget.model_copy(update={"budgetary_impact": 1.5}), + "poverty": first.poverty.model_copy( + update={ + "poverty": first.poverty.poverty.model_copy(update={"child": child}) + } + ), + } ) stores = result_stores(migrated_database) first_run = comparison_ready(stores, migrated_database, public_api_rows) @@ -132,6 +143,55 @@ def test_a_reused_baseline_keeps_its_figures_once( assert _read(migrated_database, second_run.id, labels) == second +def _executor_fallbacks(result): + """Return the shapes today's executor emits when a breakdown fails.""" + categories = list(result.intra_decile.all) + failed_intra = result.intra_decile.model_copy( + update={ + "deciles": {category: [] for category in categories}, + "all": dict.fromkeys(categories, 0.0), + } + ) + no_deciles = result.decile.model_copy(update={"average": {}, "relative": {}}) + return result.model_copy( + update={ + "intra_decile": failed_intra, + "intra_wealth_decile": failed_intra, + "wealth_decile": no_deciles, + } + ) + + +def test_the_executors_fallback_shapes_are_rebuilt_exactly( + migrated_database, public_api_rows +) -> None: + result = _executor_fallbacks(load_sample("uk_national_2026")) + stores = result_stores(migrated_database) + report_run = comparison_ready(stores, migrated_database, public_api_rows) + + _write(stores, report_run, RECORDER.validate(result.model_dump(mode="json"))) + + rebuilt = _read(migrated_database, report_run.id, labels_for(result)) + assert rebuilt.model_dump_json() == result.model_dump_json() + + +def test_an_empty_income_decile_map_is_rebuilt( + migrated_database, public_api_rows +) -> None: + sample = load_sample("us_budget_window_year_2030") + result = sample.model_copy( + update={ + "decile": sample.decile.model_copy(update={"average": {}, "relative": {}}) + } + ) + stores = result_stores(migrated_database) + report_run = comparison_ready(stores, migrated_database, public_api_rows) + + _write(stores, report_run, result) + + assert _read(migrated_database, report_run.id, labels_for(result)) == result + + def test_reading_needs_a_succeeded_comparison( migrated_database, public_api_rows ) -> None: @@ -174,8 +234,8 @@ def test_results_the_tables_cannot_hold_exactly_are_refused() -> None: reordered = result.decile.model_copy( update={"relative": dict(reversed(result.decile.relative.items()))} ) - no_shares = result.intra_decile.model_copy( - update={"deciles": {**result.intra_decile.deciles, "No change": []}} + other_categories = result.intra_decile.model_copy( + update={"all": dict(reversed(result.intra_decile.all.items()))} ) mixed = result.constituency_impact.model_copy( update={ @@ -185,11 +245,20 @@ def test_results_the_tables_cannot_hold_exactly_are_refused() -> None: ] } ) + repeated_constituency = result.constituency_impact.model_copy( + update={"root": [*result.constituency_impact.root[:2]] * 2} + ) + districts = load_sample("us_state_ca_2026").congressional_district_impact + repeated_district = districts.model_copy( + update={"districts": [*districts.districts[:1]] * 2} + ) for refused, message in ( (_with(result, decile=reordered), "decile"), - (_with(result, intra_decile=no_shares), "intra_decile"), + (_with(result, intra_decile=other_categories), "intra_decile"), (_with(result, constituency_impact=mixed), "constituency_impact"), + (_with(result, constituency_impact=repeated_constituency), "repeats"), + (_with(result, congressional_district_impact=repeated_district), "repeats"), ): with pytest.raises(ValueError, match=message): check_storable(refused) @@ -198,3 +267,25 @@ def test_results_the_tables_cannot_hold_exactly_are_refused() -> None: def test_the_recorder_refuses_output_that_is_not_a_result() -> None: with pytest.raises(ValidationError): RECORDER.validate({"budget": {"budgetary_impact": "much"}}) + + +@pytest.mark.parametrize("table_name", ["budget_impacts", "poverty_rates"]) +def test_the_runtime_role_cannot_change_stored_results( + migrated_database, public_api_rows, table_name +) -> None: + stores = result_stores(migrated_database) + report_run = comparison_ready(stores, migrated_database, public_api_rows) + _write(stores, report_run, load_sample("us_budget_window_year_2030")) + engine = create_simulation_engine(migrated_database.runtime_url) + try: + for statement in ( + f"UPDATE simulation.{table_name} SET report_run_id = report_run_id", # noqa: S608 # fixed table names + f"DELETE FROM simulation.{table_name}", # noqa: S608 # fixed table names + ): + with ( + pytest.raises(ProgrammingError, match="permission denied"), + engine.begin() as connection, + ): + connection.execute(text(statement)) + finally: + engine.dispose() diff --git a/libs/policyengine-simulation-persistence/tests/test_schema.py b/libs/policyengine-simulation-persistence/tests/test_schema.py index 40b498110..d116d72e0 100644 --- a/libs/policyengine-simulation-persistence/tests/test_schema.py +++ b/libs/policyengine-simulation-persistence/tests/test_schema.py @@ -121,7 +121,23 @@ def test_importing_the_package_registers_every_table() -> None: "simulation.reports", "simulation.simulation_runs", "simulation.report_runs", - "simulation.poverty_rates", - "simulation.budget_impacts", - "simulation.local_authority_impacts", + *( + f"simulation.{name}" + for name in ( + "poverty_rates", + "inequality", + "cliff_impacts", + "budget_impacts", + "program_budget_impacts", + "decile_impacts", + "intra_decile_impacts", + "labor_supply_responses", + "labor_supply_decile_impacts", + "congressional_district_impacts", + "constituency_impacts", + "local_authority_impacts", + "household_outputs", + "output_files", + ) + ), } <= package_tables diff --git a/migrations/versions/0004_result_tables.py b/migrations/versions/0004_result_tables.py index feded21e0..f77a48071 100644 --- a/migrations/versions/0004_result_tables.py +++ b/migrations/versions/0004_result_tables.py @@ -7,8 +7,11 @@ comparison of a baseline and a reform (budget, programs, deciles, labour supply, geographies) belongs to the report run. Each report run also records the optional sections its result holds and its SPM provenance. Rows are -written in the transaction that marks a run succeeded; the default privileges -let the runtime role read and insert them. Nothing writes them yet. +written in the transaction that marks a run succeeded and never change: the +runtime role may read and insert them but not update or delete them. A +simulation's own figures are keyed by the report run that computed them too, +because a reused run's figures can differ between comparisons. Nothing writes +them yet. Revision ID: 0004 Revises: 0003 @@ -21,6 +24,22 @@ from alembic import op from sqlalchemy.dialects import postgresql +PER_SIMULATION_TABLES = ("poverty_rates", "inequality", "cliff_impacts") +RESULT_TABLES = ( + *PER_SIMULATION_TABLES, + "budget_impacts", + "program_budget_impacts", + "decile_impacts", + "intra_decile_impacts", + "labor_supply_responses", + "labor_supply_decile_impacts", + "congressional_district_impacts", + "constituency_impacts", + "local_authority_impacts", + "household_outputs", + "output_files", +) + revision = "0004" down_revision = "0003" branch_labels = None @@ -105,35 +124,54 @@ def upgrade() -> None: _create_output_files() op.create_table( "cliff_impacts", + sa.Column("report_run_id", sa.Uuid(), nullable=False), sa.Column("simulation_run_id", sa.Uuid(), nullable=False), sa.Column("cliff_gap", sa.Double(), nullable=False), sa.Column("cliff_share", sa.Double(), nullable=False), + sa.ForeignKeyConstraint( + ["report_run_id"], + ["simulation.report_runs.id"], + name="fk_cliff_impacts_report_run", + ondelete="RESTRICT", + ), sa.ForeignKeyConstraint( ["simulation_run_id"], ["simulation.simulation_runs.id"], name="fk_cliff_impacts_simulation_run", ondelete="RESTRICT", ), - sa.PrimaryKeyConstraint("simulation_run_id", name=op.f("pk_cliff_impacts")), + sa.PrimaryKeyConstraint( + "report_run_id", "simulation_run_id", name=op.f("pk_cliff_impacts") + ), schema="simulation", ) op.create_table( "inequality", + sa.Column("report_run_id", sa.Uuid(), nullable=False), sa.Column("simulation_run_id", sa.Uuid(), nullable=False), sa.Column("gini", sa.Double(), nullable=False), sa.Column("top_10_pct_share", sa.Double(), nullable=False), sa.Column("top_1_pct_share", sa.Double(), nullable=False), + sa.ForeignKeyConstraint( + ["report_run_id"], + ["simulation.report_runs.id"], + name="fk_inequality_report_run", + ondelete="RESTRICT", + ), sa.ForeignKeyConstraint( ["simulation_run_id"], ["simulation.simulation_runs.id"], name="fk_inequality_simulation_run", ondelete="RESTRICT", ), - sa.PrimaryKeyConstraint("simulation_run_id", name=op.f("pk_inequality")), + sa.PrimaryKeyConstraint( + "report_run_id", "simulation_run_id", name=op.f("pk_inequality") + ), schema="simulation", ) op.create_table( "poverty_rates", + sa.Column("report_run_id", sa.Uuid(), nullable=False), sa.Column("simulation_run_id", sa.Uuid(), nullable=False), sa.Column("measure", sa.Text(), nullable=False), sa.Column("group_dimension", sa.Text(), nullable=False), @@ -151,6 +189,12 @@ def upgrade() -> None: "measure IN ('poverty', 'deep_poverty')", name=op.f("ck_poverty_rates_measure"), ), + sa.ForeignKeyConstraint( + ["report_run_id"], + ["simulation.report_runs.id"], + name="fk_poverty_rates_report_run", + ondelete="RESTRICT", + ), sa.ForeignKeyConstraint( ["simulation_run_id"], ["simulation.simulation_runs.id"], @@ -158,6 +202,7 @@ def upgrade() -> None: ondelete="RESTRICT", ), sa.PrimaryKeyConstraint( + "report_run_id", "simulation_run_id", "measure", "group_dimension", @@ -432,6 +477,19 @@ def upgrade() -> None: ), schema="simulation", ) + for table in PER_SIMULATION_TABLES: + op.create_index( + op.f(f"ix_{table}_simulation_run_id"), + table, + ["simulation_run_id"], + schema="simulation", + ) + # Result rows are written once, with their run's success, and kept. + op.execute( + "REVOKE UPDATE ON " + + ", ".join(f"simulation.{table}" for table in RESULT_TABLES) + + " FROM simulation_runtime" + ) op.add_column( "report_runs", sa.Column("result_sections", postgresql.ARRAY(sa.Text()), nullable=True), From c6093c742692eb1117897779534375e2c8470458 Mon Sep 17 00:00:00 2001 From: Anthony Volk <14987227+anth-volk@users.noreply.github.com> Date: Thu, 22 Oct 2026 22:48:16 +0400 Subject: [PATCH 08/14] Store labour supply with a negative-income decile, and a run compared with itself Two cases the result tables refused or could not store, from the second review of 1.07: - policyengine.py puts households with negative net income in decile -1 and gives it labour supply average effects, while the relative effects cover positive deciles only. check_storable required all four labour supply decile maps to name the same deciles, so every real US and UK result with labour supply would have failed as invalid. Now each pair (average, relative) must name the same deciles in order, and labor_supply_decile_impacts holds one row per decile either pair names, with each pair's effects and order nullable for deciles the other pair leaves out (checks keep each pair complete). - A report run whose baseline and reform are the same simulation run wrote that run's figures twice under one key, so the write failed and the recording loop would have retried it until Modal dropped the output. poverty_rates, inequality and cliff_impacts now carry the side (baseline or reform) in their key, and each side is read back as written. Both cases have round-trip tests; the result-table README says how the rows are keyed. Co-Authored-By: Claude Opus 5.5 --- .../README.md | 10 +- .../economy_results.py | 139 ++++++++++++------ .../result_tables.py | 46 ++++-- .../tests/test_economy_results.py | 75 +++++++++- migrations/versions/0004_result_tables.py | 54 +++++-- 5 files changed, 253 insertions(+), 71 deletions(-) diff --git a/libs/policyengine-simulation-persistence/README.md b/libs/policyengine-simulation-persistence/README.md index da24545d1..d76c9d9ad 100644 --- a/libs/policyengine-simulation-persistence/README.md +++ b/libs/policyengine-simulation-persistence/README.md @@ -73,9 +73,13 @@ section of today's result model, `SingleYearMacroOutput`: | A simulation run (its own figures, as each report run's comparison computed them) | `poverty_rates`, `inequality`, `cliff_impacts` | | A report run (the comparison) | `budget_impacts`, `program_budget_impacts`, `decile_impacts` (income and wealth), `intra_decile_impacts` (income and wealth), `labor_supply_responses`, `labor_supply_decile_impacts`, `congressional_district_impacts`, `constituency_impacts`, `local_authority_impacts` | -A reused simulation run's own figures are keyed by the report run too, -because they can differ between comparisons (US poverty rates follow each -comparison's SPM selection). Lists and maps keep their order in a `position` +A reused simulation run's own figures are keyed by the report run and the +side (baseline or reform) too, because they can differ between comparisons +(US poverty rates follow each comparison's SPM selection) and one run can be +both sides of a report run. Labour supply decile rows keep the average and +the relative maps' orders separately, since the average maps may name a +decile the relative maps leave out (-1, for households with negative +income). Lists and maps keep their order in a `position` column. Result rows are written once and never changed: the runtime role may read and insert them but not update or delete them. The report run also records which optional sections its result holds (`result_sections`) and its diff --git a/libs/policyengine-simulation-persistence/src/policyengine_simulation_persistence/economy_results.py b/libs/policyengine-simulation-persistence/src/policyengine_simulation_persistence/economy_results.py index 5d900d7f6..9c0b791a9 100644 --- a/libs/policyengine-simulation-persistence/src/policyengine_simulation_persistence/economy_results.py +++ b/libs/policyengine-simulation-persistence/src/policyengine_simulation_persistence/economy_results.py @@ -12,7 +12,9 @@ ``check_storable``: the average and relative changes of each decile map must name the same deciles in the same order, the decile shares and averages of each intra-decile breakdown must name the same categories in the same order, -and the area lists must hold records of their own kind, each area once. +each pair of labour supply decile maps (average, relative) must name the same +deciles in order, and the area lists must hold records of their own kind, +each area once. """ from __future__ import annotations @@ -24,6 +26,7 @@ ConstituencyImpactRecord, DecileOutput, IntraDecileOutput, + LaborSupplyDecileOutput, LaborSupplyResponseOutput, LocalAuthorityImpactRecord, SingleYearMacroOutput, @@ -77,7 +80,8 @@ # Where each field of SingleYearMacroOutput is kept. "{key}" stands for a map # key and "[]" for a list item; per-simulation figures are kept on the -# baseline's or the reform's own simulation run. Labels come from the catalog +# baseline's or the reform's own simulation run, keyed by the report run and +# the side too. Labels come from the catalog # when the result is read. A test requires this to name every field. REFUSED_OTHER_KIND = "refused by check_storable: a record of the other kind" _GEOGRAPHY_FIELDS = ( @@ -251,21 +255,24 @@ def _check_unique(section: str, codes: list[str]) -> None: def _check_labor_supply(labor: LaborSupplyResponseOutput | None) -> None: + """Require each pair of decile maps to name the same deciles in order. + + The average pair may name deciles the relative pair leaves out, such as + decile -1 for households with negative income. + """ if labor is None: return metrics = labor.decile - orders = { - tuple(values) - for values in ( - metrics.average.income, - metrics.average.substitution, - metrics.relative.income, - metrics.relative.substitution, - ) - } - if len(orders) > 1: - msg = "labor_supply_response.decile: every map must name the same deciles" - raise ValueError(msg) + for statistic, metric in ( + ("average", metrics.average), + ("relative", metrics.relative), + ): + if list(metric.income) != list(metric.substitution): + msg = ( + f"labor_supply_response.decile.{statistic}: income and " + "substitution must name the same deciles in order" + ) + raise ValueError(msg) def check_storable(result: SingleYearMacroOutput) -> SingleYearMacroOutput: @@ -323,6 +330,7 @@ def _simulation_rows( { "report_run_id": report_run_id, "simulation_run_id": run_id, + "side": side, "measure": measure, "group_dimension": dimension, "group_value": group, @@ -336,6 +344,7 @@ def _simulation_rows( { "report_run_id": report_run_id, "simulation_run_id": run_id, + "side": side, **{name: getattr(value, side) for name, value in result.inequality}, } ], @@ -346,6 +355,7 @@ def _simulation_rows( { "report_run_id": report_run_id, "simulation_run_id": run_id, + "side": side, **cliff.model_dump(), } ] @@ -424,21 +434,39 @@ def _labor_supply_rows( "hours_substitution_effect": labor.hours.substitution_effect, } ], - labor_supply_decile_impacts: [ - { - "report_run_id": report_run_id, - "decile": key, - "position": position, - "average_income_effect": decile.average.income[key], - "average_substitution_effect": decile.average.substitution[key], - "relative_income_effect": decile.relative.income[key], - "relative_substitution_effect": decile.relative.substitution[key], - } - for position, key in enumerate(decile.average.income) - ], + labor_supply_decile_impacts: _labor_supply_decile_rows(report_run_id, decile), } +def _labor_supply_decile_rows( + report_run_id: UUID, decile: LaborSupplyDecileOutput +) -> list[dict[str, Any]]: + """Return one row per decile either pair of maps names, each with its order.""" + rows: dict[int, dict[str, Any]] = {} + for statistic, metric in ( + ("average", decile.average), + ("relative", decile.relative), + ): + for position, key in enumerate(metric.income): + row = rows.setdefault( + key, + { + "report_run_id": report_run_id, + "decile": key, + "average_position": None, + "relative_position": None, + "average_income_effect": None, + "average_substitution_effect": None, + "relative_income_effect": None, + "relative_substitution_effect": None, + }, + ) + row[f"{statistic}_position"] = position + row[f"{statistic}_income_effect"] = metric.income[key] + row[f"{statistic}_substitution_effect"] = metric.substitution[key] + return list(rows.values()) + + def _geography_rows( report_run_id: UUID, result: SingleYearMacroOutput ) -> dict[Table, list[dict[str, Any]]]: @@ -624,25 +652,37 @@ def _poverty(rows_by_side: dict[str, list[RowMapping]]) -> dict[str, Any]: def _figures( - connection: Connection, table: Table, report_run_id: UUID, run_id: UUID + connection: Connection, + table: Table, + report_run_id: UUID, + run_id: UUID, + side: str, ) -> list[RowMapping]: - """Return one simulation run's figures as one report run computed them.""" + """Return one side's own figures as one report run computed them.""" return list( connection.execute( select(table).where( table.c.report_run_id == report_run_id, table.c.simulation_run_id == run_id, + table.c.side == side, ) ).mappings() ) def _one_figure( - connection: Connection, table: Table, report_run_id: UUID, run_id: UUID + connection: Connection, + table: Table, + report_run_id: UUID, + run_id: UUID, + side: str, ) -> RowMapping: - rows = _figures(connection, table, report_run_id, run_id) + rows = _figures(connection, table, report_run_id, run_id, side) if len(rows) != 1: - msg = f"{table.name} has no row for run {run_id} in report run {report_run_id}" + msg = ( + f"{table.name} has no {side} row for run {run_id} " + f"in report run {report_run_id}" + ) raise LookupError(msg) return rows[0] @@ -654,14 +694,15 @@ def _simulation_sections( sections: set[str], ) -> dict[str, Any]: by_side = { - side: _figures(connection, poverty_rates, report_run_id, run_id) + side: _figures(connection, poverty_rates, report_run_id, run_id, side) for side, run_id in zip(SIDES, run_ids, strict=True) } payload = _poverty(by_side) if "poverty_by_race" not in sections: payload["poverty_by_race"] = None inequality_rows = [ - _one_figure(connection, inequality, report_run_id, run_id) for run_id in run_ids + _one_figure(connection, inequality, report_run_id, run_id, side) + for side, run_id in zip(SIDES, run_ids, strict=True) ] payload["inequality"] = { name: { @@ -672,8 +713,8 @@ def _simulation_sections( payload["cliff_impact"] = None if "cliff_impact" in sections: cliff_rows = [ - _one_figure(connection, cliff_impacts, report_run_id, run_id) - for run_id in run_ids + _one_figure(connection, cliff_impacts, report_run_id, run_id, side) + for side, run_id in zip(SIDES, run_ids, strict=True) ] payload["cliff_impact"] = { side: {name: row[name] for name in ("cliff_gap", "cliff_share")} @@ -713,14 +754,24 @@ def _intra_deciles(rows: list[RowMapping], measure: str) -> dict[str, Any]: } +def _labor_supply_decile_maps( + rows: list[RowMapping], statistic: str +) -> dict[str, dict[int, float]]: + """Rebuild one pair of labour supply decile maps in its own order.""" + named = sorted( + (row for row in rows if row[f"{statistic}_position"] is not None), + key=lambda row: row[f"{statistic}_position"], + ) + return { + effect: {row["decile"]: row[f"{statistic}_{effect}_effect"] for row in named} + for effect in ("income", "substitution") + } + + def _labor_supply(connection: Connection, report_run_id: UUID) -> dict[str, Any]: response = _one(connection, labor_supply_responses, "report_run_id", report_run_id) deciles = _rows( - connection, - labor_supply_decile_impacts, - "report_run_id", - report_run_id, - order=("position",), + connection, labor_supply_decile_impacts, "report_run_id", report_run_id ) return { "substitution_lsr": response["substitution_lsr"], @@ -732,13 +783,7 @@ def _labor_supply(connection: Connection, report_run_id: UUID) -> dict[str, Any] "total_change": response["total_change"], "revenue_change": response["revenue_change"], "decile": { - statistic: { - effect: { - row["decile"]: row[f"{statistic}_{effect}_effect"] - for row in deciles - } - for effect in ("income", "substitution") - } + statistic: _labor_supply_decile_maps(deciles, statistic) for statistic in ("average", "relative") }, "hours": { diff --git a/libs/policyengine-simulation-persistence/src/policyengine_simulation_persistence/result_tables.py b/libs/policyengine-simulation-persistence/src/policyengine_simulation_persistence/result_tables.py index 955c72cd0..d960d5f02 100644 --- a/libs/policyengine-simulation-persistence/src/policyengine_simulation_persistence/result_tables.py +++ b/libs/policyengine-simulation-persistence/src/policyengine_simulation_persistence/result_tables.py @@ -74,6 +74,10 @@ def _simulation_run_key(table_name: str) -> list[SchemaItem]: return [ Column("report_run_id", Uuid(as_uuid=True), nullable=False), Column("simulation_run_id", Uuid(as_uuid=True), nullable=False), + # Which side of the comparison the figures describe; it tells them + # apart when one simulation run is both the baseline and the reform. + Column("side", Text, nullable=False), + CheckConstraint("side IN ('baseline', 'reform')", name="side"), ForeignKeyConstraint( ["report_run_id"], [report_runs.c.id], @@ -143,6 +147,7 @@ def _uk_area_disclosure() -> list[SchemaItem]: PrimaryKeyConstraint( "report_run_id", "simulation_run_id", + "side", "measure", "group_dimension", "group_value", @@ -163,7 +168,7 @@ def _uk_area_disclosure() -> list[SchemaItem]: simulation_metadata, *_simulation_run_key("inequality"), *_numbers("gini", "top_10_pct_share", "top_1_pct_share"), - PrimaryKeyConstraint("report_run_id", "simulation_run_id"), + PrimaryKeyConstraint("report_run_id", "simulation_run_id", "side"), ) cliff_impacts = Table( @@ -171,7 +176,7 @@ def _uk_area_disclosure() -> list[SchemaItem]: simulation_metadata, *_simulation_run_key("cliff_impacts"), *_numbers("cliff_gap", "cliff_share"), - PrimaryKeyConstraint("report_run_id", "simulation_run_id"), + PrimaryKeyConstraint("report_run_id", "simulation_run_id", "side"), ) # --- Per report run --------------------------------------------------------- @@ -259,20 +264,41 @@ def _uk_area_disclosure() -> list[SchemaItem]: PrimaryKeyConstraint("report_run_id"), ) +# One row per decile any of the four maps names. The average maps may name a +# decile the relative maps leave out: policyengine.py puts households with +# negative income in decile -1 and gives relative effects for positive +# deciles only. Each pair keeps its own order. labor_supply_decile_impacts = Table( "labor_supply_decile_impacts", simulation_metadata, *_report_run_key("labor_supply_decile_impacts"), Column("decile", Integer, nullable=False), - *_position(), - *_numbers( - "average_income_effect", - "average_substitution_effect", - "relative_income_effect", - "relative_substitution_effect", - ), + Column("average_position", Integer, nullable=True), + Column("relative_position", Integer, nullable=True), + Column("average_income_effect", Double, nullable=True), + Column("average_substitution_effect", Double, nullable=True), + Column("relative_income_effect", Double, nullable=True), + Column("relative_substitution_effect", Double, nullable=True), PrimaryKeyConstraint("report_run_id", "decile"), - UniqueConstraint("report_run_id", "position"), + UniqueConstraint("report_run_id", "average_position"), + UniqueConstraint("report_run_id", "relative_position"), + CheckConstraint( + "(average_position IS NULL) = (average_income_effect IS NULL) " + "AND (average_position IS NULL) = (average_substitution_effect IS NULL)", + name="average", + ), + CheckConstraint( + "(relative_position IS NULL) = (relative_income_effect IS NULL) " + "AND (relative_position IS NULL) = (relative_substitution_effect IS NULL)", + name="relative", + ), + CheckConstraint( + "average_position IS NOT NULL OR relative_position IS NOT NULL", + name="in_a_map", + ), + CheckConstraint( + "average_position >= 0 AND relative_position >= 0", name="positions" + ), ) congressional_district_impacts = Table( diff --git a/libs/policyengine-simulation-persistence/tests/test_economy_results.py b/libs/policyengine-simulation-persistence/tests/test_economy_results.py index b8226614b..625af84e3 100644 --- a/libs/policyengine-simulation-persistence/tests/test_economy_results.py +++ b/libs/policyengine-simulation-persistence/tests/test_economy_results.py @@ -6,11 +6,14 @@ from policyengine_simulation_persistence import ( EconomyComparisonRecorder, EconomyResultLabels, + NewReportRun, + RunTrigger, check_storable, create_simulation_engine, read_economy_comparison, ) from pydantic import ValidationError +from report_support import economy_report, report_store from result_support import ( SAMPLE_NAMES, comparison_ready, @@ -18,7 +21,8 @@ load_sample, result_stores, ) -from simulation_support import simulation_store +from run_support import economy_run +from simulation_support import economy_simulation, simulation_store from sqlalchemy import text from sqlalchemy.exc import ProgrammingError @@ -192,6 +196,75 @@ def test_an_empty_income_decile_map_is_rebuilt( assert _read(migrated_database, report_run.id, labels_for(result)) == result +def _with_negative_income_decile(result): + """Add the -1 decile policyengine.py gives households with negative income. + + It appears in the average labour supply maps only; the relative maps keep + positive deciles. + """ + labor = result.labor_supply_response + average = labor.decile.average + widened = average.model_copy( + update={ + "income": {-1: -12.5, **average.income}, + "substitution": {-1: 3.25, **average.substitution}, + } + ) + decile = labor.decile.model_copy(update={"average": widened}) + return result.model_copy( + update={"labor_supply_response": labor.model_copy(update={"decile": decile})} + ) + + +@pytest.mark.parametrize("sample_name", ["us_national_2026", "uk_national_2026"]) +def test_labour_supply_with_a_negative_income_decile_is_rebuilt( + migrated_database, public_api_rows, sample_name +) -> None: + result = _with_negative_income_decile(load_sample(sample_name)) + stores = result_stores(migrated_database) + report_run = comparison_ready(stores, migrated_database, public_api_rows) + + _write(stores, report_run, RECORDER.validate(result.model_dump(mode="json"))) + + rebuilt = _read(migrated_database, report_run.id, labels_for(result)) + assert rebuilt.model_dump_json() == result.model_dump_json() + + +def test_a_report_run_comparing_a_run_with_itself_is_stored( + migrated_database, public_api_rows +) -> None: + result = load_sample("us_state_ca_2026") + stores = result_stores(migrated_database) + simulation = simulation_store(migrated_database).create( + economy_simulation(public_api_rows, policy_id=None) + ) + report = report_store(migrated_database).create( + economy_report(simulation, simulation) + ) + run = stores.runs.start_simulation_run(economy_run(simulation, public_api_rows)).run + stores.transitions.claim_simulation_dispatch([run.id]) + stores.transitions.record_simulation_dispatched( + [run.id], modal_call_id="fc-itself", first_check_at=stores.clock() + ) + stores.transitions.complete_simulation_call("fc-itself", lambda *_: None) + report_run = stores.runs.create_report_run( + NewReportRun( + report_id=report.id, + baseline_simulation_run_id=run.id, + reform_simulation_run_id=run.id, + trigger=RunTrigger.INITIAL, + ) + ) + stores.transitions.claim_comparison_dispatch(report_run.id) + stores.transitions.record_comparison_dispatched( + report_run.id, modal_call_id="fc-comparison", first_check_at=stores.clock() + ) + + _write(stores, report_run, result) + + assert _read(migrated_database, report_run.id, labels_for(result)) == result + + def test_reading_needs_a_succeeded_comparison( migrated_database, public_api_rows ) -> None: diff --git a/migrations/versions/0004_result_tables.py b/migrations/versions/0004_result_tables.py index f77a48071..515877d02 100644 --- a/migrations/versions/0004_result_tables.py +++ b/migrations/versions/0004_result_tables.py @@ -126,8 +126,12 @@ def upgrade() -> None: "cliff_impacts", sa.Column("report_run_id", sa.Uuid(), nullable=False), sa.Column("simulation_run_id", sa.Uuid(), nullable=False), + sa.Column("side", sa.Text(), nullable=False), sa.Column("cliff_gap", sa.Double(), nullable=False), sa.Column("cliff_share", sa.Double(), nullable=False), + sa.CheckConstraint( + "side IN ('baseline', 'reform')", name=op.f("ck_cliff_impacts_side") + ), sa.ForeignKeyConstraint( ["report_run_id"], ["simulation.report_runs.id"], @@ -141,7 +145,7 @@ def upgrade() -> None: ondelete="RESTRICT", ), sa.PrimaryKeyConstraint( - "report_run_id", "simulation_run_id", name=op.f("pk_cliff_impacts") + "report_run_id", "simulation_run_id", "side", name=op.f("pk_cliff_impacts") ), schema="simulation", ) @@ -149,9 +153,13 @@ def upgrade() -> None: "inequality", sa.Column("report_run_id", sa.Uuid(), nullable=False), sa.Column("simulation_run_id", sa.Uuid(), nullable=False), + sa.Column("side", sa.Text(), nullable=False), sa.Column("gini", sa.Double(), nullable=False), sa.Column("top_10_pct_share", sa.Double(), nullable=False), sa.Column("top_1_pct_share", sa.Double(), nullable=False), + sa.CheckConstraint( + "side IN ('baseline', 'reform')", name=op.f("ck_inequality_side") + ), sa.ForeignKeyConstraint( ["report_run_id"], ["simulation.report_runs.id"], @@ -165,7 +173,7 @@ def upgrade() -> None: ondelete="RESTRICT", ), sa.PrimaryKeyConstraint( - "report_run_id", "simulation_run_id", name=op.f("pk_inequality") + "report_run_id", "simulation_run_id", "side", name=op.f("pk_inequality") ), schema="simulation", ) @@ -173,6 +181,7 @@ def upgrade() -> None: "poverty_rates", sa.Column("report_run_id", sa.Uuid(), nullable=False), sa.Column("simulation_run_id", sa.Uuid(), nullable=False), + sa.Column("side", sa.Text(), nullable=False), sa.Column("measure", sa.Text(), nullable=False), sa.Column("group_dimension", sa.Text(), nullable=False), sa.Column("group_value", sa.Text(), nullable=False), @@ -189,6 +198,9 @@ def upgrade() -> None: "measure IN ('poverty', 'deep_poverty')", name=op.f("ck_poverty_rates_measure"), ), + sa.CheckConstraint( + "side IN ('baseline', 'reform')", name=op.f("ck_poverty_rates_side") + ), sa.ForeignKeyConstraint( ["report_run_id"], ["simulation.report_runs.id"], @@ -204,6 +216,7 @@ def upgrade() -> None: sa.PrimaryKeyConstraint( "report_run_id", "simulation_run_id", + "side", "measure", "group_dimension", "group_value", @@ -363,13 +376,29 @@ def upgrade() -> None: "labor_supply_decile_impacts", sa.Column("report_run_id", sa.Uuid(), nullable=False), sa.Column("decile", sa.Integer(), nullable=False), - sa.Column("position", sa.Integer(), nullable=False), - sa.Column("average_income_effect", sa.Double(), nullable=False), - sa.Column("average_substitution_effect", sa.Double(), nullable=False), - sa.Column("relative_income_effect", sa.Double(), nullable=False), - sa.Column("relative_substitution_effect", sa.Double(), nullable=False), + sa.Column("average_position", sa.Integer(), nullable=True), + sa.Column("relative_position", sa.Integer(), nullable=True), + sa.Column("average_income_effect", sa.Double(), nullable=True), + sa.Column("average_substitution_effect", sa.Double(), nullable=True), + sa.Column("relative_income_effect", sa.Double(), nullable=True), + sa.Column("relative_substitution_effect", sa.Double(), nullable=True), + sa.CheckConstraint( + "(average_position IS NULL) = (average_income_effect IS NULL) " + "AND (average_position IS NULL) = (average_substitution_effect IS NULL)", + name=op.f("ck_labor_supply_decile_impacts_average"), + ), sa.CheckConstraint( - "position >= 0", name=op.f("ck_labor_supply_decile_impacts_position") + "(relative_position IS NULL) = (relative_income_effect IS NULL) " + "AND (relative_position IS NULL) = (relative_substitution_effect IS NULL)", + name=op.f("ck_labor_supply_decile_impacts_relative"), + ), + sa.CheckConstraint( + "average_position IS NOT NULL OR relative_position IS NOT NULL", + name=op.f("ck_labor_supply_decile_impacts_in_a_map"), + ), + sa.CheckConstraint( + "average_position >= 0 AND relative_position >= 0", + name=op.f("ck_labor_supply_decile_impacts_positions"), ), sa.ForeignKeyConstraint( ["report_run_id"], @@ -382,8 +411,13 @@ def upgrade() -> None: ), sa.UniqueConstraint( "report_run_id", - "position", - name=op.f("uq_labor_supply_decile_impacts_report_run_id_position"), + "average_position", + name=op.f("uq_labor_supply_decile_impacts_report_run_id_average_position"), + ), + sa.UniqueConstraint( + "report_run_id", + "relative_position", + name=op.f("uq_labor_supply_decile_impacts_report_run_id_relative_position"), ), schema="simulation", ) From af4c337ad34070c61de2b72ea0f7601f847f598b Mon Sep 17 00:00:00 2001 From: Anthony Volk <14987227+anth-volk@users.noreply.github.com> Date: Mon, 26 Oct 2026 16:21:28 +0400 Subject: [PATCH 09/14] Store the model and data versions a result reports The reader took a result's model and data versions from labels for the run's catalog version. Since main's runtime reports a US state or district run's data_version as the revision of the dataset it loaded (the ACS-local dataset), not the release's default data version, such a result would have been read back with a different data_version from the one written. report_runs gains result_model_version and result_data_version, written with the comparison's rows and read back as written; EconomyResultLabels now holds only constituency and local-authority labels. A test writes a US state result whose data_version names its dataset's revision and reads it back with the catalog's labels. Co-Authored-By: Claude Opus 5.5 --- .../README.md | 20 ++++++++------- .../economy_results.py | 24 +++++++++--------- .../result_tables.py | 6 ++--- .../runs.py | 6 ++++- .../tests/result_support.py | 2 -- .../tests/test_economy_results.py | 25 ++++++++++++++++--- .../tests/test_result_completeness.py | 2 -- migrations/versions/0004_result_tables.py | 8 ++++++ 8 files changed, 61 insertions(+), 32 deletions(-) diff --git a/libs/policyengine-simulation-persistence/README.md b/libs/policyengine-simulation-persistence/README.md index d76c9d9ad..a59dc10d4 100644 --- a/libs/policyengine-simulation-persistence/README.md +++ b/libs/policyengine-simulation-persistence/README.md @@ -82,17 +82,19 @@ decile the relative maps leave out (-1, for households with negative income). Lists and maps keep their order in a `position` column. Result rows are written once and never changed: the runtime role may read and insert them but not update or delete them. The report run also -records which optional sections its result holds (`result_sections`) and its -SPM provenance. `write_economy_comparison` checks the result can be held -exactly (`check_storable`) and writes its rows in the transaction that marks -the comparison step succeeded (`RunTransitions.complete_comparison`); +records which optional sections its result holds (`result_sections`), its SPM +provenance, and the model and data versions the result reports (a US state +run reports the revision of the dataset it loaded, which is not the release's +default data version). `write_economy_comparison` checks the result can be +held exactly (`check_storable`) and writes its rows in the transaction that +marks the comparison step succeeded (`RunTransitions.complete_comparison`); `EconomyComparisonRecorder` pairs that writer with validation against the result model. `read_economy_comparison` rebuilds the result exactly from the -rows and from labels the region catalog supplies (`EconomyResultLabels`): the -model and data versions of the run's catalog version, and constituency and -local-authority names and map positions by code. Each UK area's disclosure -tier and the 90% interval bounds of its income changes are stored with its -figures (null for a result computed before disclosure control). +rows and from labels the region catalog supplies (`EconomyResultLabels`): +constituency and local-authority names and map positions by code. Each UK +area's disclosure tier and the 90% interval bounds of its income changes are +stored with its figures (null for a result computed before disclosure +control). A computed household is one JSON value (`household_outputs`, PostgreSQL `json`, so its text, key order included, is kept as written) on its diff --git a/libs/policyengine-simulation-persistence/src/policyengine_simulation_persistence/economy_results.py b/libs/policyengine-simulation-persistence/src/policyengine_simulation_persistence/economy_results.py index 9c0b791a9..92a4d6522 100644 --- a/libs/policyengine-simulation-persistence/src/policyengine_simulation_persistence/economy_results.py +++ b/libs/policyengine-simulation-persistence/src/policyengine_simulation_persistence/economy_results.py @@ -3,10 +3,11 @@ ``write_economy_comparison`` runs in the transaction that marks a report run's comparison step succeeded (``RunTransitions.complete_comparison``), so a run never succeeds without its rows. ``read_economy_comparison`` rebuilds today's -result format, ``SingleYearMacroOutput``, from the rows and from labels the -region catalog supplies: the model and data versions of the run's catalog -version, and the names and map positions of constituencies and local -authorities by code. +result format, ``SingleYearMacroOutput``, from the rows and from the labels +the region catalog supplies: the names and map positions of constituencies and +local authorities by code. The model and data versions are stored as the +result reports them, since a run on a non-default dataset (a US state run on +the ACS-local dataset) reports that dataset's revision. A result the tables cannot hold exactly is refused before any write by ``check_storable``: the average and relative changes of each decile map must @@ -121,8 +122,8 @@ def _geography_storage( RESULT_FIELD_STORAGE: dict[str, str] = { "spm_provenance": "report_runs.spm_provenance", - "model_version": "catalog version: model version", - "data_version": "catalog version: data version", + "model_version": "report_runs.result_model_version", + "data_version": "report_runs.result_data_version", **{ f"budget.{name}": f"budget_impacts.{name}" for name in ( @@ -221,12 +222,9 @@ class GeographyLabel: class EconomyResultLabels: """What a stored result takes from the region catalog when it is read. - The model and data versions belong to the run's catalog version; the - geography labels are looked up by code. + Constituency and local-authority names and map positions, by code. """ - model_version: str - data_version: str constituencies: Mapping[str, GeographyLabel] = field(default_factory=dict) local_authorities: Mapping[str, GeographyLabel] = field(default_factory=dict) @@ -580,6 +578,8 @@ def write_economy_comparison( if result.spm_provenance is None else result.spm_provenance.model_dump(mode="json") ), + result_model_version=result.model_version, + result_data_version=result.data_version, ) ) @@ -956,8 +956,8 @@ def read_economy_comparison( return SingleYearMacroOutput.model_validate( { "spm_provenance": report_run_row["spm_provenance"], - "model_version": labels.model_version, - "data_version": labels.data_version, + "model_version": report_run_row["result_model_version"], + "data_version": report_run_row["result_data_version"], **_comparison_sections(connection, report_run_id, sections, labels), **_simulation_sections(connection, report_run_id, run_ids, sections), } diff --git a/libs/policyengine-simulation-persistence/src/policyengine_simulation_persistence/result_tables.py b/libs/policyengine-simulation-persistence/src/policyengine_simulation_persistence/result_tables.py index d960d5f02..2aaf8b62e 100644 --- a/libs/policyengine-simulation-persistence/src/policyengine_simulation_persistence/result_tables.py +++ b/libs/policyengine-simulation-persistence/src/policyengine_simulation_persistence/result_tables.py @@ -12,9 +12,9 @@ Constituency and local-authority names and map positions are not stored: they come from the region catalog by code. Each area's disclosure tier and 90% interval bounds are stored with its figures, null for a result computed before -disclosure control. The model and data versions are pinned -by the run's catalog version. The SPM provenance and the list of optional -sections a result holds are columns on the report run. +disclosure control. The model and data versions the result reports, its SPM +provenance and the list of optional sections it holds are columns on the +report run. """ from __future__ import annotations diff --git a/libs/policyengine-simulation-persistence/src/policyengine_simulation_persistence/runs.py b/libs/policyengine-simulation-persistence/src/policyengine_simulation_persistence/runs.py index 59e6eb926..39c5e85f0 100644 --- a/libs/policyengine-simulation-persistence/src/policyengine_simulation_persistence/runs.py +++ b/libs/policyengine-simulation-persistence/src/policyengine_simulation_persistence/runs.py @@ -282,9 +282,13 @@ def _execution_columns(prefix: str, *, required: bool) -> list[Column[Any]]: Column("created_at", DateTime(timezone=True), nullable=False), Column("updated_at", DateTime(timezone=True), nullable=False), # Set with an economy comparison's result rows (item 1.07): the optional - # sections the result holds, and its SPM provenance, if any. + # sections the result holds, its SPM provenance, if any, and the model and + # data versions it reports (a US state run reports the revision of the + # dataset it loaded, not the release's default data version). Column("result_sections", ARRAY(Text), nullable=True), Column("spm_provenance", JSONB(none_as_null=True), nullable=True), + Column("result_model_version", Text, nullable=True), + Column("result_data_version", Text, nullable=True), CheckConstraint(f"year BETWEEN {FIRST_YEAR} AND {LAST_YEAR}", name="year"), CheckConstraint(f"trigger IN ({_values(RunTrigger)})", name="trigger"), CheckConstraint( diff --git a/libs/policyengine-simulation-persistence/tests/result_support.py b/libs/policyengine-simulation-persistence/tests/result_support.py index 1fec3bed9..49eba726e 100644 --- a/libs/policyengine-simulation-persistence/tests/result_support.py +++ b/libs/policyengine-simulation-persistence/tests/result_support.py @@ -53,8 +53,6 @@ def labels(records, code_field: str, name_field: str): } return EconomyResultLabels( - model_version=result.model_version, - data_version=result.data_version, constituencies=labels( result.constituency_impact, "constituency_code", "constituency_name" ), diff --git a/libs/policyengine-simulation-persistence/tests/test_economy_results.py b/libs/policyengine-simulation-persistence/tests/test_economy_results.py index 625af84e3..700042ab6 100644 --- a/libs/policyengine-simulation-persistence/tests/test_economy_results.py +++ b/libs/policyengine-simulation-persistence/tests/test_economy_results.py @@ -75,6 +75,27 @@ def test_a_stored_result_is_rebuilt_exactly( assert rebuilt == result +def test_a_result_keeps_the_versions_it_reports( + migrated_database, public_api_rows +) -> None: + # A US state run reports the revision of the dataset it loaded (the + # ACS-local dataset), not the release's default data version, which is + # what the region catalog gives for the run's catalog version. + catalog_result = load_sample("us_state_ca_2026") + result = catalog_result.model_copy( + update={"data_version": "populace-us-acs-local-sample-revision"} + ) + stores = result_stores(migrated_database) + report_run = comparison_ready(stores, migrated_database, public_api_rows) + + _write(stores, report_run, RECORDER.validate(result.model_dump(mode="json"))) + + rebuilt = _read(migrated_database, report_run.id, labels_for(catalog_result)) + assert rebuilt.data_version == result.data_version + assert rebuilt.model_version == result.model_version + assert rebuilt == result + + UK_AREA_DISCLOSURE_FIELDS = { "disclosure_tier", "average_household_income_change_lower", @@ -275,7 +296,7 @@ def test_reading_needs_a_succeeded_comparison( _read( migrated_database, report_run.id, - EconomyResultLabels(model_version="1", data_version="1"), + EconomyResultLabels(), ) @@ -288,8 +309,6 @@ def test_reading_needs_a_label_for_every_geography( _write(stores, report_run, result) labels = labels_for(result) missing = EconomyResultLabels( - model_version=labels.model_version, - data_version=labels.data_version, constituencies=dict(list(labels.constituencies.items())[1:]), local_authorities=labels.local_authorities, ) diff --git a/libs/policyengine-simulation-persistence/tests/test_result_completeness.py b/libs/policyengine-simulation-persistence/tests/test_result_completeness.py index 42828c3c1..937d2b1f1 100644 --- a/libs/policyengine-simulation-persistence/tests/test_result_completeness.py +++ b/libs/policyengine-simulation-persistence/tests/test_result_completeness.py @@ -17,8 +17,6 @@ # Stored whole, as one JSON column. WHOLE_VALUES = (SPMComparisonProvenance,) CATALOG_SOURCES = { - "catalog version: model version", - "catalog version: data version", "region catalog: name", "region catalog: map x", "region catalog: map y", diff --git a/migrations/versions/0004_result_tables.py b/migrations/versions/0004_result_tables.py index 515877d02..032836eb3 100644 --- a/migrations/versions/0004_result_tables.py +++ b/migrations/versions/0004_result_tables.py @@ -536,6 +536,12 @@ def upgrade() -> None: ), schema="simulation", ) + for column in ("result_model_version", "result_data_version"): + op.add_column( + "report_runs", + sa.Column(column, sa.Text(), nullable=True), + schema="simulation", + ) op.create_check_constraint( op.f("ck_report_runs_spm_provenance"), "report_runs", @@ -552,6 +558,8 @@ def downgrade() -> None: schema="simulation", type_="check", ) + op.drop_column("report_runs", "result_data_version", schema="simulation") + op.drop_column("report_runs", "result_model_version", schema="simulation") op.drop_column("report_runs", "spm_provenance", schema="simulation") op.drop_column("report_runs", "result_sections", schema="simulation") op.drop_table("program_budget_impacts", schema="simulation") From 9e5b1d1e17163d859b230ea2142f88177c1f0f64 Mon Sep 17 00:00:00 2001 From: Anthony Volk <14987227+anth-volk@users.noreply.github.com> Date: Mon, 26 Oct 2026 16:22:04 +0400 Subject: [PATCH 10/14] Declare pydantic for the household writer and describe the labour supply check From the third review of 1.07: the household writer imports pydantic, which the persistence library received only through the contract library, so it is now a declared dependency (locks refreshed). The economy_results module described the labour supply check as it was before decile -1 was accepted; it now says that each pair's income and substitution maps must name the same deciles in order, and that the average pair may name deciles the relative pair leaves out. Co-Authored-By: Claude Opus 5.5 --- libs/policyengine-simulation-persistence/pyproject.toml | 2 ++ .../economy_results.py | 9 +++++---- libs/policyengine-simulation-persistence/uv.lock | 2 ++ projects/policyengine-simulation-entry/uv.lock | 2 ++ 4 files changed, 11 insertions(+), 4 deletions(-) diff --git a/libs/policyengine-simulation-persistence/pyproject.toml b/libs/policyengine-simulation-persistence/pyproject.toml index cf04f772f..ffd61c5ea 100644 --- a/libs/policyengine-simulation-persistence/pyproject.toml +++ b/libs/policyengine-simulation-persistence/pyproject.toml @@ -11,6 +11,8 @@ dependencies = [ # The result models the result tables store and rebuild. "policyengine-simulation-contract", "psycopg[binary]>=3.2,<4", + # The household writer validates with pydantic directly. + "pydantic>=2,<3", "sqlalchemy>=2,<3", ] diff --git a/libs/policyengine-simulation-persistence/src/policyengine_simulation_persistence/economy_results.py b/libs/policyengine-simulation-persistence/src/policyengine_simulation_persistence/economy_results.py index 92a4d6522..d41e576ed 100644 --- a/libs/policyengine-simulation-persistence/src/policyengine_simulation_persistence/economy_results.py +++ b/libs/policyengine-simulation-persistence/src/policyengine_simulation_persistence/economy_results.py @@ -13,9 +13,10 @@ ``check_storable``: the average and relative changes of each decile map must name the same deciles in the same order, the decile shares and averages of each intra-decile breakdown must name the same categories in the same order, -each pair of labour supply decile maps (average, relative) must name the same -deciles in order, and the area lists must hold records of their own kind, -each area once. +within each labour supply decile map pair (average, relative) the income and +substitution effects must name the same deciles in order (the average pair may +name deciles the relative pair leaves out, such as decile -1), and the area +lists must hold records of their own kind, each area once. """ from __future__ import annotations @@ -253,7 +254,7 @@ def _check_unique(section: str, codes: list[str]) -> None: def _check_labor_supply(labor: LaborSupplyResponseOutput | None) -> None: - """Require each pair of decile maps to name the same deciles in order. + """Require each pair's income and substitution maps to name one decile order. The average pair may name deciles the relative pair leaves out, such as decile -1 for households with negative income. diff --git a/libs/policyengine-simulation-persistence/uv.lock b/libs/policyengine-simulation-persistence/uv.lock index f19c0f00e..b78f0fa75 100644 --- a/libs/policyengine-simulation-persistence/uv.lock +++ b/libs/policyengine-simulation-persistence/uv.lock @@ -650,6 +650,7 @@ source = { editable = "." } dependencies = [ { name = "policyengine-simulation-contract" }, { name = "psycopg", extra = ["binary"] }, + { name = "pydantic" }, { name = "sqlalchemy" }, ] @@ -673,6 +674,7 @@ requires-dist = [ { name = "alembic", marker = "extra == 'test'", specifier = ">=1.17.1,<2" }, { name = "policyengine-simulation-contract", editable = "../policyengine-simulation-contract" }, { name = "psycopg", extras = ["binary"], specifier = ">=3.2,<4" }, + { name = "pydantic", specifier = ">=2,<3" }, { name = "pyright", marker = "extra == 'build'", specifier = ">=1.1.401" }, { name = "pytest", marker = "extra == 'test'", specifier = ">=8.3.4" }, { name = "pytest-cov", marker = "extra == 'test'", specifier = ">=6.1.1" }, diff --git a/projects/policyengine-simulation-entry/uv.lock b/projects/policyengine-simulation-entry/uv.lock index 1dd314d3f..594f94e69 100644 --- a/projects/policyengine-simulation-entry/uv.lock +++ b/projects/policyengine-simulation-entry/uv.lock @@ -972,6 +972,7 @@ source = { editable = "../../libs/policyengine-simulation-persistence" } dependencies = [ { name = "policyengine-simulation-contract" }, { name = "psycopg", extra = ["binary"] }, + { name = "pydantic" }, { name = "sqlalchemy" }, ] @@ -981,6 +982,7 @@ requires-dist = [ { name = "alembic", marker = "extra == 'test'", specifier = ">=1.17.1,<2" }, { name = "policyengine-simulation-contract", editable = "../../libs/policyengine-simulation-contract" }, { name = "psycopg", extras = ["binary"], specifier = ">=3.2,<4" }, + { name = "pydantic", specifier = ">=2,<3" }, { name = "pyright", marker = "extra == 'build'", specifier = ">=1.1.401" }, { name = "pytest", marker = "extra == 'test'", specifier = ">=8.3.4" }, { name = "pytest-cov", marker = "extra == 'test'", specifier = ">=6.1.1" }, From 2be337b4ee5690e331c85bab6de9093889faaf63 Mon Sep 17 00:00:00 2001 From: Anthony Volk <14987227+anth-volk@users.noreply.github.com> Date: Mon, 26 Oct 2026 16:56:06 +0400 Subject: [PATCH 11/14] Describe the result tables' privileges and write the disclosure tiers out From the fourth review of 1.07 (no bugs found): the persistence README's roles table and revision 0004's docstring did not say that 0004 revokes UPDATE on the result tables or adds the two version columns. And the UK area tables' tier check was built from the contract when imported, while revision 0004 writes the two tiers out, so a tier added to the contract would have changed the declared table without a test failing; the tiers are now written out in the table definitions too, and a test requires them to match the contract's. Co-Authored-By: Claude Opus 5.5 --- libs/policyengine-simulation-persistence/README.md | 5 +++-- .../result_tables.py | 7 ++++--- .../tests/test_result_completeness.py | 11 ++++++++++- migrations/versions/0004_result_tables.py | 3 ++- 4 files changed, 19 insertions(+), 7 deletions(-) diff --git a/libs/policyengine-simulation-persistence/README.md b/libs/policyengine-simulation-persistence/README.md index a59dc10d4..8b6d26e54 100644 --- a/libs/policyengine-simulation-persistence/README.md +++ b/libs/policyengine-simulation-persistence/README.md @@ -141,11 +141,12 @@ These rules are registered in `rules/registry.toml` and checked by | Role | Used by | Privileges | | --- | --- | --- | | `simulation_migrator` | The deploy workflow's migration job, through `SIMULATION_MIGRATION_DATABASE_URL` | Creates the `simulation` schema if it is missing, and owns every object in it; `REFERENCES` on the Public API tables its foreign keys point to | -| `simulation_runtime` | The Simulation Entrypoint, through `SIMULATION_DATABASE_URL` | `USAGE` on the schema, `SELECT` on the version table, and `SELECT`, `INSERT` and `UPDATE` on the tables the migrations create, except `UPDATE` on the definition tables (`simulations`, `reports`); never `DELETE`, and nothing on the Public API tables | +| `simulation_runtime` | The Simulation Entrypoint, through `SIMULATION_DATABASE_URL` | `USAGE` on the schema, `SELECT` on the version table, and `SELECT`, `INSERT` and `UPDATE` on the tables the migrations create, except `UPDATE` on the definition tables (`simulations`, `reports`) and the result tables; never `DELETE`, and nothing on the Public API tables | The initial revision grants the runtime role its privileges, including default privileges on tables the migrator creates later; revision 0002 revokes -`UPDATE` on the definition tables, which never change. Both roles must exist +`UPDATE` on the definition tables, which never change, and revision 0004 on +the result tables, whose rows are written once. Both roles must exist before the first migration runs; an operator creates them. Before revision 0002 is deployed, the owner of the Public API's tables must also grant the migrator `REFERENCES` on `policies`, `households` and `dynamics`, and diff --git a/libs/policyengine-simulation-persistence/src/policyengine_simulation_persistence/result_tables.py b/libs/policyengine-simulation-persistence/src/policyengine_simulation_persistence/result_tables.py index 2aaf8b62e..d80d8ea3c 100644 --- a/libs/policyengine-simulation-persistence/src/policyengine_simulation_persistence/result_tables.py +++ b/libs/policyengine-simulation-persistence/src/policyengine_simulation_persistence/result_tables.py @@ -19,9 +19,8 @@ from __future__ import annotations -from typing import TYPE_CHECKING, get_args +from typing import TYPE_CHECKING -from policyengine_simulation_contract.macro_output import UKGeographyDisclosureTier from sqlalchemy import ( CheckConstraint, Column, @@ -50,7 +49,9 @@ "race": ("white", "black", "hispanic", "other"), } DECILE_MEASURES = ("income", "wealth") -UK_AREA_DISCLOSURE_TIERS: tuple[str, ...] = get_args(UKGeographyDisclosureTier) +# The contract's UKGeographyDisclosureTier values, written out so that a new +# tier fails a test rather than silently changing the declared table. +UK_AREA_DISCLOSURE_TIERS = ("reported", "approximate") UK_AREA_DISCLOSURE_COLUMNS = ( "disclosure_tier", "average_household_income_change_lower", diff --git a/libs/policyengine-simulation-persistence/tests/test_result_completeness.py b/libs/policyengine-simulation-persistence/tests/test_result_completeness.py index 937d2b1f1..89eadeea3 100644 --- a/libs/policyengine-simulation-persistence/tests/test_result_completeness.py +++ b/libs/policyengine-simulation-persistence/tests/test_result_completeness.py @@ -5,13 +5,17 @@ import types import typing -from policyengine_simulation_contract.macro_output import SingleYearMacroOutput +from policyengine_simulation_contract.macro_output import ( + SingleYearMacroOutput, + UKGeographyDisclosureTier, +) from policyengine_simulation_contract.spm import SPMComparisonProvenance from policyengine_simulation_persistence import ( RESULT_FIELD_STORAGE, simulation_metadata, ) from policyengine_simulation_persistence.economy_results import REFUSED_OTHER_KIND +from policyengine_simulation_persistence.result_tables import UK_AREA_DISCLOSURE_TIERS from pydantic import BaseModel, RootModel # Stored whole, as one JSON column. @@ -72,3 +76,8 @@ def test_every_storage_location_exists() -> None: table_name, column_name = location.split(".") table = simulation_metadata.tables[f"simulation.{table_name}"] assert column_name in table.c, path + + +def test_the_tables_accept_every_disclosure_tier_the_contract_names() -> None: + """A new tier needs a migration of the UK area tables' check.""" + assert typing.get_args(UKGeographyDisclosureTier) == UK_AREA_DISCLOSURE_TIERS diff --git a/migrations/versions/0004_result_tables.py b/migrations/versions/0004_result_tables.py index 032836eb3..12665d157 100644 --- a/migrations/versions/0004_result_tables.py +++ b/migrations/versions/0004_result_tables.py @@ -6,7 +6,8 @@ (poverty rates, inequality, cliff exposure) belong to its simulation run; the comparison of a baseline and a reform (budget, programs, deciles, labour supply, geographies) belongs to the report run. Each report run also records -the optional sections its result holds and its SPM provenance. Rows are +the optional sections its result holds, its SPM provenance, and the model and +data versions the result reports. Rows are written in the transaction that marks a run succeeded and never change: the runtime role may read and insert them but not update or delete them. A simulation's own figures are keyed by the report run that computed them too, From 43aa78ad934d656a06e49005024ca31fce16c587 Mon Sep 17 00:00:00 2001 From: Anthony Volk <14987227+anth-volk@users.noreply.github.com> Date: Tue, 27 Oct 2026 17:35:22 +0400 Subject: [PATCH 12/14] Describe the comparison recorder without the removed loop EconomyComparisonRecorder's docstring named the recording loop, which 1.06 replaced with the reporting route and the safety check; it now says it validates and writes in the form RunRecorder expects. Co-Authored-By: Claude Opus 5.5 --- .../src/policyengine_simulation_persistence/economy_results.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/policyengine-simulation-persistence/src/policyengine_simulation_persistence/economy_results.py b/libs/policyengine-simulation-persistence/src/policyengine_simulation_persistence/economy_results.py index d41e576ed..8a46ec363 100644 --- a/libs/policyengine-simulation-persistence/src/policyengine_simulation_persistence/economy_results.py +++ b/libs/policyengine-simulation-persistence/src/policyengine_simulation_persistence/economy_results.py @@ -587,7 +587,7 @@ def write_economy_comparison( @dataclass(frozen=True) class EconomyComparisonRecorder: - """Validate a comparison's output and write it, for the recording loop.""" + """Validate a comparison's output and write it, as RunRecorder expects.""" def validate(self, output: object) -> SingleYearMacroOutput: """Return the output as a result the tables can hold; else raise ValueError.""" From bf2f293869aa9962cf041c56a4b03e50e1491299 Mon Sep 17 00:00:00 2001 From: Anthony Volk <14987227+anth-volk@users.noreply.github.com> Date: Tue, 27 Oct 2026 18:37:35 +0400 Subject: [PATCH 13/14] Split the economy result module into its storage map, writer and reader main has since added a rule (sim.quality.python-file-length) that a module has at most 800 lines, and economy_results had 965. It is split by responsibility, without changing behaviour: - economy_result_storage: OPTIONAL_SECTIONS, SIDES, RESULT_FIELD_STORAGE and the catalog labels (GeographyLabel, EconomyResultLabels); - economy_results: the checks, the writer and EconomyComparisonRecorder; - economy_result_reader: read_economy_comparison and its helpers. economy_results re-exports every public name, so imports keep working; the same 183 persistence tests pass. Co-Authored-By: Claude Opus 5.5 --- .../economy_result_reader.py | 413 +++++++++++++ .../economy_result_storage.py | 188 ++++++ .../economy_results.py | 561 +----------------- 3 files changed, 628 insertions(+), 534 deletions(-) create mode 100644 libs/policyengine-simulation-persistence/src/policyengine_simulation_persistence/economy_result_reader.py create mode 100644 libs/policyengine-simulation-persistence/src/policyengine_simulation_persistence/economy_result_storage.py diff --git a/libs/policyengine-simulation-persistence/src/policyengine_simulation_persistence/economy_result_reader.py b/libs/policyengine-simulation-persistence/src/policyengine_simulation_persistence/economy_result_reader.py new file mode 100644 index 000000000..de6b16ec7 --- /dev/null +++ b/libs/policyengine-simulation-persistence/src/policyengine_simulation_persistence/economy_result_reader.py @@ -0,0 +1,413 @@ +"""Rebuild an economy comparison's result from its rows. + +``read_economy_comparison`` rebuilds today's result format, +``SingleYearMacroOutput``, from the rows ``economy_results`` wrote and from +the labels the region catalog supplies (``EconomyResultLabels``): the names +and map positions of constituencies and local authorities by code. The model +and data versions, the SPM provenance and which optional sections the result +holds come from its report run. +""" + +from __future__ import annotations + +from typing import TYPE_CHECKING, Any + +from policyengine_simulation_contract.macro_output import ( + SingleYearMacroOutput, +) +from sqlalchemy import select + +from policyengine_simulation_persistence.economy_result_storage import SIDES +from policyengine_simulation_persistence.result_tables import ( + UK_AREA_DISCLOSURE_COLUMNS, + budget_impacts, + cliff_impacts, + congressional_district_impacts, + constituency_impacts, + decile_impacts, + inequality, + intra_decile_impacts, + labor_supply_decile_impacts, + labor_supply_responses, + local_authority_impacts, + poverty_rates, + program_budget_impacts, +) +from policyengine_simulation_persistence.runs import ( + ReportRunRecord, + RunStatus, + report_runs, +) + +if TYPE_CHECKING: + from collections.abc import Mapping, Sequence + from uuid import UUID + + from sqlalchemy import Connection, RowMapping, Table + + from policyengine_simulation_persistence.economy_result_storage import ( + EconomyResultLabels, + GeographyLabel, + ) + + +# --- Reading ---------------------------------------------------------------- + + +def _rows( + connection: Connection, + table: Table, + key_column: str, + key: UUID, + order: Sequence[str] = (), +) -> list[RowMapping]: + statement = select(table).where(table.c[key_column] == key) + if order: + statement = statement.order_by(*(table.c[name] for name in order)) + return list(connection.execute(statement).mappings()) + + +def _one( + connection: Connection, table: Table, key_column: str, key: UUID +) -> RowMapping: + rows = _rows(connection, table, key_column, key) + if len(rows) != 1: + msg = f"{table.name} has no row for {key}" + raise LookupError(msg) + return rows[0] + + +def _poverty(rows_by_side: dict[str, list[RowMapping]]) -> dict[str, Any]: + sections: dict[tuple[str, str], dict[str, dict[str, float]]] = {} + for side, side_rows in rows_by_side.items(): + for row in side_rows: + group = sections.setdefault((row["group_dimension"], row["measure"]), {}) + group.setdefault(row["group_value"], {})[side] = row["rate"] + return { + "poverty": { + "poverty": sections[("age", "poverty")], + "deep_poverty": sections[("age", "deep_poverty")], + }, + "poverty_by_gender": { + "poverty": sections[("gender", "poverty")], + "deep_poverty": sections[("gender", "deep_poverty")], + }, + "poverty_by_race": ( + {"poverty": sections[("race", "poverty")]} + if ("race", "poverty") in sections + else None + ), + } + + +def _figures( + connection: Connection, + table: Table, + report_run_id: UUID, + run_id: UUID, + side: str, +) -> list[RowMapping]: + """Return one side's own figures as one report run computed them.""" + return list( + connection.execute( + select(table).where( + table.c.report_run_id == report_run_id, + table.c.simulation_run_id == run_id, + table.c.side == side, + ) + ).mappings() + ) + + +def _one_figure( + connection: Connection, + table: Table, + report_run_id: UUID, + run_id: UUID, + side: str, +) -> RowMapping: + rows = _figures(connection, table, report_run_id, run_id, side) + if len(rows) != 1: + msg = ( + f"{table.name} has no {side} row for run {run_id} " + f"in report run {report_run_id}" + ) + raise LookupError(msg) + return rows[0] + + +def _simulation_sections( + connection: Connection, + report_run_id: UUID, + run_ids: tuple[UUID, UUID], + sections: set[str], +) -> dict[str, Any]: + by_side = { + side: _figures(connection, poverty_rates, report_run_id, run_id, side) + for side, run_id in zip(SIDES, run_ids, strict=True) + } + payload = _poverty(by_side) + if "poverty_by_race" not in sections: + payload["poverty_by_race"] = None + inequality_rows = [ + _one_figure(connection, inequality, report_run_id, run_id, side) + for side, run_id in zip(SIDES, run_ids, strict=True) + ] + payload["inequality"] = { + name: { + side: row[name] for side, row in zip(SIDES, inequality_rows, strict=True) + } + for name in ("gini", "top_10_pct_share", "top_1_pct_share") + } + payload["cliff_impact"] = None + if "cliff_impact" in sections: + cliff_rows = [ + _one_figure(connection, cliff_impacts, report_run_id, run_id, side) + for side, run_id in zip(SIDES, run_ids, strict=True) + ] + payload["cliff_impact"] = { + side: {name: row[name] for name in ("cliff_gap", "cliff_share")} + for side, row in zip(SIDES, cliff_rows, strict=True) + } + return payload + + +def _deciles(rows: list[RowMapping], measure: str) -> dict[str, dict[str, float]]: + measured = [row for row in rows if row["measure"] == measure] + return { + "average": {row["decile"]: row["average_change"] for row in measured}, + "relative": {row["decile"]: row["relative_change"] for row in measured}, + } + + +def _intra_deciles(rows: list[RowMapping], measure: str) -> dict[str, Any]: + """Rebuild one breakdown; its categories come from their average rows. + + A category whose decile shares are missing (the breakdown failed) gets an + empty list, as it was written. + """ + measured = [row for row in rows if row["measure"] == measure] + averages = sorted( + (row for row in measured if row["decile"] is None), + key=lambda row: row["outcome_position"], + ) + deciles: dict[str, list[float]] = {row["outcome"]: [] for row in averages} + for row in sorted( + (row for row in measured if row["decile"] is not None), + key=lambda row: (row["outcome_position"], row["decile"]), + ): + deciles[row["outcome"]].append(row["share"]) + return { + "deciles": deciles, + "all": {row["outcome"]: row["share"] for row in averages}, + } + + +def _labor_supply_decile_maps( + rows: list[RowMapping], statistic: str +) -> dict[str, dict[int, float]]: + """Rebuild one pair of labour supply decile maps in its own order.""" + named = sorted( + (row for row in rows if row[f"{statistic}_position"] is not None), + key=lambda row: row[f"{statistic}_position"], + ) + return { + effect: {row["decile"]: row[f"{statistic}_{effect}_effect"] for row in named} + for effect in ("income", "substitution") + } + + +def _labor_supply(connection: Connection, report_run_id: UUID) -> dict[str, Any]: + response = _one(connection, labor_supply_responses, "report_run_id", report_run_id) + deciles = _rows( + connection, labor_supply_decile_impacts, "report_run_id", report_run_id + ) + return { + "substitution_lsr": response["substitution_lsr"], + "income_lsr": response["income_lsr"], + "relative_lsr": { + "income": response["relative_income_response"], + "substitution": response["relative_substitution_response"], + }, + "total_change": response["total_change"], + "revenue_change": response["revenue_change"], + "decile": { + statistic: _labor_supply_decile_maps(deciles, statistic) + for statistic in ("average", "relative") + }, + "hours": { + "baseline": response["baseline_hours"], + "reform": response["reform_hours"], + "change": response["hours_change"], + "income_effect": response["hours_income_effect"], + "substitution_effect": response["hours_substitution_effect"], + }, + } + + +def _labelled_geographies( + rows: list[RowMapping], + code_field: str, + name_field: str, + labels: Mapping[str, GeographyLabel], +) -> list[dict[str, Any]]: + records = [] + for row in rows: + code = row[code_field] + label = labels.get(code) + if label is None: + msg = f"the region catalog has no label for {code}" + raise LookupError(msg) + records.append( + { + code_field: code, + name_field: label.name, + "x": label.x, + "y": label.y, + "average_household_income_change": row[ + "average_household_income_change" + ], + "relative_household_income_change": row[ + "relative_household_income_change" + ], + "population": row["population"], + **{name: row[name] for name in UK_AREA_DISCLOSURE_COLUMNS}, + } + ) + return records + + +def _geography_sections( + connection: Connection, + report_run_id: UUID, + sections: set[str], + labels: EconomyResultLabels, +) -> dict[str, Any]: + def ordered(table: Table) -> list[RowMapping]: + return _rows( + connection, table, "report_run_id", report_run_id, order=("position",) + ) + + payload: dict[str, Any] = { + "congressional_district_impact": None, + "constituency_impact": None, + "local_authority_impact": None, + } + if "congressional_district_impact" in sections: + payload["congressional_district_impact"] = { + "districts": [ + { + name: row[name] + for name in row.keys() # noqa: SIM118 # RowMapping keys + if name not in {"report_run_id", "position"} + } + for row in ordered(congressional_district_impacts) + ] + } + if "constituency_impact" in sections: + payload["constituency_impact"] = _labelled_geographies( + ordered(constituency_impacts), + "constituency_code", + "constituency_name", + labels.constituencies, + ) + if "local_authority_impact" in sections: + payload["local_authority_impact"] = _labelled_geographies( + ordered(local_authority_impacts), + "local_authority_code", + "local_authority_name", + labels.local_authorities, + ) + return payload + + +def _comparison_sections( + connection: Connection, + report_run_id: UUID, + sections: set[str], + labels: EconomyResultLabels, +) -> dict[str, Any]: + budget = _one(connection, budget_impacts, "report_run_id", report_run_id) + deciles = _rows( + connection, + decile_impacts, + "report_run_id", + report_run_id, + order=("measure", "position"), + ) + intra = _rows(connection, intra_decile_impacts, "report_run_id", report_run_id) + programs = _rows( + connection, + program_budget_impacts, + "report_run_id", + report_run_id, + order=("position",), + ) + return { + "budget": { + name: value for name, value in budget.items() if name != "report_run_id" + }, + "detailed_budget": { + row["program"]: { + "baseline": row["baseline"], + "reform": row["reform"], + "difference": row["difference"], + } + for row in programs + }, + "decile": _deciles(deciles, "income"), + "wealth_decile": ( + _deciles(deciles, "wealth") if "wealth_decile" in sections else None + ), + "intra_decile": _intra_deciles(intra, "income"), + "intra_wealth_decile": ( + _intra_deciles(intra, "wealth") + if "intra_wealth_decile" in sections + else None + ), + "labor_supply_response": ( + _labor_supply(connection, report_run_id) + if "labor_supply_response" in sections + else None + ), + **_geography_sections(connection, report_run_id, sections, labels), + } + + +def read_economy_comparison( + connection: Connection, report_run_id: UUID, labels: EconomyResultLabels +) -> SingleYearMacroOutput: + """Rebuild a succeeded economy report run's result from its rows. + + Raise LookupError when the report run has no succeeded comparison, or + when the labels lack a constituency or local authority the result names. + """ + report_run_row = ( + connection.execute(select(report_runs).where(report_runs.c.id == report_run_id)) + .mappings() + .first() + ) + if report_run_row is None: + msg = f"no report run {report_run_id}" + raise LookupError(msg) + report_run = ReportRunRecord.from_row(report_run_row) + if ( + report_run.comparison_status is not RunStatus.SUCCEEDED + or report_run.reform_simulation_run_id is None + ): + msg = f"report run {report_run_id} has no succeeded economy comparison" + raise LookupError(msg) + sections: set[str] = set(report_run_row["result_sections"] or ()) + run_ids = ( + report_run.baseline_simulation_run_id, + report_run.reform_simulation_run_id, + ) + return SingleYearMacroOutput.model_validate( + { + "spm_provenance": report_run_row["spm_provenance"], + "model_version": report_run_row["result_model_version"], + "data_version": report_run_row["result_data_version"], + **_comparison_sections(connection, report_run_id, sections, labels), + **_simulation_sections(connection, report_run_id, run_ids, sections), + } + ) diff --git a/libs/policyengine-simulation-persistence/src/policyengine_simulation_persistence/economy_result_storage.py b/libs/policyengine-simulation-persistence/src/policyengine_simulation_persistence/economy_result_storage.py new file mode 100644 index 000000000..4f09d324a --- /dev/null +++ b/libs/policyengine-simulation-persistence/src/policyengine_simulation_persistence/economy_result_storage.py @@ -0,0 +1,188 @@ +"""Where each part of an economy result is stored, and its catalog labels. + +``RESULT_FIELD_STORAGE`` names the column (or catalog label) that holds each +field of ``SingleYearMacroOutput``; a test requires it to name every field. +``EconomyResultLabels`` carries what a stored result takes from the region +catalog when it is read: constituency and local-authority names and map +positions, by code. The writer (``economy_results``) and the reader +(``economy_result_reader``) share ``OPTIONAL_SECTIONS`` and ``SIDES``. +""" + +from __future__ import annotations + +from dataclasses import dataclass, field +from typing import TYPE_CHECKING + +from policyengine_simulation_persistence.result_tables import ( + POVERTY_GROUPS, + UK_AREA_DISCLOSURE_COLUMNS, +) + +if TYPE_CHECKING: + from collections.abc import Mapping + + +# The sections a result may leave null. Which of them a stored result holds is +# recorded on its report run, so a reader returns null exactly where the +# writer received null, including for empty lists. +OPTIONAL_SECTIONS = ( + "poverty_by_race", + "wealth_decile", + "intra_wealth_decile", + "labor_supply_response", + "constituency_impact", + "local_authority_impact", + "congressional_district_impact", + "cliff_impact", +) +SIDES = ("baseline", "reform") + + +# Where each field of SingleYearMacroOutput is kept. "{key}" stands for a map +# key and "[]" for a list item; per-simulation figures are kept on the +# baseline's or the reform's own simulation run, keyed by the report run and +# the side too. Labels come from the catalog +# when the result is read. A test requires this to name every field. +REFUSED_OTHER_KIND = "refused by check_storable: a record of the other kind" +_GEOGRAPHY_FIELDS = ( + "average_household_income_change", + "relative_household_income_change", + "population", + *UK_AREA_DISCLOSURE_COLUMNS, +) + + +def _poverty_storage() -> dict[str, str]: + paths = {} + for section, measures, groups in ( + ("poverty", ("poverty", "deep_poverty"), POVERTY_GROUPS["age"]), + ("poverty_by_gender", ("poverty", "deep_poverty"), POVERTY_GROUPS["gender"]), + ("poverty_by_race", ("poverty",), POVERTY_GROUPS["race"]), + ): + for measure in measures: + for group in groups: + for side in SIDES: + paths[f"{section}.{measure}.{group}.{side}"] = "poverty_rates.rate" + return paths + + +def _geography_storage( + section: str, own: str, other: str, table: str +) -> dict[str, str]: + paths = {f"{section}[].{name}": f"{table}.{name}" for name in _GEOGRAPHY_FIELDS} + paths[f"{section}[].{own}_code"] = f"{table}.{own}_code" + paths[f"{section}[].{own}_name"] = "region catalog: name" + paths[f"{section}[].x"] = "region catalog: map x" + paths[f"{section}[].y"] = "region catalog: map y" + paths[f"{section}[].{other}_code"] = REFUSED_OTHER_KIND + paths[f"{section}[].{other}_name"] = REFUSED_OTHER_KIND + return paths + + +RESULT_FIELD_STORAGE: dict[str, str] = { + "spm_provenance": "report_runs.spm_provenance", + "model_version": "report_runs.result_model_version", + "data_version": "report_runs.result_data_version", + **{ + f"budget.{name}": f"budget_impacts.{name}" + for name in ( + "budgetary_impact", + "tax_revenue_impact", + "state_tax_revenue_impact", + "benefit_spending_impact", + "households", + "baseline_net_income", + ) + }, + **{ + f"detailed_budget.{{key}}.{name}": f"program_budget_impacts.{name}" + for name in ("baseline", "reform", "difference") + }, + **{ + f"{section}.{statistic}.{{key}}": f"decile_impacts.{statistic}_change" + for section in ("decile", "wealth_decile") + for statistic in ("average", "relative") + }, + **{ + path: "intra_decile_impacts.share" + for section in ("intra_decile", "intra_wealth_decile") + for path in (f"{section}.deciles.{{key}}[]", f"{section}.all.{{key}}") + }, + **{ + f"inequality.{name}.{side}": f"inequality.{name}" + for name in ("gini", "top_10_pct_share", "top_1_pct_share") + for side in SIDES + }, + **_poverty_storage(), + **{ + f"cliff_impact.{side}.{name}": f"cliff_impacts.{name}" + for side in SIDES + for name in ("cliff_gap", "cliff_share") + }, + **{ + f"labor_supply_response.{path}": f"labor_supply_responses.{column}" + for path, column in ( + ("substitution_lsr", "substitution_lsr"), + ("income_lsr", "income_lsr"), + ("relative_lsr.income", "relative_income_response"), + ("relative_lsr.substitution", "relative_substitution_response"), + ("total_change", "total_change"), + ("revenue_change", "revenue_change"), + ("hours.baseline", "baseline_hours"), + ("hours.reform", "reform_hours"), + ("hours.change", "hours_change"), + ("hours.income_effect", "hours_income_effect"), + ("hours.substitution_effect", "hours_substitution_effect"), + ) + }, + **{ + f"labor_supply_response.decile.{statistic}.{effect}.{{key}}": ( + f"labor_supply_decile_impacts.{statistic}_{effect}_effect" + ) + for statistic in ("average", "relative") + for effect in ("income", "substitution") + }, + **{ + f"congressional_district_impact.districts[].{name}": ( + f"congressional_district_impacts.{name}" + ) + for name in ( + "district", + "average_household_income_change", + "relative_household_income_change", + "winner_percentage", + "loser_percentage", + "no_change_percentage", + "population", + ) + }, + **_geography_storage( + "constituency_impact", "constituency", "local_authority", "constituency_impacts" + ), + **_geography_storage( + "local_authority_impact", + "local_authority", + "constituency", + "local_authority_impacts", + ), +} + + +@dataclass(frozen=True) +class GeographyLabel: + """A constituency's or local authority's name and map position.""" + + name: str + x: int | None + y: int | None + + +@dataclass(frozen=True) +class EconomyResultLabels: + """What a stored result takes from the region catalog when it is read. + + Constituency and local-authority names and map positions, by code. + """ + + constituencies: Mapping[str, GeographyLabel] = field(default_factory=dict) + local_authorities: Mapping[str, GeographyLabel] = field(default_factory=dict) diff --git a/libs/policyengine-simulation-persistence/src/policyengine_simulation_persistence/economy_results.py b/libs/policyengine-simulation-persistence/src/policyengine_simulation_persistence/economy_results.py index 8a46ec363..499e3ca68 100644 --- a/libs/policyengine-simulation-persistence/src/policyengine_simulation_persistence/economy_results.py +++ b/libs/policyengine-simulation-persistence/src/policyengine_simulation_persistence/economy_results.py @@ -21,7 +21,7 @@ from __future__ import annotations -from dataclasses import dataclass, field +from dataclasses import dataclass from typing import TYPE_CHECKING, Any from policyengine_simulation_contract.macro_output import ( @@ -33,11 +33,21 @@ LocalAuthorityImpactRecord, SingleYearMacroOutput, ) -from sqlalchemy import select, update +from sqlalchemy import update from sqlalchemy.dialects.postgresql import insert as postgres_insert +from policyengine_simulation_persistence.economy_result_reader import ( + read_economy_comparison, +) +from policyengine_simulation_persistence.economy_result_storage import ( + OPTIONAL_SECTIONS, + REFUSED_OTHER_KIND, + RESULT_FIELD_STORAGE, + SIDES, + EconomyResultLabels, + GeographyLabel, +) from policyengine_simulation_persistence.result_tables import ( - POVERTY_GROUPS, UK_AREA_DISCLOSURE_COLUMNS, budget_impacts, cliff_impacts, @@ -54,181 +64,26 @@ ) from policyengine_simulation_persistence.runs import ( ReportRunRecord, - RunStatus, report_runs, ) if TYPE_CHECKING: - from collections.abc import Mapping, Sequence from uuid import UUID - from sqlalchemy import Connection, RowMapping, Table - -# The sections a result may leave null. Which of them a stored result holds is -# recorded on its report run, so a reader returns null exactly where the -# writer received null, including for empty lists. -OPTIONAL_SECTIONS = ( - "poverty_by_race", - "wealth_decile", - "intra_wealth_decile", - "labor_supply_response", - "constituency_impact", - "local_authority_impact", - "congressional_district_impact", - "cliff_impact", -) -SIDES = ("baseline", "reform") - - -# Where each field of SingleYearMacroOutput is kept. "{key}" stands for a map -# key and "[]" for a list item; per-simulation figures are kept on the -# baseline's or the reform's own simulation run, keyed by the report run and -# the side too. Labels come from the catalog -# when the result is read. A test requires this to name every field. -REFUSED_OTHER_KIND = "refused by check_storable: a record of the other kind" -_GEOGRAPHY_FIELDS = ( - "average_household_income_change", - "relative_household_income_change", - "population", - *UK_AREA_DISCLOSURE_COLUMNS, -) - - -def _poverty_storage() -> dict[str, str]: - paths = {} - for section, measures, groups in ( - ("poverty", ("poverty", "deep_poverty"), POVERTY_GROUPS["age"]), - ("poverty_by_gender", ("poverty", "deep_poverty"), POVERTY_GROUPS["gender"]), - ("poverty_by_race", ("poverty",), POVERTY_GROUPS["race"]), - ): - for measure in measures: - for group in groups: - for side in SIDES: - paths[f"{section}.{measure}.{group}.{side}"] = "poverty_rates.rate" - return paths - - -def _geography_storage( - section: str, own: str, other: str, table: str -) -> dict[str, str]: - paths = {f"{section}[].{name}": f"{table}.{name}" for name in _GEOGRAPHY_FIELDS} - paths[f"{section}[].{own}_code"] = f"{table}.{own}_code" - paths[f"{section}[].{own}_name"] = "region catalog: name" - paths[f"{section}[].x"] = "region catalog: map x" - paths[f"{section}[].y"] = "region catalog: map y" - paths[f"{section}[].{other}_code"] = REFUSED_OTHER_KIND - paths[f"{section}[].{other}_name"] = REFUSED_OTHER_KIND - return paths - - -RESULT_FIELD_STORAGE: dict[str, str] = { - "spm_provenance": "report_runs.spm_provenance", - "model_version": "report_runs.result_model_version", - "data_version": "report_runs.result_data_version", - **{ - f"budget.{name}": f"budget_impacts.{name}" - for name in ( - "budgetary_impact", - "tax_revenue_impact", - "state_tax_revenue_impact", - "benefit_spending_impact", - "households", - "baseline_net_income", - ) - }, - **{ - f"detailed_budget.{{key}}.{name}": f"program_budget_impacts.{name}" - for name in ("baseline", "reform", "difference") - }, - **{ - f"{section}.{statistic}.{{key}}": f"decile_impacts.{statistic}_change" - for section in ("decile", "wealth_decile") - for statistic in ("average", "relative") - }, - **{ - path: "intra_decile_impacts.share" - for section in ("intra_decile", "intra_wealth_decile") - for path in (f"{section}.deciles.{{key}}[]", f"{section}.all.{{key}}") - }, - **{ - f"inequality.{name}.{side}": f"inequality.{name}" - for name in ("gini", "top_10_pct_share", "top_1_pct_share") - for side in SIDES - }, - **_poverty_storage(), - **{ - f"cliff_impact.{side}.{name}": f"cliff_impacts.{name}" - for side in SIDES - for name in ("cliff_gap", "cliff_share") - }, - **{ - f"labor_supply_response.{path}": f"labor_supply_responses.{column}" - for path, column in ( - ("substitution_lsr", "substitution_lsr"), - ("income_lsr", "income_lsr"), - ("relative_lsr.income", "relative_income_response"), - ("relative_lsr.substitution", "relative_substitution_response"), - ("total_change", "total_change"), - ("revenue_change", "revenue_change"), - ("hours.baseline", "baseline_hours"), - ("hours.reform", "reform_hours"), - ("hours.change", "hours_change"), - ("hours.income_effect", "hours_income_effect"), - ("hours.substitution_effect", "hours_substitution_effect"), - ) - }, - **{ - f"labor_supply_response.decile.{statistic}.{effect}.{{key}}": ( - f"labor_supply_decile_impacts.{statistic}_{effect}_effect" - ) - for statistic in ("average", "relative") - for effect in ("income", "substitution") - }, - **{ - f"congressional_district_impact.districts[].{name}": ( - f"congressional_district_impacts.{name}" - ) - for name in ( - "district", - "average_household_income_change", - "relative_household_income_change", - "winner_percentage", - "loser_percentage", - "no_change_percentage", - "population", - ) - }, - **_geography_storage( - "constituency_impact", "constituency", "local_authority", "constituency_impacts" - ), - **_geography_storage( - "local_authority_impact", - "local_authority", - "constituency", - "local_authority_impacts", - ), -} - - -@dataclass(frozen=True) -class GeographyLabel: - """A constituency's or local authority's name and map position.""" - - name: str - x: int | None - y: int | None - - -@dataclass(frozen=True) -class EconomyResultLabels: - """What a stored result takes from the region catalog when it is read. - - Constituency and local-authority names and map positions, by code. - """ - - constituencies: Mapping[str, GeographyLabel] = field(default_factory=dict) - local_authorities: Mapping[str, GeographyLabel] = field(default_factory=dict) - + from sqlalchemy import Connection, Table + +__all__ = [ + "OPTIONAL_SECTIONS", + "REFUSED_OTHER_KIND", + "RESULT_FIELD_STORAGE", + "SIDES", + "EconomyComparisonRecorder", + "EconomyResultLabels", + "GeographyLabel", + "check_storable", + "read_economy_comparison", + "write_economy_comparison", +] # --- Checks before writing ------------------------------------------------ @@ -601,365 +456,3 @@ def write( msg = "the comparison recorder writes only validated economy results" raise TypeError(msg) write_economy_comparison(connection, report_run, result) - - -# --- Reading ---------------------------------------------------------------- - - -def _rows( - connection: Connection, - table: Table, - key_column: str, - key: UUID, - order: Sequence[str] = (), -) -> list[RowMapping]: - statement = select(table).where(table.c[key_column] == key) - if order: - statement = statement.order_by(*(table.c[name] for name in order)) - return list(connection.execute(statement).mappings()) - - -def _one( - connection: Connection, table: Table, key_column: str, key: UUID -) -> RowMapping: - rows = _rows(connection, table, key_column, key) - if len(rows) != 1: - msg = f"{table.name} has no row for {key}" - raise LookupError(msg) - return rows[0] - - -def _poverty(rows_by_side: dict[str, list[RowMapping]]) -> dict[str, Any]: - sections: dict[tuple[str, str], dict[str, dict[str, float]]] = {} - for side, side_rows in rows_by_side.items(): - for row in side_rows: - group = sections.setdefault((row["group_dimension"], row["measure"]), {}) - group.setdefault(row["group_value"], {})[side] = row["rate"] - return { - "poverty": { - "poverty": sections[("age", "poverty")], - "deep_poverty": sections[("age", "deep_poverty")], - }, - "poverty_by_gender": { - "poverty": sections[("gender", "poverty")], - "deep_poverty": sections[("gender", "deep_poverty")], - }, - "poverty_by_race": ( - {"poverty": sections[("race", "poverty")]} - if ("race", "poverty") in sections - else None - ), - } - - -def _figures( - connection: Connection, - table: Table, - report_run_id: UUID, - run_id: UUID, - side: str, -) -> list[RowMapping]: - """Return one side's own figures as one report run computed them.""" - return list( - connection.execute( - select(table).where( - table.c.report_run_id == report_run_id, - table.c.simulation_run_id == run_id, - table.c.side == side, - ) - ).mappings() - ) - - -def _one_figure( - connection: Connection, - table: Table, - report_run_id: UUID, - run_id: UUID, - side: str, -) -> RowMapping: - rows = _figures(connection, table, report_run_id, run_id, side) - if len(rows) != 1: - msg = ( - f"{table.name} has no {side} row for run {run_id} " - f"in report run {report_run_id}" - ) - raise LookupError(msg) - return rows[0] - - -def _simulation_sections( - connection: Connection, - report_run_id: UUID, - run_ids: tuple[UUID, UUID], - sections: set[str], -) -> dict[str, Any]: - by_side = { - side: _figures(connection, poverty_rates, report_run_id, run_id, side) - for side, run_id in zip(SIDES, run_ids, strict=True) - } - payload = _poverty(by_side) - if "poverty_by_race" not in sections: - payload["poverty_by_race"] = None - inequality_rows = [ - _one_figure(connection, inequality, report_run_id, run_id, side) - for side, run_id in zip(SIDES, run_ids, strict=True) - ] - payload["inequality"] = { - name: { - side: row[name] for side, row in zip(SIDES, inequality_rows, strict=True) - } - for name in ("gini", "top_10_pct_share", "top_1_pct_share") - } - payload["cliff_impact"] = None - if "cliff_impact" in sections: - cliff_rows = [ - _one_figure(connection, cliff_impacts, report_run_id, run_id, side) - for side, run_id in zip(SIDES, run_ids, strict=True) - ] - payload["cliff_impact"] = { - side: {name: row[name] for name in ("cliff_gap", "cliff_share")} - for side, row in zip(SIDES, cliff_rows, strict=True) - } - return payload - - -def _deciles(rows: list[RowMapping], measure: str) -> dict[str, dict[str, float]]: - measured = [row for row in rows if row["measure"] == measure] - return { - "average": {row["decile"]: row["average_change"] for row in measured}, - "relative": {row["decile"]: row["relative_change"] for row in measured}, - } - - -def _intra_deciles(rows: list[RowMapping], measure: str) -> dict[str, Any]: - """Rebuild one breakdown; its categories come from their average rows. - - A category whose decile shares are missing (the breakdown failed) gets an - empty list, as it was written. - """ - measured = [row for row in rows if row["measure"] == measure] - averages = sorted( - (row for row in measured if row["decile"] is None), - key=lambda row: row["outcome_position"], - ) - deciles: dict[str, list[float]] = {row["outcome"]: [] for row in averages} - for row in sorted( - (row for row in measured if row["decile"] is not None), - key=lambda row: (row["outcome_position"], row["decile"]), - ): - deciles[row["outcome"]].append(row["share"]) - return { - "deciles": deciles, - "all": {row["outcome"]: row["share"] for row in averages}, - } - - -def _labor_supply_decile_maps( - rows: list[RowMapping], statistic: str -) -> dict[str, dict[int, float]]: - """Rebuild one pair of labour supply decile maps in its own order.""" - named = sorted( - (row for row in rows if row[f"{statistic}_position"] is not None), - key=lambda row: row[f"{statistic}_position"], - ) - return { - effect: {row["decile"]: row[f"{statistic}_{effect}_effect"] for row in named} - for effect in ("income", "substitution") - } - - -def _labor_supply(connection: Connection, report_run_id: UUID) -> dict[str, Any]: - response = _one(connection, labor_supply_responses, "report_run_id", report_run_id) - deciles = _rows( - connection, labor_supply_decile_impacts, "report_run_id", report_run_id - ) - return { - "substitution_lsr": response["substitution_lsr"], - "income_lsr": response["income_lsr"], - "relative_lsr": { - "income": response["relative_income_response"], - "substitution": response["relative_substitution_response"], - }, - "total_change": response["total_change"], - "revenue_change": response["revenue_change"], - "decile": { - statistic: _labor_supply_decile_maps(deciles, statistic) - for statistic in ("average", "relative") - }, - "hours": { - "baseline": response["baseline_hours"], - "reform": response["reform_hours"], - "change": response["hours_change"], - "income_effect": response["hours_income_effect"], - "substitution_effect": response["hours_substitution_effect"], - }, - } - - -def _labelled_geographies( - rows: list[RowMapping], - code_field: str, - name_field: str, - labels: Mapping[str, GeographyLabel], -) -> list[dict[str, Any]]: - records = [] - for row in rows: - code = row[code_field] - label = labels.get(code) - if label is None: - msg = f"the region catalog has no label for {code}" - raise LookupError(msg) - records.append( - { - code_field: code, - name_field: label.name, - "x": label.x, - "y": label.y, - "average_household_income_change": row[ - "average_household_income_change" - ], - "relative_household_income_change": row[ - "relative_household_income_change" - ], - "population": row["population"], - **{name: row[name] for name in UK_AREA_DISCLOSURE_COLUMNS}, - } - ) - return records - - -def _geography_sections( - connection: Connection, - report_run_id: UUID, - sections: set[str], - labels: EconomyResultLabels, -) -> dict[str, Any]: - def ordered(table: Table) -> list[RowMapping]: - return _rows( - connection, table, "report_run_id", report_run_id, order=("position",) - ) - - payload: dict[str, Any] = { - "congressional_district_impact": None, - "constituency_impact": None, - "local_authority_impact": None, - } - if "congressional_district_impact" in sections: - payload["congressional_district_impact"] = { - "districts": [ - { - name: row[name] - for name in row.keys() # noqa: SIM118 # RowMapping keys - if name not in {"report_run_id", "position"} - } - for row in ordered(congressional_district_impacts) - ] - } - if "constituency_impact" in sections: - payload["constituency_impact"] = _labelled_geographies( - ordered(constituency_impacts), - "constituency_code", - "constituency_name", - labels.constituencies, - ) - if "local_authority_impact" in sections: - payload["local_authority_impact"] = _labelled_geographies( - ordered(local_authority_impacts), - "local_authority_code", - "local_authority_name", - labels.local_authorities, - ) - return payload - - -def _comparison_sections( - connection: Connection, - report_run_id: UUID, - sections: set[str], - labels: EconomyResultLabels, -) -> dict[str, Any]: - budget = _one(connection, budget_impacts, "report_run_id", report_run_id) - deciles = _rows( - connection, - decile_impacts, - "report_run_id", - report_run_id, - order=("measure", "position"), - ) - intra = _rows(connection, intra_decile_impacts, "report_run_id", report_run_id) - programs = _rows( - connection, - program_budget_impacts, - "report_run_id", - report_run_id, - order=("position",), - ) - return { - "budget": { - name: value for name, value in budget.items() if name != "report_run_id" - }, - "detailed_budget": { - row["program"]: { - "baseline": row["baseline"], - "reform": row["reform"], - "difference": row["difference"], - } - for row in programs - }, - "decile": _deciles(deciles, "income"), - "wealth_decile": ( - _deciles(deciles, "wealth") if "wealth_decile" in sections else None - ), - "intra_decile": _intra_deciles(intra, "income"), - "intra_wealth_decile": ( - _intra_deciles(intra, "wealth") - if "intra_wealth_decile" in sections - else None - ), - "labor_supply_response": ( - _labor_supply(connection, report_run_id) - if "labor_supply_response" in sections - else None - ), - **_geography_sections(connection, report_run_id, sections, labels), - } - - -def read_economy_comparison( - connection: Connection, report_run_id: UUID, labels: EconomyResultLabels -) -> SingleYearMacroOutput: - """Rebuild a succeeded economy report run's result from its rows. - - Raise LookupError when the report run has no succeeded comparison, or - when the labels lack a constituency or local authority the result names. - """ - report_run_row = ( - connection.execute(select(report_runs).where(report_runs.c.id == report_run_id)) - .mappings() - .first() - ) - if report_run_row is None: - msg = f"no report run {report_run_id}" - raise LookupError(msg) - report_run = ReportRunRecord.from_row(report_run_row) - if ( - report_run.comparison_status is not RunStatus.SUCCEEDED - or report_run.reform_simulation_run_id is None - ): - msg = f"report run {report_run_id} has no succeeded economy comparison" - raise LookupError(msg) - sections: set[str] = set(report_run_row["result_sections"] or ()) - run_ids = ( - report_run.baseline_simulation_run_id, - report_run.reform_simulation_run_id, - ) - return SingleYearMacroOutput.model_validate( - { - "spm_provenance": report_run_row["spm_provenance"], - "model_version": report_run_row["result_model_version"], - "data_version": report_run_row["result_data_version"], - **_comparison_sections(connection, report_run_id, sections, labels), - **_simulation_sections(connection, report_run_id, run_ids, sections), - } - ) From 29ae5bdedde9ed669b5e94205b48fdadadf27b5e Mon Sep 17 00:00:00 2001 From: Anthony Volk <14987227+anth-volk@users.noreply.github.com> Date: Fri, 30 Oct 2026 00:43:59 +0400 Subject: [PATCH 14/14] Add a changelog fragment for the result tables Co-Authored-By: Claude Opus 5.5 --- changelog.d/948.added.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/948.added.md diff --git a/changelog.d/948.added.md b/changelog.d/948.added.md new file mode 100644 index 000000000..35d5f83bd --- /dev/null +++ b/changelog.d/948.added.md @@ -0,0 +1 @@ +Added the result tables, in migration revision `0004` of the `simulation` schema. Each section of an economy result (`SingleYearMacroOutput`) is stored as rows: a simulation run's poverty rates, inequality and cliff impacts, and a report run's budget, program, decile, intra-decile, labour supply, congressional district, constituency and local authority impacts. A computed household is stored as one JSON value on its simulation run, and `output_files` links each stored file to one run. A reader rebuilds the economy result exactly from the rows, with constituency and local authority names and map positions from the region catalog. No route writes results yet.