Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Step discontinuities

The breaks pass finds level changes in an ordered series. This chapter covers the cross-sectional counterpart: a level jump of one column across a threshold in another column, or across a diagonal boundary in two columns, in a table with no meaningful row order. The detector id is discontinuities; it runs at the standard and deep budgets and reports category changes, type step_discontinuity, form step.

Two candidate families are scanned for each numeric target column:

  • axis steps: a step indicator 1{x > c} for every other numeric column x, at 20 interior quantile cutpoints of x;

  • diagonal steps: a step indicator across a line cos(theta) * zx + sin(theta) * zy > c in each pair of columns (standardized), over 16 directions. Directions within one step of an axis are skipped; the axis scan covers them. When there are more than 20 numeric columns, pairs are restricted to the 10 axes whose axis scan scored best for that target.

Each candidate is fitted by ordinary least squares against a smooth background — [1, u, u^2] for an axis step (with u the standardized axis), [1, zx, zy] for a diagonal step — so the step coefficient measures the jump net of the smooth relationship. A grid-selected threshold is then refined on a finer grid inside the winning interval, because a threshold placed one grid cell away from the true boundary dilutes the jump estimate (the smooth background absorbs part of it).

Selection honesty: split halves

Rows are split deterministically into a fit half and an evaluation half. The fit half selects the candidate (largest |t_fit|) and ranks candidates across units; the evaluation half, which selection never reads, estimates the jump, its standard error, and the held-out gain (the fit-half step model’s evaluation-half mean squared error against the fit-half smooth-only model). Because selection and estimation use different rows, the winner’s evaluation-half z keeps its null calibration no matter how many candidates were searched: under no jump anywhere, |z| >= 2 fires on about 4.6% of unit winners. Reporting applies stricter bars, because the screen runs once per numeric target: |z| >= 4 and a held-out gain of at least 0.5% of the target’s evaluation-half variance.

Typing: a jump is scale-invariant

A steep smooth transition (a logistic crossing, a kink) also produces a large step coefficient against a quadratic background. The screen therefore types each flagged candidate with a local test on the evaluation half: the level gap between the nearest points on each side of the boundary at two scales, the nearest 15 and the nearest 60 points per side. A true jump shows the same gap at both scales (ratio near 1); a smooth transition’s gap grows with scale (ratio around 2 or more), because the wider window spans more of the slope. A candidate is reported as a jump only when the small-scale gap is significant (type_gap_t > 3) and the ratio stays below 1.5 (type_ratio). The evidence also carries type_z: the step’s t-statistic when the background is augmented with quadratic and cubic terms along the projection. The resolution limit is stated plainly: a smooth transition narrower than the small scale’s span is indistinguishable from a jump, and is typed as one.

The demonstration below plants three structures in one frame: an axis step, a diagonal step that no single column expresses, and a steep logistic transition that must not be reported.

s1 steps by 0.453839 across a diagonal boundary in s0 and y_diag (direction 112 degrees, standardized threshold 0.198008): evaluation-half jump 0.453839 (se 0.031079, z 14.602823), held-out gain 0.010642; the local gap is scale-invariant (ratio 0.93), typing it as a jump rather than a steep smooth transition
y_diag steps by 1.620865 across a diagonal boundary in s0 and s1 (direction 112 degrees, standardized threshold 0.420663): evaluation-half jump 1.620865 (se 0.089635, z 18.082974), held-out gain 0.189325; the local gap is scale-invariant (ratio 1.23), typing it as a jump rather than a steep smooth transition
s0 steps by -0.554768 across a diagonal boundary in s1 and y_diag (direction 45 degrees, standardized threshold 0.195177): evaluation-half jump -0.554768 (se 0.04552, z -12.187234), held-out gain 0.015755; the local gap is scale-invariant (ratio 0.90), typing it as a jump rather than a steep smooth transition
y_axis steps by 1.773857 where x crosses 0.588449: evaluation-half jump 1.773857 (se 0.061643, z 28.77615), held-out gain 0.175928; the local gap is scale-invariant (ratio 0.85), typing it as a jump rather than a steep smooth transition
s0 steps by -0.323716 across a diagonal boundary in y_axis and y_diag (direction 79 degrees, standardized threshold 0.233278): evaluation-half jump -0.323716 (se 0.040681, z -7.957443), held-out gain 0.007863; the local gap is scale-invariant (ratio 0.69), typing it as a jump rather than a steep smooth transition
5 step findings

The axis step is recovered with its threshold in the axis column’s original units; the diagonal step names both columns and the boundary direction in degrees, with the threshold in standardized units. The logistic column produces no finding: its best candidate flags on the evaluation half, but the two-scale gap grows with scale, so it is typed as a smooth transition and counted in the coverage string instead of reported.

The screen also reports mirror readings: s1 steps across a boundary drawn in (s0, y_diag), and s0 across boundaries involving y_diag. These are the same planted jump read from the other side — a step finding is a conditional level difference, and a column that records which side of a boundary each row sits on (here y_diag, which was built from the boundary) shows the boundary again when it serves as an axis for another target. Read a step finding as “the target’s level differs across this boundary”, not as evidence about which column causes the jump.

What the pass does not report

  • A jump whose target relationship is only visible against a residual. The screen scans raw columns. Screening the residuals of a fitted smooth model — the recommended second pass in the originating implementation — is not part of this detector.

  • Steps in a categorical direction. Axes are numeric columns; a level shift between the levels of a categorical column is the conditional-rules and concentration passes’ territory.

  • More than one jump per (target, axis set). Each unit reports its single best boundary. A target with two genuine steps along the same axis produces one finding, for the stronger jump.

  • Flagged candidates below the reporting bars. Candidates with 2 <= |z| < 4, or a held-out gain under 0.5% of the target’s variance, are counted in coverage but not reported.