Skip to content

Extract the per-group Xbar/S estimator for phased charts (#144, PR 1) - #149

Merged
cnicholas merged 1 commit into
fix/xbar-s-table-subgroup-nfrom
feat/phased-xbar-s-refactor
Oct 18, 2026
Merged

cnicholas merged 1 commit into
fix/xbar-s-table-subgroup-nfrom
feat/phased-xbar-s-refactor

Conversation

@cnicholas

Copy link
Copy Markdown
Owner

Part of #144 (PR 1 of 4). Stacked on #148: the base is fix/xbar-s-table-subgroup-n, so the diff shows only this change; it retargets to main when #148 merges.

Summary

  • What: the code the global and stratified Xbar/S builders had in duplicate now lives in five helpers (_aggregate_subgroups, _fit_xbar_group, _apply_xbar_limits, _apply_s_limits, _subgroup_label_column); the lane-divider label rule is its own function (_lane_labels); calculate_limits_vectorized takes a sigma-hat per row.
  • Why: phased Xbar/S (Phased (staged) limits for Xbar and S charts #144) is N per-stage charts on one axis, and each stage needs exactly the per-stratum estimator. Extracting it first means the feature PR adds a loop over phases, not new arithmetic, and the per-row sigma is the hook for a vectorised path if the app ever needs one.
  • Scope: refactor only. No chart, statistic, metadata or error message changes.

Contract / invariants

  • Defaults unchanged — validation/xbar_s_sweep.py (new) fingerprints 504 Xbar/S requests on T100 PM SDS 1 and 3 (chart x companion x seven by= shapes x value x n_mode: 420 charts and 84 refusals). Identical output on 7f32215 and this branch: 0 differing lines.
  • Residuals unaffected
  • Row/index alignment preserved — the fingerprints cover row order; the gate's drawn-limit comparisons pass
  • Output schema compatible — golden masters untouched and passing, not regenerated
  • Pinned error strings unchanged

Behaviour changes

None.

Methodology

  • No methodology change — implementation only

Tests

  • tests/test_xbar_s_helpers.py (14 tests): _lane_labels keeps the astype date rendering and the _ join; a per-row sigma matches the formula row by row, a scalar equals a constant Series exactly, and a Series sigma supplies the result index; _fit_xbar_group returns None without replication, charts n = 1 and drops n = 0, decides constant-n separately for Xbar and S, and under n_mode='average' overwrites N while n keeps the actual sizes; _apply_s_limits is B3/B4 per row around S-bar; _aggregate_subgroups with and without the cached cell mean and with an R2 limits column; the four subgroup-label rules
  • pytest tests/ — 2567 passed, 7 skipped
  • ruff check .
  • mypy processbehavior — 14 errors, all pre-existing and outside the touched code (X/mR and Histogram sites)
  • Golden masters: untouched, 22 pass
  • python validation/e2e_bishop_report.py — 1547 passed, 0 failed, 4 pending; docs/reference/validation.md unchanged

Notes

  • Committed with the ruff-format hook skipped: analysis.py and spc_constants.py have never been ruff-formatted, and the hook would have rewritten about twenty unrelated blocks. A formatting-only commit can follow separately if wanted.
  • Next: PR 2 adds phased=True for Xbar and S on top of these helpers.

…ed paths (#144)

The global and stratified Xbar/S builders carried the same aggregation, fit and
limit code twice. It now lives in five helpers (_aggregate_subgroups,
_fit_xbar_group, _apply_xbar_limits, _apply_s_limits, _subgroup_label_column),
the lane-divider label rule is its own function (_lane_labels), and
calculate_limits_vectorized accepts a sigma-hat per row. Phased Xbar/S (#144)
is N per-stage charts on one axis, each one exactly the per-stratum estimator;
with the estimator extracted the feature adds a loop, not arithmetic.

No behaviour change. validation/xbar_s_sweep.py (new) fingerprints 504 Xbar/S
requests on T100 PM SDS 1 and 3 and prints identical output before and after;
golden masters untouched; gate 1547 passed, 0 failed, 4 pending.
@cnicholas
cnicholas force-pushed the fix/xbar-s-table-subgroup-n branch from 7f32215 to 3e08ebb Compare October 18, 2026 22:21
@cnicholas
cnicholas force-pushed the feat/phased-xbar-s-refactor branch from 732512f to 57f499c Compare October 18, 2026 22:21
@cnicholas
cnicholas merged commit eb0acf5 into fix/xbar-s-table-subgroup-n Oct 18, 2026
17 checks passed
cnicholas added a commit that referenced this pull request Oct 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant