Skip to content
This repository was archived by the owner on Jul 2, 2026. It is now read-only.

Commit e0be63b

Browse files
authored
Remove reported SPM data inputs (#960)
* Remove reported SPM data inputs * Require policyengine-us 1.691.3
1 parent c3a4624 commit e0be63b

12 files changed

Lines changed: 73 additions & 52 deletions

File tree

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Remove reported SPM WIC, school meals, broadband, and tax inputs from CPS outputs in favor of policyengine-us formulas.

policyengine_us_data/datasets/cps/cps.py

Lines changed: 8 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -444,7 +444,7 @@ def add_rent(self, cps: h5py.File, person: DataFrame, household: DataFrame):
444444
# Assume zero housing assistance since
445445
cps["pre_subsidy_rent"] = cps["rent"]
446446
cps["housing_assistance"] = np.zeros_like(
447-
cps["spm_unit_capped_housing_subsidy_reported"]
447+
cps["spm_unit_capped_housing_subsidy_data"]
448448
)
449449
cps["real_estate_taxes"] = np.zeros(len(cps["age"]), dtype=float)
450450
cps["real_estate_taxes"][mask] = imputed_values["real_estate_taxes"]
@@ -633,6 +633,9 @@ def add_takeup(self):
633633
data["age"],
634634
)
635635

636+
for source_anchor in ("snap_reported", "ssi_reported"):
637+
data.pop(source_anchor, None)
638+
636639
self.save_dataset(data)
637640

638641

@@ -1260,9 +1263,8 @@ def add_personal_income_variables(cps: h5py.File, person: DataFrame, year: int):
12601263
# The code for strike benefits is 12.
12611264
cps["strike_benefits"] = (person.OI_OFF == 12) * person.OI_VAL
12621265
cps["child_support_received"] = person.CSP_VAL
1263-
# Assume all public assistance / welfare dollars (PAW_VAL) are TANF.
1264-
# They could also include General Assistance.
1265-
cps["tanf_reported"] = person.PAW_VAL
1266+
# CPS SSI receipt anchors SSI take-up and disability alignment inside
1267+
# add_takeup; it is dropped before the dataset is saved.
12661268
cps["ssi_reported"] = person.SSI_VAL
12671269
# Allocate CPS RETCB_VAL (a single bundled retirement contribution
12681270
# total) into account-type-specific variables using a proportional
@@ -1397,15 +1399,8 @@ def add_spm_variables(self, cps: h5py.File, spm_unit: DataFrame) -> None:
13971399
SPM_RENAMES = dict(
13981400
spm_unit_total_income_reported="SPM_TOTVAL",
13991401
snap_reported="SPM_SNAPSUB",
1400-
spm_unit_capped_housing_subsidy_reported="SPM_CAPHOUSESUB",
1401-
free_school_meals_reported="SPM_SCHLUNCH",
1402-
spm_unit_energy_subsidy_reported="SPM_ENGVAL",
1403-
spm_unit_wic_reported="SPM_WICVAL",
1404-
spm_unit_broadband_subsidy_reported="SPM_BBSUBVAL",
1405-
spm_unit_payroll_tax_reported="SPM_FICA",
1406-
spm_unit_federal_tax_reported="SPM_FEDTAX",
1407-
# State tax includes refundable credits.
1408-
spm_unit_state_tax_reported="SPM_STTAX",
1402+
spm_unit_capped_housing_subsidy_data="SPM_CAPHOUSESUB",
1403+
spm_unit_energy_subsidy_data="SPM_ENGVAL",
14091404
spm_unit_capped_work_childcare_expenses="SPM_CAPWKCCXPNS",
14101405
spm_unit_net_income_reported="SPM_RESOURCES",
14111406
spm_unit_pre_subsidy_childcare_expenses="SPM_CHILDCAREXPNS",
@@ -1425,8 +1420,6 @@ def add_spm_variables(self, cps: h5py.File, spm_unit: DataFrame) -> None:
14251420
spm_unit.SPM_TENMORTSTATUS.map(tenure_map).fillna("RENTER").astype("S")
14261421
)
14271422

1428-
cps["reduced_price_school_meals_reported"] = cps["free_school_meals_reported"] * 0
1429-
14301423

