Skip to content

Commit f5a463a

Browse files
Refresh HBAI columns after structural post-hooks (#38)
1 parent 823828c commit f5a463a

1 file changed

Lines changed: 49 additions & 0 deletions

File tree

interfaces/python/policyengine_uk_compiled/structural.py

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,55 @@ def weighted_median(values: np.ndarray, weights: np.ndarray) -> float:
131131
cutoff = weights.sum() / 2.0
132132
return float(values[np.searchsorted(np.cumsum(weights), cutoff, side="left")])
133133

134+
def refresh_household_hbai_columns(hh: "pd.DataFrame") -> "pd.DataFrame":
135+
"""Recompute derived HBAI household columns from primitive inputs.
136+
137+
Post-hooks often mutate household net income directly. Re-deriving the
138+
AHC and equivalised fields here keeps poverty metrics consistent with
139+
those changes, rather than trusting stale columns emitted before the
140+
hook ran.
141+
"""
142+
hh = hh.copy()
143+
144+
if "housing_costs_ahc_annual" in hh.columns:
145+
housing_costs = hh["housing_costs_ahc_annual"].fillna(0.0)
146+
elif {"baseline_net_income", "baseline_net_income_ahc"}.issubset(hh.columns):
147+
housing_costs = (
148+
hh["baseline_net_income"].fillna(0.0)
149+
- hh["baseline_net_income_ahc"].fillna(0.0)
150+
)
151+
else:
152+
housing_costs = 0.0
153+
154+
for prefix in ("baseline", "reform"):
155+
net_col = f"{prefix}_net_income"
156+
net_ahc_col = f"{prefix}_net_income_ahc"
157+
eq_factor_col = f"{prefix}_equivalisation_factor"
158+
eq_col = f"{prefix}_equivalised_net_income"
159+
eq_factor_ahc_col = f"{prefix}_equivalisation_factor_ahc"
160+
eq_ahc_col = f"{prefix}_equivalised_net_income_ahc"
161+
162+
if net_col not in hh.columns:
163+
continue
164+
165+
hh[net_ahc_col] = hh[net_col].fillna(0.0) - housing_costs
166+
167+
if eq_factor_col in hh.columns:
168+
eq_factor = hh[eq_factor_col].fillna(1.0).clip(lower=1e-9)
169+
hh[eq_col] = hh[net_col].fillna(0.0) / eq_factor
170+
elif eq_col not in hh.columns:
171+
hh[eq_col] = hh[net_col].fillna(0.0)
172+
173+
if eq_factor_ahc_col in hh.columns:
174+
eq_factor_ahc = hh[eq_factor_ahc_col].fillna(1.0).clip(lower=1e-9)
175+
hh[eq_ahc_col] = hh[net_ahc_col].fillna(0.0) / eq_factor_ahc
176+
elif eq_ahc_col not in hh.columns:
177+
hh[eq_ahc_col] = hh[net_ahc_col].fillna(0.0)
178+
179+
return hh
180+
181+
households = refresh_household_hbai_columns(households)
182+
134183
person_counts = persons.groupby("household_id").size() if "household_id" in persons.columns else pd.Series(dtype=float)
135184

136185
def hbai_for(prefix: str) -> HbaiIncomes:

0 commit comments

Comments
 (0)