euromod_linking.methods.lma_labour_alignment.hierarchy¶
Two-level hierarchical alignment: activity (level 1), then unemployment within the active population (level 2); employment is the residual.
Economic rationale for the hierarchy¶
Labour-market outcomes are modelled as a two-stage decision, mirroring standard labour-supply theory: first the participation margin (in or out of the labour force), then the employment margin (employed vs unemployed, conditional on participating). Aligning in that order guarantees the macro accounting identities hold exactly at every cell:
labour force = employment target + unemployment target (level 1)
unemployment = its own target within the labour force (level 2)
employment = labour force - unemployment (residual, never adjusted
directly — adjusting it independently could break the
identity and double-count transitions)
A one-shot alignment of employment and unemployment separately could hit both targets while implying an impossible participation path (e.g. someone entering employment straight from inactivity being counted as an unemployment exit). The hierarchy makes every implied transition economically interpretable: inactive -> active (participation entry), active non-unemployed -> unemployed (job loss / unsuccessful entry), unemployed -> employed (residual job finding).
Who transitions is decided by ranked propensities (see scoring.py): people whose observable characteristics make the destination state most likely move first — the micro pattern a gradual macro adjustment would plausibly follow — rather than by random draw, which would attribute transitions to unrepresentative individuals and distort the distributional results.
Operates on the FULL dataset (households intact): candidate selection is restricted to the eligible (working-age) mask, but boundary splits copy whole households and rescale every member’s weight, because taxes and benefits are assessed on complete household contexts (see weights.py).
Attributes¶
Functions¶
|
Per-cell achieved vs target with tolerance grades. |
|
Move people between inactive and active to close each cell's active_gap. |
|
Within the (new) active population, close each cell's unemp_gap; |
|
Internal consistency of the post-alignment states; raises MethodError. |
Module Contents¶
- euromod_linking.methods.lma_labour_alignment.hierarchy.accuracy(df: pandas.DataFrame, targets: pandas.DataFrame, eligible: pandas.Series) list[dict][source]¶
Per-cell achieved vs target with tolerance grades.
Carries the baseline each target was built from. Without it a grade is uninterpretable: “exact” only ever means the alignment hit the number it was handed, and a target that silently equals the baseline grades exactly the same as one that moved a hundred thousand people.
- euromod_linking.methods.lma_labour_alignment.hierarchy.align_level1_activity(df: pandas.DataFrame, targets: pandas.DataFrame, eligible: pandas.Series) tuple[pandas.DataFrame, list[dict]][source]¶
Move people between inactive and active to close each cell’s active_gap.
A positive gap means the macro model projects labour-force growth in the cell: entrants are recruited from the inactive (domestic tasks, other — never students/retirees/disabled, who sit in the shielded ‘other’ state), highest predicted activity propensity first — the most labour-market- attached inactive individuals are the plausible marginal entrants. A negative gap withdraws active individuals with the lowest propensity — the weakest attachment leaves first (last-in-first-out intuition).
- euromod_linking.methods.lma_labour_alignment.hierarchy.align_level2_employment(df: pandas.DataFrame, targets: pandas.DataFrame, eligible: pandas.Series) tuple[pandas.DataFrame, list[dict]][source]¶
Within the (new) active population, close each cell’s unemp_gap; employment is the residual state.
Rising unemployment recruits from active non-unemployed ranked by unemployment propensity (highest first: observably most at risk of job loss); falling unemployment releases the unemployed with the lowest propensity first (observably most employable — the plausible first hires in an upswing). Employment is then defined as active-and-not-unemployed, so the participation decided at level 1 and the unemployment decided here pin down employment by identity — it is never adjusted directly.
- euromod_linking.methods.lma_labour_alignment.hierarchy.validate_states(df: pandas.DataFrame) None[source]¶
Internal consistency of the post-alignment states; raises MethodError.
- euromod_linking.methods.lma_labour_alignment.hierarchy.FLAG_COLS = ('transition_to_active', 'transition_to_inactive', 'transition_to_unemp', 'transition_from_unemp')¶
- euromod_linking.methods.lma_labour_alignment.hierarchy.GRADE_LADDER = (('exact', 0.01), ('excellent', 1.0), ('good', 2.0), ('acceptable', 5.0), ('poor', 10.0))¶