fullseye

その数字のうち、いくつが測り方のものか(ゲージ R&R と測定の不確かさ)

できること

工程のばらつきを見る管理図も工程能力も、測定のばらつきを含んだままの数字を見ています。この層はそれを分けます —— 総変動のうち何割が部品どうしの差で、何割が「測るという行為」の差なのか。そして 1 回の測定について、成分ごとの不確かさを合成して報告可能な形にします。

どれも閉形式の規格モデルで、照合できる厳密な恒等式を持ちます。使った式でそのまま答え合わせをする op は 1 つも入れていません。

What it does

Separate how much of a number comes from the parts and how much from the act of measuring, then combine the components of a single measurement into a reportable uncertainty. Every operator is a closed-form standards model with an exact identity to check it against. The analysis-of-variance decomposition closes algebraically (SS_total = SS_part + SS_operator + SS_interaction + SS_error, relative difference 1e-16); repeatability equals the mean of the per-cell np.var(ddof=1) that numpy computes independently; the published worked example (10 parts x 3 operators x 3 trials) is reproduced to 1.5e-06 on EV/AV/GRR/PV with contribution percentages 3.4/4.4/7.8/92.2 exactly. Whether the interaction is kept or pooled into error moves EV by 7.3 %, so the model actually used is reported (interaction_pooled, interaction_p), and a negative variance component — which happens in 31 of 40 synthetic runs when the true component is zero — is clamped to zero but declared rather than hidden. On the uncertainty side: the divisors that turn a distribution shape into a standard uncertainty are exact (a/sqrt(3), a/sqrt(6), a/sqrt(2)); ignoring correlation errs in both directions on the same data (u_c of resistance 0.0702 -> 0.1945, a 2.8x overestimate, while reactance goes the other way); the effective degrees of freedom are truncated immediately before the t lookup as the standard requires (16.64 -> 16 gives k = 2.1199, matching the published 2.12); and the propagation law’s breakdown at a stationary point is returned as structure (guf_valid, invalid_reasons) rather than as a silent u_c = 0. A sum of four rectangular distributions has an exact coverage interval via Irwin-Hall, sqrt(3)(2 x 0.6^(1/4) - 4) = -3.879407, against which the propagation law is structurally 0.040521 too wide.

向くところ / 向かないところ

最初の 1 本

import numpy as np
import fullseye as fs

# その数字のうち、いくつが測り方のものか
t = {"part":     np.repeat([f"P{i}" for i in range(6)], 9),
     "operator": np.tile(np.repeat(["A", "B", "C"], 3), 6),
     "value":    np.random.default_rng(0).normal(10.0, 1.0, 54)}
g = fs.ledger.msa_gauge_rr(t)
print("%%GRR %.1f %% / 区別できる階級数 %.1f / 交互作用を畳んだか %s"
      % (g["pct_grr"][0], g["ndc"][0], bool(g["interaction_pooled"][0])))

# 不確かさ: 分布の形 -> 合成 -> 拡張
u = fs.ledger.gum_standard_uncertainty(
    {"halfwidth": [0.5, 0.2], "distribution": ["rectangular", "triangular"]})
e = fs.ledger.gum_expanded({"u": u["u"], "sensitivity": [1.0, 1.0],
                            "dof": [np.inf, 8.0]}, estimate=10.0)
print("u_c %.4f / k %.3f(nu_eff %.1f を %.0f へ切り捨て)/ U %.4f"
      % (e["u_combined"][0], e["coverage_factor"][0],
         e["dof_effective"][0], e["dof_used"][0], e["expanded"][0]))

# 伝播則が破綻する場所は、黙って 0 を返さず申告する
b = fs.ledger.gum_propagate({"u": [0.005, 0.005], "sensitivity": [0.0, 0.0]})
print("u_c %.1f / 有効か %s / 理由 %s"
      % (b["u_combined"][0], bool(b["guf_valid"][0]), list(b["invalid_reasons"])))

裏づけ