Net income after taxes and benefits¶
This shows a range of Ontario households.
Show code cell source
from policyengine_canada import Microsimulation, Simulation
from policyengine_core.reforms import Reform
from policyengine_canada.model_api import *
import pandas as pd
YEAR = 2023
def make_hh(adults, children, child_age):
people = dict(head=dict(age=30))
members = ["head"]
if adults == 2:
people["spouse"] = dict(age=30)
members += ["spouse"]
for i in range(children):
people[f"child{i}"] = dict(age=child_age)
members += [f"child{i}"]
return dict(
people=people,
households=dict(household=dict(members=members, province="ONTARIO")),
# Same impact for households with $250k+ income, so show up to $300k.
# $1k increments.
axes=[[dict(name="employment_income", count=301, min=0, max=300_000)]],
)
l = []
for adults in [1, 2]:
for children in [0, 1, 2, 3]:
for child_age in [1]:
hh = make_hh(adults, children, child_age)
baseline_hh = Simulation(situation=hh)
l.append(
pd.DataFrame(
dict(
adults=adults,
children=children,
child_age=child_age,
# Reshape combined array to get head's varied earnings.
employment_income=baseline_hh.calculate(
"employment_income", YEAR
)[0 :: (adults + children)],
household_net_income=baseline_hh.calculate(
"household_net_income", YEAR
),
mtr=baseline_hh.calculate("marginal_tax_rate", YEAR)[
0 :: (adults + children)
],
)
)
)
df = pd.concat(l)
df
/opt/hostedtoolcache/Python/3.12.7/x64/lib/python3.12/site-packages/tqdm/auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html
from .autonotebook import tqdm as notebook_tqdm
adults | children | child_age | employment_income | household_net_income | mtr | |
---|---|---|---|---|---|---|
0 | 1 | 0 | 1 | 0.0 | 373.000000 | 0.000000 |
1 | 1 | 0 | 1 | 1000.0 | 1373.000000 | 0.000000 |
2 | 1 | 0 | 1 | 2000.0 | 2373.000000 | 0.000000 |
3 | 1 | 0 | 1 | 3000.0 | 3373.000000 | -0.270000 |
4 | 1 | 0 | 1 | 4000.0 | 4643.000000 | -0.270000 |
... | ... | ... | ... | ... | ... | ... |
296 | 2 | 3 | 1 | 296000.0 | 205400.062500 | 0.461594 |
297 | 2 | 3 | 1 | 297000.0 | 205938.468750 | 0.461594 |
298 | 2 | 3 | 1 | 298000.0 | 206476.875000 | 0.461609 |
299 | 2 | 3 | 1 | 299000.0 | 207015.265625 | 0.461594 |
300 | 2 | 3 | 1 | 300000.0 | 207553.671875 | 0.461609 |
2408 rows × 6 columns
Show code cell source
from policyengine_canada import Simulation
sim = Simulation(
situation=dict(
people=dict(
person=dict(
age=30,
employment_income=20_000,
)
)
)
)
sim.calculate("household_net_income")
array([21633.], dtype=float32)
Here’s an example of using axes to calculate how variables relate to each other. Income tax is a progressive schedule (for an example), and people over 65 are exempt. The chart below plots income tax by income and age together.
import plotly.express as px
px.line(
df,
"employment_income",
"household_net_income",
color="children",
facet_col="adults",
title="Household net income by employment income",
)
px.line(
df,
"employment_income",
"mtr",
color="children",
facet_col="adults",
title="Marginal tax rate by employment income",
)