Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions changelog_entry.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
- bump: minor
changes:
added:
- Child poverty impact function.
7 changes: 7 additions & 0 deletions docs/outputs/calculate_child_poverty_impacts.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Child poverty impacts

This extension calculates the change in child poverty.

```{eval-rst}
.. autofunction:: policyengine.outputs.macro.comparison.poverty.calculate_child_poverty_impacts.calculate_child_poverty_impacts
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import pandas as pd
from policyengine import Simulation as PolicyEngine # Rename Simulation to PolicyEngine to avoid name conflict
from policyengine_core.simulations import Simulation
from pydantic import BaseModel

class ChildPovertyImpactParameters(BaseModel): # Ask extension developers to validate inputs to their functions
count_years: int
start_year: int
country: str
reform: dict

def calculate_child_poverty_impacts(
engine: PolicyEngine,
country: str,
reform: dict,
count_years: int = 10,
start_year: int = 2024,

) -> pd.DataFrame:
"""The change in mean child poverty under baseline vs reform.
Args:
engine: A PolicyEngine instance.
is_child(bool): person level
in_poverty(bool): spm_unit level
Returns:
The change in mean child poverty under baseline vs reform.
"""

ChildPovertyImpactParameters.model_validate(
count_years=count_years,
start_year=start_year,
)

baseline_simulation: Simulation = engine.build_simulation(
name="baseline", # Optionally, we could cache named simulations so we're not rerunning baseline each time. Or not!
country=country,
policy={},
scope="macro",
)

reform_simulation: Simulation = engine.build_simulation(
name="reform",
country=country,
policy=reform,
scope="macro",
)

end_year = start_year + count_years

years = []
baseline_child_poverty = []
reform_child_poverty = []
child_poverty_change = []

for year in range(start_year, end_year):
baseline_cp = _get_child_povert_chnage(
baseline_simulation, year
).mean()
reform_cp = _get_child_povert_chnage(
reform_simulation, year
).mean()
years.append(year)
baseline_child_poverty.append(baseline_cp)
reform_child_poverty.append(reform_cp)
child_poverty_change.append(reform_cp - baseline_cp)

return pd.DataFrame(
{
"year": years,
"baseline_child_poverty": baseline_child_poverty,
"reform_child_poverty": reform_child_poverty,
"child_poverty_change": child_poverty_change,
}
)


def _get_child_povert_chnage(
sim: Microsimulation,
year: int,
):
is_child = sim.calculate("is_child", period=year)
in_poverty = sim.calculate("in_poverty", map_to="person", period=year)
return in_poverty[is_child].mean()
17 changes: 17 additions & 0 deletions tests/country/test_child_poverty.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
def test_child_poverty():
from policyengine import Simulation

sim = Simulation(
country="us",
scope="macro",
reform={
"gov.irs.credits.ctc.refundable.fully_refundable": True,
},
)

child_poverty = sim.calculate_child_poverty_impacts(count_years=3)

assert len(child_poverty) == 3
assert (child_poverty.child_poverty_change < 0).all()
assert (child_poverty.reform_child_poverty > 0).all()
assert (child_poverty.baseline_child_poverty > 0).all()
Loading