14311424
@pipeline_node(
14321425
PipelineNode(

policyengine_us_data/datasets/cps/extended_cps.py

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -161,8 +161,6 @@ def _supports_structural_mortgage_inputs() -> bool:
161161
"social_security_survivors",
162162
# Transfer income
163163
"unemployment_compensation",
164-
"tanf_reported",
165-
"ssi_reported",
166164
"child_support_received",
167165
"veterans_benefits",
168166
"workers_compensation",
@@ -171,15 +169,8 @@ def _supports_structural_mortgage_inputs() -> bool:
171169
"receives_wic",
172170
# SPM variables
173171
"spm_unit_total_income_reported",
174-
"snap_reported",
175-
"spm_unit_capped_housing_subsidy_reported",
176-
"free_school_meals_reported",
177-
"spm_unit_energy_subsidy_reported",
178-
"spm_unit_wic_reported",
179-
"spm_unit_broadband_subsidy_reported",
180-
"spm_unit_payroll_tax_reported",
181-
"spm_unit_federal_tax_reported",
182-
"spm_unit_state_tax_reported",
172+
"spm_unit_capped_housing_subsidy_data",
173+
"spm_unit_energy_subsidy_data",
183174
"spm_unit_net_income_reported",
184175
"spm_unit_pre_subsidy_childcare_expenses",
185176
# Medical expenses

policyengine_us_data/db/etl_national_targets.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -291,15 +291,15 @@ def extract_national_targets(year: int = DEFAULT_YEAR):
291291
"year": 2024,
292292
},
293293
{
294-
"constraint_variable": "spm_unit_energy_subsidy_reported",
294+
"constraint_variable": "spm_unit_energy_subsidy_data",
295295
"target_variable": "household_count",
296296
"household_count": 5_939_605,
297297
"source": "https://liheappm.acf.gov/sites/default/files/private/congress/profiles/2023/FY2023AllStates%28National%29Profile-508Compliant.pdf",
298298
"notes": "LIHEAP total households served by state programs",
299299
"year": 2023,
300300
},
301301
{
302-
"constraint_variable": "spm_unit_energy_subsidy_reported",
302+
"constraint_variable": "spm_unit_energy_subsidy_data",
303303
"target_variable": "household_count",
304304
"household_count": 5_876_646,
305305
"source": "https://liheappm.acf.gov/sites/default/files/private/congress/profiles/2024/FY2024_AllStates%28National%29_Profile.pdf",
@@ -718,7 +718,7 @@ def load_national_targets(
718718
stratum_notes = "National ACA Premium Tax Credit Recipients"
719719
constraint_operation = ">"
720720
constraint_value = "0"
721-
elif constraint_var == "spm_unit_energy_subsidy_reported":
721+
elif constraint_var == "spm_unit_energy_subsidy_data":
722722
stratum_notes = "National LIHEAP Recipient Households"
723723
constraint_operation = ">"
724724
constraint_value = "0"

policyengine_us_data/utils/loss.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1815,10 +1815,9 @@ def _add_snap_metric_columns(
18151815
"""
18161816
snap_targets = pd.read_csv(CALIBRATION_FOLDER / "snap_state.csv")
18171817

1818-
snap_cost = sim.calculate("snap_reported", map_to="household").values
1819-
snap_hhs = (sim.calculate("snap_reported", map_to="household").values > 0).astype(
1820-
int
1821-
)
1818+
snap = sim.calculate("snap", map_to="household").values
1819+
snap_cost = snap
1820+
snap_hhs = (snap > 0).astype(int)
18221821

18231822
state = sim.calculate("state_code", map_to="person").values
18241823
state = sim.map_result(state, "person", "household", how="value_from_first_person")

policyengine_us_data/utils/national_target_parity.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -482,9 +482,9 @@ def classify_national_target(
482482
target_name,
483483
index.match(
484484
variable="household_count",
485-
domain_variable="spm_unit_energy_subsidy_reported",
485+
domain_variable="spm_unit_energy_subsidy_data",
486486
period=period,
487-
constraints=[_constraint("spm_unit_energy_subsidy_reported", ">", 0)],
487+
constraints=[_constraint("spm_unit_energy_subsidy_data", ">", 0)],
488488
),
489489
reason="structured_liheap_target",
490490
)

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ classifiers = [
2222
"Programming Language :: Python :: 3.14",
2323
]
2424
dependencies = [
25-
"policyengine-us>=1.691.1",
25+
"policyengine-us>=1.691.3",
2626
# policyengine-core 3.26.1 is the current 3.26.x runtime and includes the fix for
2727
# PolicyEngine/policyengine-core#482 (user-set ETERNITY inputs lost
2828
# after _invalidate_all_caches) and is required by policyengine-us 1.682.1+.

tests/integration/support/tiny_stage_3.py

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,6 @@
3535
"cps_race",
3636
"detailed_occupation_recode",
3737
"treasury_tipped_occupation_code",
38-
"tanf_reported",
39-
"ssi_reported",
4038
"is_puf_clone",
4139
)
4240
)
@@ -50,8 +48,7 @@
5048
"tax_unit_is_joint",
5149
"spm_unit_total_income_reported",
5250
"spm_unit_net_income_reported",
53-
"spm_unit_capped_housing_subsidy_reported",
54-
"snap_reported",
51+
"spm_unit_capped_housing_subsidy_data",
5552
"household_is_puf_clone",
5653
)
5754
)
@@ -224,8 +221,6 @@ def _extended_person_arrays(
224221
person_count,
225222
dtype=np.int16,
226223
),
227-
"tanf_reported": np.zeros(person_count, dtype=np.float32),
228-
"ssi_reported": np.zeros(person_count, dtype=np.float32),
229224
"is_puf_clone": np.concatenate(
230225
[
231226
np.zeros(cps_person_count, dtype=np.bool_),
@@ -260,12 +255,11 @@ def _extended_group_arrays(
260255
"spm_unit_net_income_reported": np.round(total_income * 0.85, 2).astype(
261256
np.float32
262257
),
263-
"spm_unit_capped_housing_subsidy_reported": np.where(
258+
"spm_unit_capped_housing_subsidy_data": np.where(
264259
arrays["tenure_type"] == b"RENTED",
265260
1_200,
266261
0,
267262
).astype(np.float32),
268-
"snap_reported": np.where(total_income < 50_000, 1_000, 0).astype(np.float32),
269263
"household_is_puf_clone": np.concatenate(
270264
[
271265
np.zeros(cps_household_count, dtype=np.bool_),

tests/integration/test_cps_generation.py

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ def fit(self, X_train, predictors, imputed_variables):
211211
cps = {
212212
"age": np.array([40, 12, 70], dtype=np.int32),
213213
"is_household_head": np.array([True, False, True], dtype=bool),
214-
"spm_unit_capped_housing_subsidy_reported": np.zeros(3, dtype=np.float32),
214+
"spm_unit_capped_housing_subsidy_data": np.zeros(3, dtype=np.float32),
215215
}
216216
person = pd.DataFrame({"P_SEQ": [1, 2, 1]})
217217
household = pd.DataFrame({"H_TENURE": [2, 1]})
@@ -225,3 +225,46 @@ def fit(self, X_train, predictors, imputed_variables):
225225
np.array([0, 0, 4000], dtype=np.int32),
226226
)
227227
assert not dataset.file_path.exists()
228+
229+
230+
def test_add_spm_variables_keeps_formulaic_outputs_out_of_dataset():
231+
from policyengine_us_data.datasets.cps.cps import add_spm_variables
232+
233+
cps = {}
234+
spm_unit = pd.DataFrame(
235+
{
236+
"SPM_TOTVAL": [50_000],
237+
"SPM_RESOURCES": [45_000],
238+
"SPM_SNAPSUB": [1_200],
239+
"SPM_CAPHOUSESUB": [3_000],
240+
"SPM_ENGVAL": [500],
241+
"SPM_SCHLUNCH": [800],
242+
"SPM_WICVAL": [200],
243+
"SPM_BBSUBVAL": [360],
244+
"SPM_FICA": [3_825],
245+
"SPM_FEDTAX": [2_000],
246+
"SPM_STTAX": [1_000],
247+
"SPM_CAPWKCCXPNS": [4_000],
248+
"SPM_CHILDCAREXPNS": [4_500],
249+
"SPM_TENMORTSTATUS": [3],
250+
}
251+
)
252+
253+
add_spm_variables(None, cps, spm_unit)
254+
255+
assert cps["spm_unit_total_income_reported"].tolist() == [50_000]
256+
assert cps["spm_unit_net_income_reported"].tolist() == [45_000]
257+
assert cps["snap_reported"].tolist() == [1_200]
258+
assert cps["spm_unit_capped_housing_subsidy_data"].tolist() == [3_000]
259+
assert cps["spm_unit_energy_subsidy_data"].tolist() == [500]
260+
assert cps["spm_unit_tenure_type"].tolist() == [b"RENTER"]
261+
for variable in (
262+
"free_school_meals_reported",
263+
"reduced_price_school_meals_reported",
264+
"spm_unit_wic_reported",
265+
"spm_unit_broadband_subsidy_reported",
266+
"spm_unit_payroll_tax_reported",
267+
"spm_unit_federal_tax_reported",
268+
"spm_unit_state_tax_reported",
269+
):
270+
assert variable not in cps

tests/unit/datasets/test_cps_file_handles.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -479,7 +479,7 @@ class FakeACS_2022:
479479
dataset = FakeDataset()
480480
cps = {
481481
"age": np.array([40], dtype=np.int32),
482-
"spm_unit_capped_housing_subsidy_reported": np.array([0.0]),
482+
"spm_unit_capped_housing_subsidy_data": np.array([0.0]),
483483
# add_id_variables populates this upstream of add_rent in the real
484484
# pipeline; see the policyengine-core#482 workaround override below.
485485
"is_household_head": np.array([True]),

0 commit comments

Comments
 (0)