Skip to content

Commit 41edccb

Browse files
authored
Assign is_parent from FRS microdata (#343)
1 parent 7329e55 commit 41edccb

5 files changed

Lines changed: 78 additions & 1 deletion

File tree

changelog.d/73.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Assign `is_parent` from FRS adult-table membership and benefit-unit dependent-child counts (#73).

policyengine_uk_data/datasets/frs.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,36 @@ def attach_legacy_benefit_proxies_from_frs_person(
228228
)
229229

230230

231+
def derive_is_parent_from_frs_microdata(
232+
person_ids,
233+
person_benunit_ids,
234+
adult_person_ids,
235+
benunit_ids,
236+
dependent_children,
237+
) -> np.ndarray:
238+
"""Identify FRS adults in benefit units with dependent children.
239+
240+
FRS benefit units contain either one adult or a couple plus any dependent
241+
children. Using the raw adult table and benefit-unit dependent-child count
242+
avoids ranking adults across the whole household when multiple benefit
243+
units share a household.
244+
"""
245+
246+
dependent_children_by_benunit = pd.Series(
247+
np.asarray(dependent_children, dtype=float),
248+
index=np.asarray(benunit_ids),
249+
)
250+
has_dependent_children = (
251+
pd.Series(np.asarray(person_benunit_ids))
252+
.map(dependent_children_by_benunit)
253+
.fillna(0)
254+
.to_numpy()
255+
> 0
256+
)
257+
is_adult_record = np.isin(np.asarray(person_ids), np.asarray(adult_person_ids))
258+
return is_adult_record & has_dependent_children
259+
260+
231261
def _as_non_negative_array(values) -> np.ndarray:
232262
values = np.asarray(values, dtype=float)
233263
return np.maximum(np.nan_to_num(values, nan=0.0), 0.0)
@@ -443,6 +473,23 @@ def create_frs(
443473
pe_person["hours_worked"] = np.maximum(person.tothours, 0) * 52
444474
pe_person["is_household_head"] = person.hrpid == 1
445475
pe_person["is_benunit_head"] = person.uperson == 1
476+
dependent_children = (
477+
benunit.depchldb
478+
if "depchldb" in benunit
479+
else frs["child"]
480+
.groupby("benunit_id")
481+
.size()
482+
.reindex(benunit.benunit_id)
483+
.fillna(0)
484+
.to_numpy()
485+
)
486+
pe_person["is_parent"] = derive_is_parent_from_frs_microdata(
487+
person_ids=pe_person.person_id,
488+
person_benunit_ids=pe_person.person_benunit_id,
489+
adult_person_ids=frs["adult"].person_id,
490+
benunit_ids=pe_benunit.benunit_id,
491+
dependent_children=dependent_children,
492+
)
446493
MARITAL = [
447494
"MARRIED",
448495
"SINGLE",
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import numpy as np
2+
3+
from policyengine_uk_data.datasets.frs import derive_is_parent_from_frs_microdata
4+
5+
6+
def test_is_parent_uses_benefit_unit_not_household_rank():
7+
result = derive_is_parent_from_frs_microdata(
8+
person_ids=np.array([1_001, 1_002, 1_003, 1_004]),
9+
person_benunit_ids=np.array([101, 101, 102, 102]),
10+
adult_person_ids=np.array([1_001, 1_002, 1_003]),
11+
benunit_ids=np.array([101, 102]),
12+
dependent_children=np.array([0, 1]),
13+
)
14+
15+
assert result.tolist() == [False, False, True, False]
16+
17+
18+
def test_is_parent_marks_both_adults_in_couple_with_children():
19+
result = derive_is_parent_from_frs_microdata(
20+
person_ids=np.array([2_001, 2_002, 2_003]),
21+
person_benunit_ids=np.array([201, 201, 201]),
22+
adult_person_ids=np.array([2_001, 2_002]),
23+
benunit_ids=np.array([201]),
24+
dependent_children=np.array([1]),
25+
)
26+
27+
assert result.tolist() == [True, True, False]

policyengine_uk_data/tests/test_legacy_benefit_proxies.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -465,6 +465,8 @@ def fake_read_csv(path, *args, **kwargs):
465465
"legacy_jobseeker_proxy",
466466
"esa_health_condition_proxy",
467467
"esa_support_group_proxy",
468+
"is_parent",
468469
}.issubset(dataset.person.columns)
470+
assert not dataset.person["is_parent"].iloc[0]
469471
assert dataset.person["education_grants"].iloc[0] == 100
470472
assert dataset.person["disabled_students_allowance_eligible_expenses"].iloc[0] == 0

uv.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)