Skip to content

Commit 7a32306

Browse files
baogorekclaude
authored andcommitted
Convert WIC float draws to bools for consistency with other takeup variables
Resolves category-specific rate comparisons at data generation time so only bools (would_claim_wic, wic_nutritional_risk_imputed) are stored in the dataset, matching the pattern used by all other takeup variables. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent b22b857 commit 7a32306

5 files changed

Lines changed: 102 additions & 12 deletions

File tree

policyengine_us_data/datasets/cps/cps.py

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -268,13 +268,24 @@ def add_takeup(self):
268268
rng = seeded_rng("meets_ssi_resource_test")
269269
data["meets_ssi_resource_test"] = rng.random(n_persons) < ssi_pass_rate
270270

271-
# WIC draws (country package compares against category-specific rates)
272-
rng = seeded_rng("wic_takeup_draw")
273-
data["wic_takeup_draw"] = rng.random(n_persons).astype(np.float32)
271+
# WIC: resolve draws to bools using category-specific rates
272+
wic_categories = baseline.calculate("wic_category_str").values
273+
wic_takeup_rates = load_take_up_rate("wic_takeup", self.time_period)
274+
wic_takeup_rate_by_person = np.array(
275+
[wic_takeup_rates.get(c, 0) for c in wic_categories]
276+
)
277+
rng = seeded_rng("would_claim_wic")
278+
data["would_claim_wic"] = rng.random(n_persons) < wic_takeup_rate_by_person
274279

275-
rng = seeded_rng("wic_nutritional_risk_draw")
276-
data["wic_nutritional_risk_draw"] = rng.random(n_persons).astype(
277-
np.float32
280+
wic_risk_rates = load_take_up_rate(
281+
"wic_nutritional_risk", self.time_period
282+
)
283+
wic_risk_rate_by_person = np.array(
284+
[wic_risk_rates.get(c, 0) for c in wic_categories]
285+
)
286+
rng = seeded_rng("wic_nutritional_risk_imputed")
287+
data["wic_nutritional_risk_imputed"] = (
288+
rng.random(n_persons) < wic_risk_rate_by_person
278289
)
279290

280291
self.save_dataset(data)

policyengine_us_data/parameters/__init__.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,20 @@ def load_take_up_rate(variable_name: str, year: int = 2018):
3535
if "rates_by_state" in data:
3636
return data["rates_by_state"]
3737

38+
# WIC-style: rates by category (each category has a time series)
39+
if "rates_by_category" in data:
40+
result = {}
41+
for category, time_series in data["rates_by_category"].items():
42+
applicable_value = None
43+
for y, value in sorted(time_series.items()):
44+
if int(y) <= year:
45+
applicable_value = value
46+
else:
47+
break
48+
if applicable_value is not None:
49+
result[category] = applicable_value
50+
return result
51+
3852
# Standard time-series values
3953
values = data["values"]
4054
applicable_value = None
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
rates_by_category:
2+
PREGNANT:
3+
1980: 0.913
4+
POSTPARTUM:
5+
1980: 0.933
6+
BREASTFEEDING:
7+
1980: 0.889
8+
INFANT:
9+
1980: 0.95
10+
CHILD:
11+
1980: 0.752
12+
NONE:
13+
1980: 0
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
rates_by_category:
2+
PREGNANT:
3+
2018: 0.533
4+
2019: 0.523
5+
2020: 0.456
6+
2021: 0.437
7+
2022: 0.456
8+
POSTPARTUM:
9+
2018: 0.844
10+
2019: 0.847
11+
2020: 0.685
12+
2021: 0.672
13+
2022: 0.689
14+
BREASTFEEDING:
15+
2018: 0.687
16+
2019: 0.684
17+
2020: 0.604
18+
2021: 0.608
19+
2022: 0.663
20+
INFANT:
21+
2018: 0.978
22+
2019: 0.984
23+
2020: 0.817
24+
2021: 0.78
25+
2022: 0.784
26+
CHILD:
27+
2018: 0.442
28+
2019: 0.448
29+
2020: 0.406
30+
2021: 0.432
31+
2022: 0.46
32+
NONE:
33+
2018: 0

policyengine_us_data/tests/test_stochastic_variables.py

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -117,12 +117,31 @@ def test_boolean_generation(self):
117117
assert take_up.dtype == bool
118118
assert set(take_up).issubset({True, False})
119119

120-
def test_wic_draws_are_float(self):
121-
rng = seeded_rng("wic_takeup_draw")
122-
draws = rng.random(1000).astype(np.float32)
123-
assert draws.dtype == np.float32
124-
assert np.all(draws >= 0)
125-
assert np.all(draws < 1)
120+
def test_wic_takeup_rates_load(self):
121+
rates = load_take_up_rate("wic_takeup", 2022)
122+
assert isinstance(rates, dict)
123+
assert rates["PREGNANT"] == 0.456
124+
assert rates["INFANT"] == 0.784
125+
assert rates["NONE"] == 0
126+
127+
def test_wic_nutritional_risk_rates_load(self):
128+
rates = load_take_up_rate("wic_nutritional_risk", 2022)
129+
assert isinstance(rates, dict)
130+
assert rates["INFANT"] == 0.95
131+
assert rates["CHILD"] == 0.752
132+
assert rates["NONE"] == 0
133+
134+
def test_wic_category_specific_proportions(self):
135+
rates = load_take_up_rate("wic_takeup", 2022)
136+
n = 10_000
137+
rng = seeded_rng("would_claim_wic")
138+
draws = rng.random(n)
139+
for category, expected_rate in [
140+
("INFANT", 0.784),
141+
("CHILD", 0.46),
142+
]:
143+
take_up = draws[:n] < expected_rate
144+
assert abs(take_up.mean() - expected_rate) < 0.05
126145

127146
def test_state_specific_medicaid_proportions(self):
128147
rates = load_take_up_rate("medicaid", 2022)

0 commit comments

Comments
 (0)