Income sources#
This chart, mirroring Figure 12 of the UK’s Households Below Average Income poverty publication, shows the breakdown of income sources for each income decile.
from policyengine_us import Microsimulation
import pandas as pd
import numpy as np
sim = Microsimulation()
household_benefits = sim.calculate("household_benefits")
household_pensions = sim.calculate("pension_income", map_to="household")
household_investment_income = sim.calculate(
"net_investment_income", map_to="household"
)
household_earnings = sim.calculate(
"employment_income", map_to="household"
) + sim.calculate("self_employment_income", map_to="household")
total_income = (
household_benefits
+ household_pensions
+ household_investment_income
+ household_earnings
)
equivalised_income = sim.calculate("equiv_household_net_income")
household_count_people = sim.calculate("people", map_to="household")
equivalised_income.weights *= household_count_people.values
household_income_percentile = equivalised_income.percentile_rank()
income_source_decodes = {
"Earnings": household_earnings,
"Pensions": household_pensions,
"Investment": household_investment_income,
"State support": household_benefits,
}
percentiles = []
values = []
income_sources = []
for percentile in range(1, 101):
in_decile = household_income_percentile == percentile
cumulative_income = 0
for income_source in income_source_decodes:
percentiles.append(percentile)
income_sources.append(income_source)
income_source_values = income_source_decodes[income_source]
values.append(
np.maximum(income_source_values[in_decile].sum(), 0)
/ total_income[in_decile].sum()
)
cumulative_income += np.maximum(
income_source_values[in_decile].sum(), 0
)
# Add 'other income'
percentiles.append(percentile)
income_sources.append("Other")
values.append(1 - cumulative_income / total_income[in_decile].sum())
df = pd.DataFrame(
{
"Percentile": percentiles,
"Income source": income_sources,
"Value": values,
}
)
# Order by state support, other income, pensions, investment, earnings
df["Income source"] = pd.Categorical(
df["Income source"],
["State support", "Other", "Pensions", "Investment", "Earnings"],
)
df = df.sort_values(["Percentile", "Income source"], ascending=[True, False])
import plotly.express as px
from policyengine_core.charts import format_fig
fig = px.bar(
df,
x="Percentile",
y="Value",
color="Income source",
).update_layout(
height=600,
width=800,
# No bar gap
bargap=0,
# No space between bars
bargroupgap=0,
yaxis=dict(
tickformat=".0%",
title="Percentage of income",
tickvals=[0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1],
),
xaxis=dict(
title="Income percentile",
tickvals=list(range(1, 101, 10)),
),
)
fig = format_fig(fig).update_layout(
title="Sources of income for pensioner households",
)
fig