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 plotly.express as px
from policyengine_core.charts import format_fig
sim = Microsimulation()
period = 2026
household_benefits = sim.calc("household_benefits", period=period)
household_pensions = sim.calc("pension_income", period=period, map_to="household")
household_investment_income = sim.calc(
"net_investment_income", period=period, map_to="household"
)
household_earnings = sim.calc(
"employment_income", period=period, map_to="household"
) + sim.calc("self_employment_income", period=period, map_to="household")
total_income = (
household_benefits
+ household_pensions
+ household_investment_income
+ household_earnings
)
household_income_decile = sim.calc(
"equiv_household_net_income", period=period
).decile_rank()
income_source_decodes = {
"Earnings": household_earnings,
"Pensions": household_pensions,
"Investment": household_investment_income,
"State support": household_benefits,
}
deciles = []
values = []
income_sources = []
for decile in range(1, 11):
in_decile = household_income_decile == decile
decile_total_income = total_income[in_decile].sum()
cumulative_income = 0
for income_source, income_source_values in income_source_decodes.items():
deciles.append(decile)
income_sources.append(income_source)
income_source_total = max(income_source_values[in_decile].sum(), 0)
values.append(income_source_total / decile_total_income)
cumulative_income += income_source_total
deciles.append(decile)
income_sources.append("Other")
values.append(1 - cumulative_income / decile_total_income)
df = pd.DataFrame(
{
"Decile": deciles,
"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(["Decile", "Income source"], ascending=[True, False])
fig = px.bar(
df,
x="Decile",
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 decile",
tickvals=list(range(1, 11)),
),
)
fig = format_fig(fig).update_layout(
title="Sources of income by household income decile",
)
fig