Charts#
PolicyEngine Core provides a set of chart utils to speed up data visualisation for PolicyEngine model-powered analyses. These use the PolicyEngine styling by default. The examples below use the PolicyEngine UK microsimulation model.
Bar chart#
The bar_chart
function creates a bar chart from a dataframe.
# Reform code generated from the PolicyEngine export function.
from policyengine_uk import Microsimulation
from policyengine_core.reforms import Reform
from policyengine_core.periods import instant
def modify_parameters(parameters):
parameters.gov.hmrc.income_tax.rates.uk[0].rate.update(
start=instant("2023-01-01"), stop=instant("2028-12-31"), value=0.25
)
return parameters
class reform(Reform):
def apply(self):
self.modify_parameters(modify_parameters)
baseline = Microsimulation()
reformed = Microsimulation(reform=reform)
baseline_income = baseline.calculate("household_net_income", 2023)
reformed_income = reformed.calculate("household_net_income", 2023)
gain = reformed_income - baseline_income
decile = baseline.calculate("household_income_decile", 2023)
decile_impacts = (
gain.groupby(decile).sum() / baseline_income.groupby(decile).sum()
)
decile_impacts = decile_impacts[decile_impacts.index != 0]
from policyengine_core.charts import *
display_fig(
bar_chart(
decile_impacts,
title="Change in net income by decile",
xaxis_title="Decile",
yaxis_title="Change in net income",
xaxis_tickvals=list(range(1, 11)),
yaxis_tickformat=".0%",
text_format=".1%",
hover_text_function=lambda x, y: f"The {cardinal(x)} decile sees a {y:+.1%} in net income",
)
)
Cross-section bar chart#
The cross-section bar chart is useful for showing the distribution of outcomes along different breakdowns.
lower_age_group = baseline.calculate("age", 2023) // 10
personal_gain = reformed.calculate(
"household_net_income", 2023, map_to="person"
) - baseline.calculate("household_net_income", 2023, map_to="person")
personal_gain = personal_gain[lower_age_group < 8]
lower_age_group = lower_age_group[lower_age_group < 8] + 1
display_fig(
cross_section_bar_chart(
personal_gain,
lower_age_group,
slices=[-0.1, -0.01, 0.01, 0.1],
xaxis_tickformat=".0%",
category_names=[
"Lose more than 10%",
"Lose between 1% and 10%",
"Experience less than 1% change",
"Gain between 1% and 10%",
"Gain more than 10%",
],
yaxis_ticktext=[
"Under 10",
"10 to 19",
"20 to 29",
"30 to 39",
"40 to 49",
"50 to 59",
"60 to 69",
"70 to 79",
],
color_discrete_map={
"Lose more than 10%": DARK_GRAY,
"Lose between 1% and 10%": MEDIUM_DARK_GRAY,
"Experience less than 1% change": GRAY,
"Gain between 1% and 10%": LIGHT_GRAY,
"Gain more than 10%": BLUE,
},
legend_orientation="h",
legend_y=-0.2,
title="Gain by age",
hover_text_function=lambda age, outcome, percent: f"{percent:.1%} of {age * 10:.0f} to {(age + 1) * 10:.0f} year olds {outcome.lower()} of their income",
)
)