-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #47 from PolicyEngine/dev
Add budget charts
- Loading branch information
Showing
13 changed files
with
305 additions
and
100 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
109 changes: 109 additions & 0 deletions
109
policyengine/outputs/macro/comparison/budget/general.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
from policyengine import Simulation | ||
import plotly.graph_objects as go | ||
import plotly.express as px | ||
import pandas as pd | ||
from policyengine.utils.charts import * | ||
|
||
|
||
def general(simulation: Simulation, chart: bool = False): | ||
"""Calculate the budgetary impact of the given simulation. | ||
Args: | ||
simulation (Simulation): The simulation for which the revenue impact is to be calculated. | ||
Returns: | ||
dict: A dictionary containing the budgetary impact details with the following keys: | ||
- budgetary_impact (float): The overall budgetary impact. | ||
- tax_revenue_impact (float): The impact on tax revenue. | ||
- state_tax_revenue_impact (float): The impact on state tax revenue. | ||
- benefit_spending_impact (float): The impact on benefit spending. | ||
- households (int): The number of households. | ||
- baseline_net_income (float): The total net income in the baseline scenario. | ||
""" | ||
baseline = simulation.calculate("macro/baseline") | ||
reform = simulation.calculate("macro/reform") | ||
|
||
tax_revenue_impact = ( | ||
reform["gov"]["balance"]["total_tax"] | ||
- baseline["gov"]["balance"]["total_tax"] | ||
) | ||
state_tax_revenue_impact = ( | ||
reform["gov"]["balance"]["total_state_tax"] | ||
- baseline["gov"]["balance"]["total_state_tax"] | ||
) | ||
benefit_spending_impact = ( | ||
reform["gov"]["balance"]["total_spending"] | ||
- baseline["gov"]["balance"]["total_spending"] | ||
) | ||
budgetary_impact = tax_revenue_impact - benefit_spending_impact | ||
households = sum(baseline["household"]["demographics"]["household_weight"]) | ||
baseline_net_income = baseline["household"]["finance"]["total_net_income"] | ||
result = dict( | ||
budgetary_impact=budgetary_impact, | ||
tax_revenue_impact=tax_revenue_impact, | ||
state_tax_revenue_impact=state_tax_revenue_impact, | ||
benefit_spending_impact=benefit_spending_impact, | ||
households=households, | ||
baseline_net_income=baseline_net_income, | ||
) | ||
if chart: | ||
return budget_chart(simulation, result) | ||
else: | ||
return result | ||
|
||
|
||
def budget_chart(simulation: Simulation, data: dict) -> go.Figure: | ||
if simulation.country == "uk": | ||
x = ["Tax revenues", "Benefit spending", "Budgetary impact"] | ||
y = [ | ||
data["tax_revenue_impact"], | ||
-data["benefit_spending_impact"], | ||
data["budgetary_impact"], | ||
] | ||
else: | ||
x = [ | ||
"Federal tax revenues", | ||
"State tax revenues", | ||
"Benefit spending", | ||
"Budgetary impact", | ||
] | ||
y = [ | ||
data["tax_revenue_impact"] - data["state_tax_revenue_impact"], | ||
data["state_tax_revenue_impact"], | ||
-data["benefit_spending_impact"], | ||
data["budgetary_impact"], | ||
] | ||
fig = go.Figure( | ||
data=[ | ||
go.Waterfall( | ||
x=x, | ||
y=[i / 1e9 for i in y], | ||
orientation="v", | ||
measure=["relative"] * (len(x) - 1) + ["total"], | ||
text=[ | ||
( | ||
"+" + str(round(val / 1e9, 1)) | ||
if val > 0 | ||
else str(round(val / 1e9, 1)) | ||
) | ||
for val in y | ||
], | ||
textposition="inside", | ||
increasing={"marker": {"color": BLUE}}, | ||
decreasing={"marker": {"color": DARK_GRAY}}, | ||
totals={"marker": {"color": BLUE if y[-1] > 0 else DARK_GRAY}}, | ||
connector={ | ||
"line": {"color": DARK_GRAY, "width": 2, "dash": "dot"} | ||
}, | ||
) | ||
] | ||
) | ||
|
||
fig.update_layout( | ||
title="Budgetary impact by government revenue and spending", | ||
xaxis_title="", | ||
yaxis_title="Budgetary impact (£ billions)", | ||
yaxis_tickformat=",.0f", | ||
) | ||
|
||
return format_fig(fig) |
2 changes: 1 addition & 1 deletion
2
...tputs/macro/comparison/detailed_budget.py → ...tputs/macro/comparison/budget/programs.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
from policyengine import Simulation | ||
import plotly.graph_objects as go | ||
import plotly.express as px | ||
import pandas as pd | ||
from policyengine.utils.charts import * | ||
|
||
|
||
def window( | ||
simulation: Simulation, | ||
chart: bool = False, | ||
federal_only: bool = False, | ||
count_years: int = 1, | ||
): | ||
if count_years == 1: | ||
kwargs = {} | ||
else: | ||
kwargs = {"count_years": count_years} | ||
baseline = simulation.calculate( | ||
"macro/baseline/gov/budget_window", **kwargs | ||
) | ||
reform = simulation.calculate("macro/reform/gov/budget_window", **kwargs) | ||
total_budget_effect = [ | ||
(y - x) / 1e9 | ||
for x, y in zip(baseline["total_budget"], reform["total_budget"]) | ||
] | ||
federal_budget_effect = [ | ||
(y - x) / 1e9 | ||
for x, y in zip( | ||
baseline["total_federal_budget"], reform["total_federal_budget"] | ||
) | ||
] | ||
|
||
result = dict( | ||
total_budget=total_budget_effect, | ||
federal_budget=federal_budget_effect, | ||
) | ||
|
||
if chart: | ||
return budget_window_chart( | ||
result["federal_budget"] | ||
if federal_only | ||
else result["total_budget"] | ||
) | ||
else: | ||
return result | ||
|
||
|
||
def budget_window_chart(budget_effect) -> go.Figure: | ||
fig = go.Figure( | ||
data=[ | ||
go.Bar( | ||
y=budget_effect, | ||
x=list(map(str, range(2025, 2025 + 10))), | ||
marker=dict( | ||
color=[BLUE if y > 0 else DARK_GRAY for y in budget_effect] | ||
), | ||
text=[ | ||
f"{'+' if y >= 0 else ''}{y:.1f}" for y in budget_effect | ||
], | ||
) | ||
] | ||
).update_layout( | ||
title="Budgetary impact by year", | ||
xaxis_title="Year", | ||
yaxis_title="Budgetary impact (£ billions)", | ||
) | ||
|
||
return format_fig(fig) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
27 changes: 0 additions & 27 deletions
27
policyengine/outputs/macro/comparison/local_areas/parliamentary_constituencies/data.py
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.