Households
pe.us.calculate_household and pe.uk.calculate_household compute every variable in the country model for a single household. Same keyword arguments, different entity structures.
US
result = pe.us.calculate_household(
people=[
{"age": 35, "employment_income": 40_000},
{"age": 33},
{"age": 8},
{"age": 5},
],
tax_unit={"filing_status": "JOINT"},
household={"state_code": "TX"},
year=2026,
)Entities
| Argument | Purpose |
|---|---|
people |
List of person dicts. Keys are any person-level variable on the model. |
tax_unit |
Tax-unit inputs (e.g. filing_status). |
spm_unit |
SPM-unit inputs. |
household |
Household inputs. state_code is essentially always needed. |
family |
Family-level inputs. |
marital_unit |
Marital-unit inputs. |
All adults default to one shared tax unit and household. For separate tax units (e.g. two adult roommates), construct the Simulation directly and set the entity-membership arrays.
UK
result = pe.uk.calculate_household(
people=[
{"age": 35, "employment_income": 50_000},
{"age": 33, "employment_income": 30_000},
{"age": 4},
],
benunit={},
household={},
year=2026,
)| Argument | Purpose |
|---|---|
people |
Person-level inputs. |
benunit |
Benefit unit (closest analog to US tax unit — single adult or couple plus their dependent children). |
household |
Household-level inputs. |
Reforms
Pass a reform dict of parameter-path to value:
pe.us.calculate_household(
...,
reform={"gov.irs.credits.ctc.amount.adult_dependent": 1_000},
)Scale parameters use bracket indexing:
reform = {"gov.irs.credits.ctc.amount.base[0].amount": 3_000}Time-varying reforms use a nested dict of YYYY-MM-DD → value:
reform = {
"gov.irs.credits.ctc.amount.adult_dependent": {
"2026-01-01": 1_000,
"2028-01-01": 2_000,
},
}Structural reforms (new variables, formula swaps) require the Simulation path — see Reforms.
Year
pe.us.calculate_household(..., year=2026)The year determines which parameter values apply. For multi-year analysis, call the function once per year rather than building a custom reform.
Extra variables
The result exposes every variable in the model by default. To surface variables that aren’t in the default catalog explicitly:
result = pe.us.calculate_household(
...,
extra_variables=["medicaid_income_level", "spm_unit_spm_threshold"],
)Accessing the result
result.person[0].income_tax # first person
result.person[2].age # third person
result.tax_unit.income_tax # single tax unit
result.household.household_net_income # single householdThe result is a Pydantic model — .model_dump() gives you a dict, individual sections are regular attribute lookups.
Errors
Unknown variables raise with the closest match:
ValueError: Unknown variable 'income_ax'. Did you mean 'income_tax'?
Unknown parameters in reforms raise similarly. Misplaced inputs (a person-level variable under tax_unit=...) raise with entity hints. The catalog is enumerated at construction time — typos fail fast.
When not to use this
Loops over many households are much slower than a single Simulation call. For population analysis, see Microsimulation — the reform dict carries over identically.