policyengine 2.2.0__tar.gz → 2.2.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {policyengine-2.2.0 → policyengine-2.2.2}/CHANGELOG.md +14 -0
- {policyengine-2.2.0 → policyengine-2.2.2}/PKG-INFO +1 -1
- {policyengine-2.2.0 → policyengine-2.2.2}/changelog.yaml +10 -0
- {policyengine-2.2.0 → policyengine-2.2.2}/docs/_config.yml +3 -10
- {policyengine-2.2.0 → policyengine-2.2.2}/policyengine/outputs/macro/comparison/budget/general.py +3 -1
- policyengine-2.2.2/policyengine/outputs/macro/comparison/local_areas/parliamentary_constituencies.py +46 -0
- policyengine-2.2.2/policyengine/outputs/macro/single/gov/local_areas/parliamentary_constituencies.py +85 -0
- {policyengine-2.2.0 → policyengine-2.2.2}/policyengine/outputs/macro/single/household/income_distribution.py +1 -1
- {policyengine-2.2.0 → policyengine-2.2.2}/policyengine/simulation.py +11 -0
- policyengine-2.2.2/policyengine/utils/constituency_maps.py +91 -0
- {policyengine-2.2.0 → policyengine-2.2.2}/policyengine.egg-info/PKG-INFO +1 -1
- {policyengine-2.2.0 → policyengine-2.2.2}/policyengine.egg-info/SOURCES.txt +1 -0
- {policyengine-2.2.0 → policyengine-2.2.2}/pyproject.toml +1 -1
- policyengine-2.2.0/policyengine/outputs/macro/comparison/local_areas/parliamentary_constituencies.py +0 -167
- policyengine-2.2.0/policyengine/outputs/macro/single/gov/local_areas/parliamentary_constituencies.py +0 -47
- {policyengine-2.2.0 → policyengine-2.2.2}/.github/CONTRIBUTING.md +0 -0
- {policyengine-2.2.0 → policyengine-2.2.2}/.github/changelog_template.md +0 -0
- {policyengine-2.2.0 → policyengine-2.2.2}/.github/fetch_version.py +0 -0
- {policyengine-2.2.0 → policyengine-2.2.2}/.github/get-changelog-diff.sh +0 -0
- {policyengine-2.2.0 → policyengine-2.2.2}/.github/has-functional-changes.sh +0 -0
- {policyengine-2.2.0 → policyengine-2.2.2}/.github/is-version-number-acceptable.sh +0 -0
- {policyengine-2.2.0 → policyengine-2.2.2}/.github/publish-git-tag.sh +0 -0
- {policyengine-2.2.0 → policyengine-2.2.2}/.github/workflows/pr.yml +0 -0
- {policyengine-2.2.0 → policyengine-2.2.2}/.github/workflows/push.yml +0 -0
- {policyengine-2.2.0 → policyengine-2.2.2}/.gitignore +0 -0
- {policyengine-2.2.0 → policyengine-2.2.2}/LICENSE +0 -0
- {policyengine-2.2.0 → policyengine-2.2.2}/Makefile +0 -0
- {policyengine-2.2.0 → policyengine-2.2.2}/README.md +0 -0
- {policyengine-2.2.0 → policyengine-2.2.2}/changelog_entry.yaml +0 -0
- {policyengine-2.2.0 → policyengine-2.2.2}/docs/_static/style.css +0 -0
- {policyengine-2.2.0 → policyengine-2.2.2}/docs/_toc.yml +0 -0
- {policyengine-2.2.0 → policyengine-2.2.2}/docs/index.ipynb +0 -0
- {policyengine-2.2.0 → policyengine-2.2.2}/docs/logo.png +0 -0
- {policyengine-2.2.0 → policyengine-2.2.2}/docs/maintaining.ipynb +0 -0
- {policyengine-2.2.0 → policyengine-2.2.2}/docs/schema.ipynb +0 -0
- {policyengine-2.2.0 → policyengine-2.2.2}/policyengine/__init__.py +0 -0
- {policyengine-2.2.0 → policyengine-2.2.2}/policyengine/constants.py +0 -0
- {policyengine-2.2.0 → policyengine-2.2.2}/policyengine/outputs/household/comparison/net_income_change.py +0 -0
- {policyengine-2.2.0 → policyengine-2.2.2}/policyengine/outputs/household/single/net_income.py +0 -0
- {policyengine-2.2.0 → policyengine-2.2.2}/policyengine/outputs/macro/comparison/budget/programs.py +0 -0
- {policyengine-2.2.0 → policyengine-2.2.2}/policyengine/outputs/macro/comparison/budget/window.py +0 -0
- {policyengine-2.2.0 → policyengine-2.2.2}/policyengine/outputs/macro/comparison/decile/income.py +0 -0
- {policyengine-2.2.0 → policyengine-2.2.2}/policyengine/outputs/macro/comparison/decile/wealth.py +0 -0
- {policyengine-2.2.0 → policyengine-2.2.2}/policyengine/outputs/macro/comparison/inequality.py +0 -0
- {policyengine-2.2.0 → policyengine-2.2.2}/policyengine/outputs/macro/comparison/labor_supply_response.py +0 -0
- {policyengine-2.2.0 → policyengine-2.2.2}/policyengine/outputs/macro/comparison/poverty/age.py +0 -0
- {policyengine-2.2.0 → policyengine-2.2.2}/policyengine/outputs/macro/comparison/poverty/gender.py +0 -0
- {policyengine-2.2.0 → policyengine-2.2.2}/policyengine/outputs/macro/comparison/poverty/race.py +0 -0
- {policyengine-2.2.0 → policyengine-2.2.2}/policyengine/outputs/macro/comparison/winners/income_decile.py +0 -0
- {policyengine-2.2.0 → policyengine-2.2.2}/policyengine/outputs/macro/comparison/winners/wealth_decile.py +0 -0
- {policyengine-2.2.0 → policyengine-2.2.2}/policyengine/outputs/macro/single/gov/balance.py +0 -0
- {policyengine-2.2.0 → policyengine-2.2.2}/policyengine/outputs/macro/single/gov/budget_window.py +0 -0
- {policyengine-2.2.0 → policyengine-2.2.2}/policyengine/outputs/macro/single/gov/programs.py +0 -0
- {policyengine-2.2.0 → policyengine-2.2.2}/policyengine/outputs/macro/single/household/demographics.py +0 -0
- {policyengine-2.2.0 → policyengine-2.2.2}/policyengine/outputs/macro/single/household/finance.py +0 -0
- {policyengine-2.2.0 → policyengine-2.2.2}/policyengine/outputs/macro/single/household/inequality.py +0 -0
- {policyengine-2.2.0 → policyengine-2.2.2}/policyengine/outputs/macro/single/household/labor_supply.py +0 -0
- {policyengine-2.2.0 → policyengine-2.2.2}/policyengine/utils/__init__.py +0 -0
- {policyengine-2.2.0 → policyengine-2.2.2}/policyengine/utils/charts.py +0 -0
- {policyengine-2.2.0 → policyengine-2.2.2}/policyengine/utils/huggingface.py +0 -0
- {policyengine-2.2.0 → policyengine-2.2.2}/policyengine.egg-info/dependency_links.txt +0 -0
- {policyengine-2.2.0 → policyengine-2.2.2}/policyengine.egg-info/requires.txt +0 -0
- {policyengine-2.2.0 → policyengine-2.2.2}/policyengine.egg-info/top_level.txt +0 -0
- {policyengine-2.2.0 → policyengine-2.2.2}/setup.cfg +0 -0
|
@@ -5,6 +5,18 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [2.2.2] - 2024-12-06 14:02:41
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
|
|
12
|
+
- Household simulation example broken due to a type error.
|
|
13
|
+
|
|
14
|
+
## [2.2.1] - 2024-12-03 13:16:27
|
|
15
|
+
|
|
16
|
+
### Fixed
|
|
17
|
+
|
|
18
|
+
- Formatting in constituency charts.
|
|
19
|
+
|
|
8
20
|
## [2.2.0] - 2024-12-02 13:48:27
|
|
9
21
|
|
|
10
22
|
### Added
|
|
@@ -39,6 +51,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
39
51
|
|
|
40
52
|
|
|
41
53
|
|
|
54
|
+
[2.2.2]: https://github.com/PolicyEngine/policyengine.py/compare/2.2.1...2.2.2
|
|
55
|
+
[2.2.1]: https://github.com/PolicyEngine/policyengine.py/compare/2.2.0...2.2.1
|
|
42
56
|
[2.2.0]: https://github.com/PolicyEngine/policyengine.py/compare/2.1.0...2.2.0
|
|
43
57
|
[2.1.0]: https://github.com/PolicyEngine/policyengine.py/compare/2.0.0...2.1.0
|
|
44
58
|
[2.0.0]: https://github.com/PolicyEngine/policyengine.py/compare/1.0.1...2.0.0
|
|
@@ -26,3 +26,13 @@
|
|
|
26
26
|
- State level subsets.
|
|
27
27
|
- Huggingface token CLI entry.
|
|
28
28
|
date: 2024-12-02 13:48:27
|
|
29
|
+
- bump: patch
|
|
30
|
+
changes:
|
|
31
|
+
fixed:
|
|
32
|
+
- Formatting in constituency charts.
|
|
33
|
+
date: 2024-12-03 13:16:27
|
|
34
|
+
- bump: patch
|
|
35
|
+
changes:
|
|
36
|
+
fixed:
|
|
37
|
+
- Household simulation example broken due to a type error.
|
|
38
|
+
date: 2024-12-06 14:02:41
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# _config.yml
|
|
2
|
-
title: PolicyEngine
|
|
3
2
|
author: PolicyEngine
|
|
4
|
-
|
|
3
|
+
title: PolicyEngine
|
|
4
|
+
copyright: "2025"
|
|
5
5
|
logo: logo.png
|
|
6
6
|
|
|
7
7
|
execute:
|
|
@@ -19,11 +19,4 @@ sphinx:
|
|
|
19
19
|
html_theme: furo
|
|
20
20
|
pygments_style: default
|
|
21
21
|
html_css_files:
|
|
22
|
-
- style.css
|
|
23
|
-
# extra_extensions:
|
|
24
|
-
# - sphinx.ext.autodoc
|
|
25
|
-
# - sphinxarg.ext
|
|
26
|
-
# - sphinx.ext.viewcode
|
|
27
|
-
# - sphinx.ext.napoleon
|
|
28
|
-
# - sphinx_math_dollar
|
|
29
|
-
# - sphinx.ext.mathjax
|
|
22
|
+
- style.css
|
{policyengine-2.2.0 → policyengine-2.2.2}/policyengine/outputs/macro/comparison/budget/general.py
RENAMED
|
@@ -104,6 +104,8 @@ def budget_chart(simulation: Simulation, data: dict) -> go.Figure:
|
|
|
104
104
|
xaxis_title="",
|
|
105
105
|
yaxis_title="Budgetary impact (£ billions)",
|
|
106
106
|
yaxis_tickformat=",.0f",
|
|
107
|
+
uniformtext_minsize=12,
|
|
108
|
+
uniformtext_mode="hide",
|
|
107
109
|
)
|
|
108
110
|
|
|
109
|
-
return format_fig(fig)
|
|
111
|
+
return format_fig(fig, simulation.country)
|
policyengine-2.2.2/policyengine/outputs/macro/comparison/local_areas/parliamentary_constituencies.py
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
from policyengine import Simulation
|
|
2
|
+
import pandas as pd
|
|
3
|
+
from policyengine.utils.huggingface import download
|
|
4
|
+
import plotly.express as px
|
|
5
|
+
from policyengine.utils.charts import *
|
|
6
|
+
from policyengine.utils.constituency_maps import plot_hex_map
|
|
7
|
+
from typing import Callable
|
|
8
|
+
from policyengine_core import Microsimulation
|
|
9
|
+
from microdf import MicroSeries
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def parliamentary_constituencies(
|
|
13
|
+
simulation: Simulation,
|
|
14
|
+
chart: bool = False,
|
|
15
|
+
metric: Callable[[Microsimulation], MicroSeries] = None,
|
|
16
|
+
comparator: bool = None,
|
|
17
|
+
) -> dict:
|
|
18
|
+
if not simulation.options.get("include_constituencies"):
|
|
19
|
+
return {}
|
|
20
|
+
|
|
21
|
+
kwargs = {}
|
|
22
|
+
if metric is not None:
|
|
23
|
+
kwargs["metric"] = metric
|
|
24
|
+
|
|
25
|
+
if comparator is None:
|
|
26
|
+
comparator = lambda x, y: (y / x) - 1
|
|
27
|
+
|
|
28
|
+
constituency_baseline = simulation.calculate(
|
|
29
|
+
"macro/baseline/gov/local_areas/parliamentary_constituencies", **kwargs
|
|
30
|
+
)
|
|
31
|
+
constituency_reform = simulation.calculate(
|
|
32
|
+
"macro/reform/gov/local_areas/parliamentary_constituencies", **kwargs
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
result = {}
|
|
36
|
+
|
|
37
|
+
for constituency in constituency_baseline:
|
|
38
|
+
result[constituency] = comparator(
|
|
39
|
+
constituency_baseline[constituency],
|
|
40
|
+
constituency_reform[constituency],
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
if chart:
|
|
44
|
+
return plot_hex_map(result)
|
|
45
|
+
|
|
46
|
+
return result
|
policyengine-2.2.2/policyengine/outputs/macro/single/gov/local_areas/parliamentary_constituencies.py
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
from policyengine import Simulation
|
|
2
|
+
from policyengine.utils.huggingface import download
|
|
3
|
+
import h5py
|
|
4
|
+
from microdf import MicroSeries
|
|
5
|
+
import pandas as pd
|
|
6
|
+
from typing import Callable
|
|
7
|
+
from policyengine_core import Microsimulation
|
|
8
|
+
from policyengine.utils.constituency_maps import plot_hex_map
|
|
9
|
+
|
|
10
|
+
DEFAULT_VARIABLES = [
|
|
11
|
+
"household_net_income",
|
|
12
|
+
]
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def parliamentary_constituencies(
|
|
16
|
+
simulation: Simulation,
|
|
17
|
+
metric: Callable[[Microsimulation], MicroSeries] = None,
|
|
18
|
+
chart: bool = False,
|
|
19
|
+
) -> dict:
|
|
20
|
+
"""Calculate the impact of the reform on parliamentary constituencies.
|
|
21
|
+
|
|
22
|
+
Args:
|
|
23
|
+
simulation (Simulation): The simulation for which the impact is to be calculated.
|
|
24
|
+
custom_function (Callable[[Microsimulation], [float]]): A custom function to calculate the impact. This must be called on a Microsimulation and return a float (we will call it for each constituency weight set).
|
|
25
|
+
|
|
26
|
+
"""
|
|
27
|
+
if not simulation.options.get("include_constituencies"):
|
|
28
|
+
return {}
|
|
29
|
+
|
|
30
|
+
if metric is None:
|
|
31
|
+
metric = lambda sim: sim.calculate("household_net_income").median()
|
|
32
|
+
weights_file_path = download(
|
|
33
|
+
repo="policyengine/policyengine-uk-data",
|
|
34
|
+
repo_filename="parliamentary_constituency_weights.h5",
|
|
35
|
+
local_folder=None,
|
|
36
|
+
version=None,
|
|
37
|
+
)
|
|
38
|
+
constituency_names_file_path = download(
|
|
39
|
+
repo="policyengine/policyengine-uk-data",
|
|
40
|
+
repo_filename="constituencies_2024.csv",
|
|
41
|
+
local_folder=None,
|
|
42
|
+
version=None,
|
|
43
|
+
)
|
|
44
|
+
constituency_names = pd.read_csv(constituency_names_file_path)
|
|
45
|
+
|
|
46
|
+
with h5py.File(weights_file_path, "r") as f:
|
|
47
|
+
weights = f[str(simulation.time_period)][...]
|
|
48
|
+
|
|
49
|
+
result = {}
|
|
50
|
+
|
|
51
|
+
sim = simulation.selected
|
|
52
|
+
original_hh_weight = sim.calculate("household_weight").values
|
|
53
|
+
|
|
54
|
+
for constituency_id in range(weights.shape[0]):
|
|
55
|
+
sim.set_input(
|
|
56
|
+
"household_weight",
|
|
57
|
+
sim.default_calculation_period,
|
|
58
|
+
weights[constituency_id],
|
|
59
|
+
)
|
|
60
|
+
sim.get_holder("person_weight").delete_arrays(
|
|
61
|
+
sim.default_calculation_period
|
|
62
|
+
)
|
|
63
|
+
sim.get_holder("benunit_weight").delete_arrays(
|
|
64
|
+
sim.default_calculation_period
|
|
65
|
+
)
|
|
66
|
+
calculation_result = metric(simulation.selected)
|
|
67
|
+
code = constituency_names.code.iloc[constituency_id]
|
|
68
|
+
result[constituency_names.set_index("code").loc[code]["name"]] = (
|
|
69
|
+
calculation_result
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
sim.get_holder("person_weight").delete_arrays(
|
|
73
|
+
sim.default_calculation_period
|
|
74
|
+
)
|
|
75
|
+
sim.get_holder("benunit_weight").delete_arrays(
|
|
76
|
+
sim.default_calculation_period
|
|
77
|
+
)
|
|
78
|
+
sim.set_input(
|
|
79
|
+
"household_weight", sim.default_calculation_period, original_hh_weight
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
if chart:
|
|
83
|
+
return plot_hex_map(result)
|
|
84
|
+
|
|
85
|
+
return result
|
|
@@ -29,7 +29,7 @@ def income_distribution_chart(simulation: Simulation) -> go.Figure:
|
|
|
29
29
|
color_discrete_sequence=[BLUE],
|
|
30
30
|
)
|
|
31
31
|
fig.update_layout(
|
|
32
|
-
title="Number of
|
|
32
|
+
title="Number of households by net income band",
|
|
33
33
|
xaxis_title="Household net income",
|
|
34
34
|
yaxis_title="Number of households",
|
|
35
35
|
)
|
|
@@ -39,6 +39,8 @@ class Simulation:
|
|
|
39
39
|
"""The tax-benefit simulation for the baseline scenario."""
|
|
40
40
|
reformed: CountrySimulation = None
|
|
41
41
|
"""The tax-benefit simulation for the reformed scenario."""
|
|
42
|
+
selected: CountryMicrosimulation = None
|
|
43
|
+
"""The selected simulation for the current calculation."""
|
|
42
44
|
verbose: bool = False
|
|
43
45
|
"""Whether to print out progress messages."""
|
|
44
46
|
|
|
@@ -74,6 +76,11 @@ class Simulation:
|
|
|
74
76
|
elif isinstance(reform, int):
|
|
75
77
|
reform = Reform.from_api(reform, country_id=country)
|
|
76
78
|
|
|
79
|
+
if isinstance(baseline, dict):
|
|
80
|
+
baseline = Reform.from_dict(baseline, country_id=country)
|
|
81
|
+
elif isinstance(baseline, int):
|
|
82
|
+
baseline = Reform.from_api(baseline, country_id=country)
|
|
83
|
+
|
|
77
84
|
self.baseline = baseline
|
|
78
85
|
self.reform = reform
|
|
79
86
|
|
|
@@ -84,6 +91,10 @@ class Simulation:
|
|
|
84
91
|
self._initialise_simulations()
|
|
85
92
|
|
|
86
93
|
def _set_dataset(self, dataset: str):
|
|
94
|
+
if isinstance(dataset, dict):
|
|
95
|
+
self.data = dataset
|
|
96
|
+
return
|
|
97
|
+
|
|
87
98
|
if dataset in DATASETS[self.country]:
|
|
88
99
|
self.data = DATASETS[self.country][dataset]
|
|
89
100
|
elif dataset is None:
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import pandas as pd
|
|
2
|
+
import plotly.express as px
|
|
3
|
+
from policyengine import Simulation
|
|
4
|
+
import pandas as pd
|
|
5
|
+
from policyengine.utils.huggingface import download
|
|
6
|
+
import plotly.express as px
|
|
7
|
+
from policyengine.utils.charts import *
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def plot_hex_map(value_by_constituency_name: dict) -> dict:
|
|
11
|
+
constituency_names_file_path = download(
|
|
12
|
+
repo="policyengine/policyengine-uk-data",
|
|
13
|
+
repo_filename="constituencies_2024.csv",
|
|
14
|
+
local_folder=None,
|
|
15
|
+
version=None,
|
|
16
|
+
)
|
|
17
|
+
constituency_names = pd.read_csv(constituency_names_file_path)
|
|
18
|
+
|
|
19
|
+
x_range = constituency_names["x"].max() - constituency_names["x"].min()
|
|
20
|
+
y_range = constituency_names["y"].max() - constituency_names["y"].min()
|
|
21
|
+
# Expand x range to preserve aspect ratio
|
|
22
|
+
expanded_lower_x_range = -(y_range - x_range) / 2
|
|
23
|
+
expanded_upper_x_range = x_range - expanded_lower_x_range
|
|
24
|
+
constituency_names.x = (
|
|
25
|
+
constituency_names.x - (constituency_names.y % 2 == 0) * 0.5
|
|
26
|
+
)
|
|
27
|
+
constituency_names["Value"] = (
|
|
28
|
+
pd.Series(
|
|
29
|
+
list(value_by_constituency_name.values()),
|
|
30
|
+
index=list(value_by_constituency_name.keys()),
|
|
31
|
+
)
|
|
32
|
+
.loc[constituency_names["name"]]
|
|
33
|
+
.values
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
fig = px.scatter(
|
|
37
|
+
constituency_names,
|
|
38
|
+
x="x",
|
|
39
|
+
y="y",
|
|
40
|
+
color="Value",
|
|
41
|
+
hover_name="name",
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
format_fig(fig)
|
|
45
|
+
|
|
46
|
+
# Show hexagons on scatter points
|
|
47
|
+
|
|
48
|
+
fig.update_traces(
|
|
49
|
+
marker=dict(
|
|
50
|
+
symbol="hexagon", line=dict(width=0, color="lightgray"), size=15
|
|
51
|
+
)
|
|
52
|
+
)
|
|
53
|
+
fig.update_layout(
|
|
54
|
+
xaxis_tickvals=[],
|
|
55
|
+
xaxis_title="",
|
|
56
|
+
yaxis_tickvals=[],
|
|
57
|
+
yaxis_title="",
|
|
58
|
+
xaxis_range=[expanded_lower_x_range, expanded_upper_x_range],
|
|
59
|
+
yaxis_range=[
|
|
60
|
+
constituency_names["y"].min(),
|
|
61
|
+
constituency_names["y"].max(),
|
|
62
|
+
],
|
|
63
|
+
).update_traces(marker_size=10).update_layout(
|
|
64
|
+
xaxis_range=[30, 85], yaxis_range=[-50, 2]
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
x_min = fig.data[0]["marker"]["color"].min()
|
|
68
|
+
x_max = fig.data[0]["marker"]["color"].max()
|
|
69
|
+
max_abs = max(abs(x_min), abs(x_max))
|
|
70
|
+
|
|
71
|
+
if x_min < 0:
|
|
72
|
+
colorscale = [
|
|
73
|
+
[0, DARK_GRAY],
|
|
74
|
+
[0.5, "lightgray"],
|
|
75
|
+
[1, BLUE],
|
|
76
|
+
]
|
|
77
|
+
else:
|
|
78
|
+
colorscale = [
|
|
79
|
+
[0, "lightgray"],
|
|
80
|
+
[1, BLUE],
|
|
81
|
+
]
|
|
82
|
+
|
|
83
|
+
fig.update_layout(
|
|
84
|
+
coloraxis=dict(
|
|
85
|
+
cmin=-max_abs if x_min < 0 else 0,
|
|
86
|
+
cmax=max_abs,
|
|
87
|
+
colorscale=colorscale,
|
|
88
|
+
)
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
return fig
|
policyengine-2.2.0/policyengine/outputs/macro/comparison/local_areas/parliamentary_constituencies.py
DELETED
|
@@ -1,167 +0,0 @@
|
|
|
1
|
-
from policyengine import Simulation
|
|
2
|
-
import pandas as pd
|
|
3
|
-
from policyengine.utils.huggingface import download
|
|
4
|
-
import plotly.express as px
|
|
5
|
-
from policyengine.utils.charts import *
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
def parliamentary_constituencies(
|
|
9
|
-
simulation: Simulation,
|
|
10
|
-
chart: bool = False,
|
|
11
|
-
variable: str = None,
|
|
12
|
-
aggregator: str = None,
|
|
13
|
-
relative: bool = None,
|
|
14
|
-
) -> dict:
|
|
15
|
-
if not simulation.options.get("include_constituencies"):
|
|
16
|
-
return {}
|
|
17
|
-
|
|
18
|
-
if chart:
|
|
19
|
-
return heatmap(
|
|
20
|
-
simulation=simulation,
|
|
21
|
-
variable=variable,
|
|
22
|
-
aggregator=aggregator,
|
|
23
|
-
relative=relative,
|
|
24
|
-
)
|
|
25
|
-
|
|
26
|
-
constituency_baseline = simulation.calculate(
|
|
27
|
-
"macro/baseline/gov/local_areas/parliamentary_constituencies"
|
|
28
|
-
)
|
|
29
|
-
constituency_reform = simulation.calculate(
|
|
30
|
-
"macro/reform/gov/local_areas/parliamentary_constituencies"
|
|
31
|
-
)
|
|
32
|
-
|
|
33
|
-
result = {}
|
|
34
|
-
|
|
35
|
-
for constituency in constituency_baseline:
|
|
36
|
-
result[constituency] = {}
|
|
37
|
-
for key in constituency_baseline[constituency]:
|
|
38
|
-
result[constituency][key] = {
|
|
39
|
-
"change": constituency_reform[constituency][key]
|
|
40
|
-
- constituency_baseline[constituency][key],
|
|
41
|
-
"baseline": constituency_baseline[constituency][key],
|
|
42
|
-
"reform": constituency_reform[constituency][key],
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
return result
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
def heatmap(
|
|
49
|
-
simulation: Simulation,
|
|
50
|
-
variable: str = None,
|
|
51
|
-
aggregator: str = None,
|
|
52
|
-
relative: bool = None,
|
|
53
|
-
) -> dict:
|
|
54
|
-
if not simulation.options.get("include_constituencies"):
|
|
55
|
-
return {}
|
|
56
|
-
|
|
57
|
-
options = {}
|
|
58
|
-
|
|
59
|
-
if variable is not None:
|
|
60
|
-
options["variables"] = [variable]
|
|
61
|
-
if aggregator is not None:
|
|
62
|
-
options["aggregator"] = aggregator
|
|
63
|
-
|
|
64
|
-
constituency_baseline = simulation.calculate(
|
|
65
|
-
"macro/baseline/gov/local_areas/parliamentary_constituencies",
|
|
66
|
-
**options,
|
|
67
|
-
)
|
|
68
|
-
constituency_reform = simulation.calculate(
|
|
69
|
-
"macro/reform/gov/local_areas/parliamentary_constituencies", **options
|
|
70
|
-
)
|
|
71
|
-
|
|
72
|
-
result = {}
|
|
73
|
-
|
|
74
|
-
constituency_names_file_path = download(
|
|
75
|
-
repo="policyengine/policyengine-uk-data",
|
|
76
|
-
repo_filename="constituencies_2024.csv",
|
|
77
|
-
local_folder=None,
|
|
78
|
-
version=None,
|
|
79
|
-
)
|
|
80
|
-
constituency_names = pd.read_csv(constituency_names_file_path)
|
|
81
|
-
|
|
82
|
-
if variable is None:
|
|
83
|
-
variable = "household_net_income"
|
|
84
|
-
if relative is None:
|
|
85
|
-
relative = True
|
|
86
|
-
|
|
87
|
-
for constituency in constituency_baseline:
|
|
88
|
-
if relative:
|
|
89
|
-
result[constituency] = (
|
|
90
|
-
constituency_reform[constituency][variable]
|
|
91
|
-
/ constituency_baseline[constituency][variable]
|
|
92
|
-
- 1
|
|
93
|
-
)
|
|
94
|
-
else:
|
|
95
|
-
result[constituency] = (
|
|
96
|
-
constituency_reform[constituency][variable]
|
|
97
|
-
- constituency_baseline[constituency][variable]
|
|
98
|
-
)
|
|
99
|
-
|
|
100
|
-
x_range = constituency_names["x"].max() - constituency_names["x"].min()
|
|
101
|
-
y_range = constituency_names["y"].max() - constituency_names["y"].min()
|
|
102
|
-
# Expand x range to preserve aspect ratio
|
|
103
|
-
expanded_lower_x_range = -(y_range - x_range) / 2
|
|
104
|
-
expanded_upper_x_range = x_range - expanded_lower_x_range
|
|
105
|
-
constituency_names.x = (
|
|
106
|
-
constituency_names.x - (constituency_names.y % 2 == 0) * 0.5
|
|
107
|
-
)
|
|
108
|
-
constituency_names["Relative change"] = (
|
|
109
|
-
pd.Series(list(result.values()), index=list(result.keys()))
|
|
110
|
-
.loc[constituency_names["name"]]
|
|
111
|
-
.values
|
|
112
|
-
)
|
|
113
|
-
|
|
114
|
-
label = simulation.baseline.tax_benefit_system.variables[variable].label
|
|
115
|
-
|
|
116
|
-
fig = px.scatter(
|
|
117
|
-
constituency_names,
|
|
118
|
-
x="x",
|
|
119
|
-
y="y",
|
|
120
|
-
color="Relative change",
|
|
121
|
-
hover_name="name",
|
|
122
|
-
title=f"{'Relative change' if relative else 'Change'} in {label} by parliamentary constituency",
|
|
123
|
-
)
|
|
124
|
-
|
|
125
|
-
format_fig(fig)
|
|
126
|
-
|
|
127
|
-
# Show hexagons on scatter points
|
|
128
|
-
|
|
129
|
-
fig.update_traces(
|
|
130
|
-
marker=dict(
|
|
131
|
-
symbol="hexagon", line=dict(width=0, color="lightgray"), size=15
|
|
132
|
-
)
|
|
133
|
-
)
|
|
134
|
-
fig.update_layout(
|
|
135
|
-
xaxis_tickvals=[],
|
|
136
|
-
xaxis_title="",
|
|
137
|
-
yaxis_tickvals=[],
|
|
138
|
-
yaxis_title="",
|
|
139
|
-
xaxis_range=[expanded_lower_x_range, expanded_upper_x_range],
|
|
140
|
-
yaxis_range=[
|
|
141
|
-
constituency_names["y"].min(),
|
|
142
|
-
constituency_names["y"].max(),
|
|
143
|
-
],
|
|
144
|
-
).update_traces(marker_size=10).update_layout(
|
|
145
|
-
xaxis_range=[30, 85], yaxis_range=[-50, 2]
|
|
146
|
-
)
|
|
147
|
-
|
|
148
|
-
x_min = fig.data[0]["marker"]["color"].min()
|
|
149
|
-
x_max = fig.data[0]["marker"]["color"].max()
|
|
150
|
-
max_abs = max(abs(x_min), abs(x_max))
|
|
151
|
-
|
|
152
|
-
fig.update_layout(
|
|
153
|
-
coloraxis=dict(
|
|
154
|
-
cmin=-max_abs,
|
|
155
|
-
cmax=max_abs,
|
|
156
|
-
colorscale=[
|
|
157
|
-
[0, DARK_GRAY],
|
|
158
|
-
[0.5, "lightgray"],
|
|
159
|
-
[1, BLUE],
|
|
160
|
-
],
|
|
161
|
-
colorbar=dict(
|
|
162
|
-
tickformat=".0%" if relative else ",.0f",
|
|
163
|
-
),
|
|
164
|
-
)
|
|
165
|
-
)
|
|
166
|
-
|
|
167
|
-
return fig
|
policyengine-2.2.0/policyengine/outputs/macro/single/gov/local_areas/parliamentary_constituencies.py
DELETED
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
from policyengine import Simulation
|
|
2
|
-
from policyengine.utils.huggingface import download
|
|
3
|
-
import h5py
|
|
4
|
-
from microdf import MicroDataFrame
|
|
5
|
-
import pandas as pd
|
|
6
|
-
|
|
7
|
-
DEFAULT_VARIABLES = [
|
|
8
|
-
"household_net_income",
|
|
9
|
-
]
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
def parliamentary_constituencies(
|
|
13
|
-
simulation: Simulation,
|
|
14
|
-
variables: list = DEFAULT_VARIABLES,
|
|
15
|
-
aggregator: str = "sum",
|
|
16
|
-
) -> dict:
|
|
17
|
-
if not simulation.options.get("include_constituencies"):
|
|
18
|
-
return {}
|
|
19
|
-
weights_file_path = download(
|
|
20
|
-
repo="policyengine/policyengine-uk-data",
|
|
21
|
-
repo_filename="parliamentary_constituency_weights.h5",
|
|
22
|
-
local_folder=None,
|
|
23
|
-
version=None,
|
|
24
|
-
)
|
|
25
|
-
constituency_names_file_path = download(
|
|
26
|
-
repo="policyengine/policyengine-uk-data",
|
|
27
|
-
repo_filename="constituencies_2024.csv",
|
|
28
|
-
local_folder=None,
|
|
29
|
-
version=None,
|
|
30
|
-
)
|
|
31
|
-
constituency_names = pd.read_csv(constituency_names_file_path)
|
|
32
|
-
|
|
33
|
-
with h5py.File(weights_file_path, "r") as f:
|
|
34
|
-
weights = f[str(simulation.time_period)][...]
|
|
35
|
-
|
|
36
|
-
sim_df = simulation.selected.calculate_dataframe(variables)
|
|
37
|
-
|
|
38
|
-
result = {}
|
|
39
|
-
|
|
40
|
-
for constituency_id in range(weights.shape[0]):
|
|
41
|
-
weighted_df = MicroDataFrame(sim_df, weights=weights[constituency_id])
|
|
42
|
-
code = constituency_names.code.iloc[constituency_id]
|
|
43
|
-
result[constituency_names.set_index("code").loc[code]["name"]] = (
|
|
44
|
-
getattr(weighted_df, aggregator)().to_dict()
|
|
45
|
-
)
|
|
46
|
-
|
|
47
|
-
return result
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{policyengine-2.2.0 → policyengine-2.2.2}/policyengine/outputs/household/single/net_income.py
RENAMED
|
File without changes
|
{policyengine-2.2.0 → policyengine-2.2.2}/policyengine/outputs/macro/comparison/budget/programs.py
RENAMED
|
File without changes
|
{policyengine-2.2.0 → policyengine-2.2.2}/policyengine/outputs/macro/comparison/budget/window.py
RENAMED
|
File without changes
|
{policyengine-2.2.0 → policyengine-2.2.2}/policyengine/outputs/macro/comparison/decile/income.py
RENAMED
|
File without changes
|
{policyengine-2.2.0 → policyengine-2.2.2}/policyengine/outputs/macro/comparison/decile/wealth.py
RENAMED
|
File without changes
|
{policyengine-2.2.0 → policyengine-2.2.2}/policyengine/outputs/macro/comparison/inequality.py
RENAMED
|
File without changes
|
|
File without changes
|
{policyengine-2.2.0 → policyengine-2.2.2}/policyengine/outputs/macro/comparison/poverty/age.py
RENAMED
|
File without changes
|
{policyengine-2.2.0 → policyengine-2.2.2}/policyengine/outputs/macro/comparison/poverty/gender.py
RENAMED
|
File without changes
|
{policyengine-2.2.0 → policyengine-2.2.2}/policyengine/outputs/macro/comparison/poverty/race.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{policyengine-2.2.0 → policyengine-2.2.2}/policyengine/outputs/macro/single/gov/budget_window.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{policyengine-2.2.0 → policyengine-2.2.2}/policyengine/outputs/macro/single/household/finance.py
RENAMED
|
File without changes
|
{policyengine-2.2.0 → policyengine-2.2.2}/policyengine/outputs/macro/single/household/inequality.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|