2026年10月8日に、NISTの1標本平均検定、2工程の平均比較、SciPyのttest_indを再読しました。標本設計、仮説方向、等分散・Welch、欠測、置換法、信頼区間を分け、平均差やp値を因果効果・実務価値の保証とは扱いません。
平均購入額が上がった、作業時間が短くなった。観測した差を報告するとき、t検定は「平均差がゼロ」という仮説とデータの整合性を調べる方法になります。ただし、同じ人の前後を比べるのか、別々の人を比べるのかで計算は変わります。小さなp値が出ても、利益が増えることや施策の因果効果まで自動的に分かるわけではありません。
この記事では、手で追える5件ずつの仮想データから、Welchのt検定、対応のあるt検定、平均差の信頼区間、標準化効果量、必要人数の計画までつなげます。数値はすべて教材であり、実顧客の成果ではありません。
30秒で要点
- 別々の人の平均なら独立2標本、同じ人の前後なら対応あり、ひとつの集団と固定の基準値なら1標本のt検定を検討します。
- 独立2群で等分散を置かない方法がWelch検定です。独立性の欠如や極端な歪みまで解決する方法ではありません。
- p値とともに、平均差の単位・方向・95%信頼区間を示します。標準化効果量は、どの標準偏差で割ったかも必要です。
- 標本数と停止条件は結果を見る前に決めます。非有意は同等性の証明ではなく、検出力80%も成功の保証ではありません。
最初に、何を1件として比較するか決める
t検定の中心は平均です。中央値、購入の有無、上位顧客だけの売上など、知りたい対象を変えると分析も変わります。たとえば平均購入額では、購入者だけか、未購入者を0円として含む全対象者かで別の問いになります。
表が収まらない場合は、横にスクロールできます
| 比較したいこと | 観測の関係 | 検討する方法 |
|---|---|---|
| A画面とB画面に割り付けた別々の利用者の平均作業時間 | 人どうしが独立した2群 | Welch、共通分散を仮定できる設計ならStudentの独立2標本t検定 |
| 同じ担当者の導入前後の平均作業時間 | 担当者IDで対応する2回の測定 | 対応のあるt検定 |
| ひとつの工程の平均重量が固定基準100gと異なるか | 独立した1標本と既知の定数 | 1標本t検定 |
基準値自体が別の標本から推定された平均なら、その不確実性も考えます。「前年の標本平均」を既知の定数として扱うと、比較の誤差を小さく見積もる場合があります。NISTの2標本t検定は、独立した2標本と一対一に対応する測定を区別しています。
同じ利用者の10回の訪問は、10人分の独立した観測とは限りません。店舗単位で施策を割り付けた場合も、店舗内の客をすべて独立とする検定は設計と合わない可能性があります。先に割付単位・集計単位・観測期間を決め、必要なら利用者単位の集計やクラスタを扱うモデルを選びます。
仮定は、検定ボタンを押す前後の両方で調べる
表が収まらない場合は、横にスクロールできます
| 確認項目 | 見るもの | 問題があったとき |
|---|---|---|
| 独立性・対応関係 | ID、割付方法、繰り返し、時系列 | 対応あり・反復測定・クラスタを扱う設計へ戻る |
| 分布と極端値 | 生データ、ヒストグラム、箱ひげ図、Q-Qプロット | 計測誤りを調べ、推定対象を保つ分析や感度分析を検討する |
| 分散 | 群ごとの標準偏差、人数、測定条件 | 共通分散を置けなければWelchを検討する |
| 欠測・除外 | 群別の欠測数と理由、除外規則 | 都合のよい値だけが残っていないか調べる |
小標本での通常のt推論には、独立群では各母集団、対応ありでは差の分布について正規分布の仮定が関わります。標本が大きければ平均の近似が役立つこともありますが、「30件を超えたから常に安全」という境界は置けません。歪み、裾の重さ、群の不均衡も確認します。
Shapiro–Wilk検定の非有意は正規性の証明ではありません。各5人では分布を見抜く情報も乏しいため、検定のp値だけで方法を自動分岐させず、測定の仕組みと図を併せて判断します。Levene検定で非有意だったことだけを根拠に等分散を確定することも避けます。外れ値は、大きいという理由だけで消しません。入力ミスなら訂正し、正しい高額購入なら平均売上にとって重要な観測かもしれません。欠測の一括削除も、残った人が対象集団を代表するかを別途確認する必要があります。
独立2群の例:平均差4.2点をどう読むか
二つのコーヒーを、別々の5人ずつが100点尺度で評価した仮想例です。同じ位置の数字に対応関係はありません。
表が収まらない場合は、横にスクロールできます
| 群 | 5人の評価点 | 平均 | 標本標準偏差 |
|---|---|---|---|
| A | 72、65、80、75、68 | 72.0 | 5.874 |
| B | 78、70、82、77、74 | 76.2 | 4.494 |
ここでは差を一貫して B - A と定義します。平均差は76.2 - 72.0 = 4.2点です。「平均差ゼロ」を帰無仮説、ゼロではないことを対立仮説とする両側Welch検定を使います。
Welchの標準誤差は、各群の標本分散をs²、人数をnとして、SE = √(sA²/nA + sB²/nB)。今回の分散は34.5と20.2なので、SEは約3.308点です。t = 4.2 / SE は約1.270、Welch–Satterthwaiteの自由度は約7.488になります。計算式はNIST、実装はSciPyのttest_indで確認できます。
Pythonで検定・差の区間・効果量をまとめて計算する
以下のコードはすべて仮想入力を含み、各ブロックを単独で実行できます。2026年10月4日にPython 3.12、NumPy 2.5.3、SciPy 1.16.2、Matplotlib 3.10.7、statsmodels 0.14.5で確認しました。最新版の組み合わせを保証するものではありません。図のコードは実行フォルダにPNGを保存します。
import numpy as np
from scipy import stats
A = np.array([72, 65, 80, 75, 68], dtype=float)
B = np.array([78, 70, 82, 77, 74], dtype=float)
result = stats.ttest_ind(B, A, equal_var=False, alternative="two-sided")
ci = result.confidence_interval(confidence_level=0.95)
diff = B.mean() - A.mean()
pooled_sd = np.sqrt(
((len(A) - 1) * A.var(ddof=1) + (len(B) - 1) * B.var(ddof=1))
/ (len(A) + len(B) - 2)
)
d_s = diff / pooled_sd
g_approx = d_s * (1 - 3 / (4 * (len(A) + len(B)) - 9))
print(f"B - A: {diff:.3f} points")
print(f"Welch t={result.statistic:.6f}, df={result.df:.6f}, p={result.pvalue:.6f}")
print(f"95% CI: [{ci.low:.3f}, {ci.high:.3f}] points")
print(f"pooled-SD d_s={d_s:.3f}, Hedges g (approx)={g_approx:.3f}")
出力は両側p値が約0.242、平均差の95%区間が-3.519〜11.919点です。5%水準では平均差ゼロを棄却できません。一方、区間にはかなり大きな正の差も含まれます。「差がない」と決めるのではなく、今回の少人数では方向と大きさを十分に絞れていないと読みます。
p値は、帰無仮説と検定の標本モデルの下で、観測した統計量と同等以上に極端な値が出る確率です。「帰無仮説が正しい確率」「今回の差が偶然である確率」ではありません。NISTのp値の説明
95%信頼区間の95%は、仮定の下で同じ手順を繰り返したときの被覆率です。今回の固定された母平均差に95%の確率を割り当てたものではありません。NISTの信頼区間
Cohenのdは、p値の代わりの合格点ではない
上のd_sは、平均差を人数で重み付けしたプール標準偏差で割った記述的な標準化差です。約0.803、Hedgesの小標本補正の近似を掛けたgは約0.725です。Welch検定を実行したことと、共通の標準偏差が妥当であることは別なので、分散が大きく違うなら、この標準化が問いに適切か検討します。
0.2・0.5・0.8という慣用的なdの目安を、そのまま採用基準にはしません。dの分母と小標本補正、対応ありのd_zとの違いはLakensの方法論論文で整理されています。実務の判断では、まず4.2点という元の単位、測定尺度の意味、区間、必要な改善幅を残します。
同じ人の前後なら、差を1人1件として扱う
次は別の仮想調査です。同じ5人を前後で測定し、ID順の値が偶然先ほどと同じだったとします。この場合、各人の差は6、5、2、2、6点。平均差は同じ4.2点でも、差の標準偏差は約2.049点です。
import numpy as np
from scipy import stats
before = np.array([72, 65, 80, 75, 68], dtype=float)
after = np.array([78, 70, 82, 77, 74], dtype=float)
differences = after - before # same people, matched by ID
result = stats.ttest_rel(after, before, alternative="two-sided")
ci = result.confidence_interval(confidence_level=0.95)
d_z = differences.mean() / differences.std(ddof=1)
one_sample = stats.ttest_1samp(differences, popmean=0)
assert np.isclose(result.statistic, one_sample.statistic)
print(f"paired t={result.statistic:.6f}, df={result.df:.0f}, p={result.pvalue:.6f}")
print(f"mean change={differences.mean():.3f}, 95% CI=[{ci.low:.3f}, {ci.high:.3f}]")
print(f"difference-SD d_z={d_z:.3f}")
対応ありではt≈4.583、自由度4、p≈0.0102、区間は1.655〜6.745点です。この違いは「有意にする方法を選べる」ことを意味しません。対応関係はデータを取った設計で決まります。配列を並べ替えて都合のよいペアを作ることもできません。SciPyのttest_rel
d_z≈2.049は差の標準偏差で割っており、独立群のd_sと同じ尺度として単純比較しません。また前後差が明確でも、練習、季節、別の施策が同時に変わっていれば、その変化を導入施策だけの効果とは言えません。
図では個人差・平均の区間・平均差の区間を分ける
ヒストグラムは分布、箱ひげ図は中央値や四分位、平均の区間は平均推定の不確実性を示します。人数5の未知分散で各群の平均区間を描くなら、ここでは自由度4のt分位点を使います。固定値1.96を掛ける区間とは違います。2群の平均区間が重なるかどうかだけで、平均差の検定を代用しないでください。
import numpy as np
import matplotlib.pyplot as plt
from scipy import stats
groups = [np.array([72, 65, 80, 75, 68]), np.array([78, 70, 82, 77, 74])]
fig, axes = plt.subplots(1, 3, figsize=(12, 3.6))
for values, label in zip(groups, ["A", "B"]):
axes[0].hist(values, bins=[60, 65, 70, 75, 80, 85], alpha=0.5, label=label)
axes[0].set(xlabel="Score", ylabel="People")
axes[0].legend()
axes[1].boxplot(groups, tick_labels=["A", "B"])
axes[1].set(ylabel="Score")
means = [x.mean() for x in groups]
half_width = [stats.t.ppf(0.975, len(x) - 1) * stats.sem(x) for x in groups]
axes[2].errorbar([0, 1], means, yerr=half_width, fmt="o", capsize=5)
axes[2].set(xticks=[0, 1], xticklabels=["A", "B"], ylabel="Mean score, 95% t CI")
fig.tight_layout()
fig.savefig("t-test-distribution-and-mean-ci.png", dpi=150)
plt.close(fig)
print("Saved t-test-distribution-and-mean-ci.png")
各5点のヒストグラムは区切り方で見え方が変わるので、本文図のような生データも残します。図だけで正規性を証明できるわけではありません。
売上A/Bでは、統計的な差と採用する価値を分ける
仮想の独立した対象者A群120人、B群118人について、固定期間の1人あたり売上を考えます。次の乱数は正規分布から作る計算教材です。実際の売上によくある0円、右に長い裾、返品、利用者の反復を再現するモデルではありません。
import numpy as np
from scipy import stats
rng = np.random.RandomState(0)
A = rng.normal(loc=1200, scale=300, size=120)
B = rng.normal(loc=1280, scale=310, size=118)
result = stats.ttest_ind(B, A, equal_var=False, alternative="two-sided")
ci = result.confidence_interval(confidence_level=0.95)
pooled_sd = np.sqrt(((len(A)-1)*A.var(ddof=1) + (len(B)-1)*B.var(ddof=1))
/ (len(A)+len(B)-2))
print(f"means A={A.mean():.2f}, B={B.mean():.2f} yen")
print(f"B-A={B.mean()-A.mean():.2f} yen, p={result.pvalue:.6f}")
print(f"95% CI=[{ci.low:.2f}, {ci.high:.2f}] yen, d_s={(B.mean()-A.mean())/pooled_sd:.3f}")
生成時に置いた母平均差80円と、実現した標本の平均差は別です。この乱数標本では平均差約25.58円、95%区間-52.22〜103.37円、p≈0.518となります。たとえば事前に「追加コストを考えると少なくとも50円の売上増が必要」と置いても、この結果だけでは50円を超える差を確かめられません。売上増と利益増も別です。
判断記録には、対象者と集計期間、群別人数・平均・標準偏差、差と区間、p値、除外理由、実装費用、採用条件を残します。NISTも統計的有意性と実用上の重要性を区別しています。購入率など0/1の比率を扱う場合は、成功数と分母を持つ統計的仮説検定の例を参照してください。
検出力と必要人数は、差を見る前に計画する
同じ有意水準でも、小さい差を安定して検出するには一般に多くの情報が必要です。計画では「最低限意味のある差」「想定する標準偏差」「配分」「有意水準」「検出力」を置きます。実施後に観測されたdだけから人数を逆算すると、小標本で誇張された差を将来も期待するおそれがあります。
次の計算は、等分散・独立・1対1配分の2標本t検定を想定する計画例です。TTestIndPowerの実装はプール分散を使うため、Welch検定の不等分散条件に対する厳密な必要人数ではありません。不等分散・不均等配分が重要なら、その条件を入れた専用計算やシミュレーションで計画を検討します。
from math import ceil
from statsmodels.stats.power import TTestIndPower
planner = TTestIndPower()
for d in [0.2, 0.3, 0.5, 0.8]:
raw_n = planner.solve_power(effect_size=d, alpha=0.05, power=0.80,
ratio=1, alternative="two-sided")
n = ceil(raw_n)
print(f"d={d:.1f}: {n} per group, {2*n} total")
表が収まらない場合は、横にスクロールできます
| 仮定した標準化差 | 各群人数(切り上げ) | 合計 |
|---|---|---|
| 0.2 | 394 | 788 |
| 0.3 | 176 | 352 |
| 0.5 | 64 | 128 |
| 0.8 | 26 | 52 |
検出力80%は、置いた対立仮説とモデルの下で反復したときに棄却できる確率です。個々の実験が80%の確率で「正しい結論」になるという意味ではありません。脱落を見込むなら、その割合の根拠と登録人数・解析人数の違いも記録します。solve_powerの引数
通常の固定標本のt検定を毎日確認し、p<0.05になった時だけ止めると、予定した誤検出率を保てません。途中判定が必要なら、逐次検定として停止規則と推論手順を先に設計します。継続監視と推論を扱う一次研究は、その区別と方法固有の仮定を示しています。
別の方法に移るときも、知りたい量を変えない
表が収まらない場合は、横にスクロールできます
| 困っていること | 候補と確認点 |
|---|---|
| 独立群で強い歪みがある | 変換やロバストな平均推定を検討。対数変換すれば元の算術平均差とは別の量になる |
| 順序尺度や分布の違いが問い | Mann–Whitney U。一般には平均差や中央値差そのものの検定ではない |
| 対応ありで差の分布を順位で扱う | Wilcoxon符号付き順位。差の対称性、0差や同順位の扱いを確認する |
| 平均差の区間を再標本化で推定したい | ブートストラップ。ただし人・ペア・店舗など元の独立単位を保つ。少数標本を増やす魔法ではない |
| 3群以上、複数要因を比較する | ANOVAや回帰モデル。複数の検定を行うなら比較の集合と調整を決める |
順位法の対象と制約はSciPyのMann–Whitney U、Wilcoxonに明記されています。片側検定も「Bを良く見せたいから」では選べません。反対方向の差をどう扱うかを含め、データを見る前に仮説と判断を定めます。
手元の比較を一度だけ点検する
最小の検証は、少数の行をIDと期間まで遡り、分析単位が正しいか確かめることから始められます。
- 主要指標、対象集団、差の方向、独立か対応ありかを1文で書く。
- 各群の人数・欠測・平均・標準偏差と生データ図を出し、重複や計測誤りを調べる。
- 事前に選んだ方法で、差の区間とp値を計算する。想定外の分析は探索として分ける。
- 区間を最低限必要な改善幅と比べ、採用・追加の独立した検証・見送りの根拠を残す。
練習として、同じ20人の研修前後なら何を1標本にするか、別店舗の20件ずつなら何が独立かを考えてください。前者は20人分の差、後者は店舗内相関と割付単位の確認が先です。また「p=0.20だから2円以内で同じ」とは言えません。同等性を主張したいなら、許容差を先に定めた同等性の設計が必要です。
比較が3群以上になる場合は分散分析の実務ガイド、人数と期間の見直しには少標本A/Bテストの注意点が続きになります。