|
1 | | -"""Miscellaneous compute functions (vehicles, housing, savings, SCP).""" |
| 1 | +"""Miscellaneous compute functions (vehicles, housing, savings, SCP, |
| 2 | +student loans).""" |
2 | 3 |
|
3 | 4 | import numpy as np |
4 | 5 |
|
| 6 | +_ENGLAND_REGIONS = { |
| 7 | + "NORTH_EAST", |
| 8 | + "NORTH_WEST", |
| 9 | + "YORKSHIRE", |
| 10 | + "EAST_MIDLANDS", |
| 11 | + "WEST_MIDLANDS", |
| 12 | + "EAST_OF_ENGLAND", |
| 13 | + "LONDON", |
| 14 | + "SOUTH_EAST", |
| 15 | + "SOUTH_WEST", |
| 16 | +} |
| 17 | + |
5 | 18 |
|
6 | 19 | def compute_vehicles(target, ctx) -> np.ndarray: |
7 | 20 | """Compute vehicle ownership targets.""" |
@@ -34,3 +47,25 @@ def compute_scottish_child_payment(target, ctx) -> np.ndarray: |
34 | 47 | """Compute Scottish child payment spend.""" |
35 | 48 | scp = ctx.sim.calculate("scottish_child_payment") |
36 | 49 | return ctx.household_from_person(scp) |
| 50 | + |
| 51 | + |
| 52 | +def compute_student_loan_plan(target, ctx) -> np.ndarray: |
| 53 | + """Count England borrowers on a given plan with repayments > 0. |
| 54 | +
|
| 55 | + SLC targets cover borrowers liable to repay AND earning above threshold |
| 56 | + in England only — matching exactly what the FRS captures via PAYE. |
| 57 | + """ |
| 58 | + plan_name = target.name # e.g. "slc/plan_2_borrowers_above_threshold" |
| 59 | + if "plan_2" in plan_name: |
| 60 | + plan_value = "PLAN_2" |
| 61 | + elif "plan_5" in plan_name: |
| 62 | + plan_value = "PLAN_5" |
| 63 | + else: |
| 64 | + return None |
| 65 | + |
| 66 | + plan = ctx.sim.calculate("student_loan_plan").values |
| 67 | + region = ctx.sim.calculate("region", map_to="person").values |
| 68 | + is_england = np.isin(region, list(_ENGLAND_REGIONS)) |
| 69 | + on_plan = (plan == plan_value) & is_england |
| 70 | + |
| 71 | + return ctx.household_from_person(on_plan.astype(float)) |
0 commit comments