「2つのグループに差があるか調べたいが、データが正規分布に従う保証がない」。統計分析の現場では、このような場面にしばしば遭遇する。t検定は強力な手法だが、正規分布の仮定が崩れると信頼性が低下する。そこで登場するのがノンパラメトリック検定である。
1945年、アメリカの化学者フランク・ウィルコクソン(Frank Wilcoxon, 1892–1965)は、わずか3ページの論文「Individual Comparisons by Ranking Methods」を発表した。ウィルコクソンはアメリカン・シアナミド社で実験データの分析に携わるなかで、t検定に代わるより簡便な手法を模索していた。彼が提案したのは、データの実際の数値ではなく順位を用いて検定を行うという画期的なアイデアである。この論文では2つの検定、すなわち順位和検定(2標本)と符号付き順位検定(1標本)が同時に提案された。
1947年にはヘンリー・マンとドナルド・ホイットニーが独立に同等の検定を理論的に発展させたため、この検定はマン・ホイットニーのU検定(Mann–Whitney U test)とも呼ばれる。本記事ではウィルコクソンの順位和検定に加え、同じデータに対して異なるアプローチをとる並べ替え検定(permutation test)についても解説する。
ノンパラメトリック法とは
Z検定やt検定、F検定などの検定では、母集団が正規分布に従うことを仮定している。このように母集団分布を仮定したうえで検定統計量を導出し仮説検定を行う方法をパラメトリック法(parametric method)という。
これに対して、ノンパラメトリック法(non-parametric method)は母集団分布の仮定を設けずに仮説検定を行う。ノンパラメトリック法の基本的な考え方は、データの観測値そのものではなく大きさの順位を用いて統計量を構成することである。母集団分布がわかっている場合でも、サンプルサイズが小さいときにはノンパラメトリック法が有効とされるケースが多い。
| 検定内容 | パラメトリック法 | ノンパラメトリック法 |
|---|---|---|
| 2群の差(対応なし) | 2標本t検定 | ウィルコクソンの順位和検定、並べ替え検定 |
| 2群の差(対応あり) | 対応ありt検定 | 符号付き順位検定、符号検定 |
| 3群以上の差 | 一元配置分散分析 | クラスカル・ウォリス検定 |
ウィルコクソンの順位和検定
基本的な考え方
ウィルコクソンの順位和検定(Wilcoxon rank sum test)は、2つの独立な群の分布に差があるかを検定する手法である。2群のデータを統合して小さい順に順位を割り当て、その順位和(rank sum)を検定統計量として用いる。
各群の分布の形が同じであるという仮定のもとでは、中央値の差の検定と捉えることもできる。帰無仮説は「2つの群の分布は同じ」であり、対立仮説に応じて片側検定または両側検定を行う。
計算手順
具体例で手順を示す。ある学校で2クラスの生徒に対し、補習授業の効果を検証する。補習を受けたA群(3人)と受けていないB群(3人)の試験成績(点)は次の通りであった。
| 生徒1 | 生徒2 | 生徒3 | |
|---|---|---|---|
| A群(補習あり) | 78 | 85 | 92 |
| B群(補習なし) | 60 | 65 | 72 |
帰無仮説を「2群の成績の分布は同じ」、対立仮説を「A群の成績の分布はB群より良い方にずれている」として片側検定を行う。
Step 1:統合して順位を付ける
A群とB群のデータをまとめて、値の小さい順に順位を与える。
| 値 | 60 | 65 | 72 | 78 | 85 | 92 |
|---|---|---|---|---|---|---|
| 群 | B | B | B | A | A | A |
| 順位 | 1 | 2 | 3 | 4 | 5 | 6 |
Step 2:順位和を求める
A群の順位和 W_A を計算する。
なお、B群の順位和は W_B = 1 + 2 + 3 = 6 であり、W_A + W_B = 15 + 6 = 21 = \dfrac{6 \times 7}{2} となる。これは1から N までの自然数の総和に等しく、常に成り立つ関係である。
Step 3:P値を求める
帰無仮説が正しいとすると、6人の順位はランダムに割り振られると考えられる。A群の3人に与えられる順位の組合せは {}_6C_3 = 20 通りあり、各組合せは等確率 \dfrac{1}{20} で生じる。
A群の方が「良い方にずれている」なら W_A は大きな値をとるはずである。そこで P(W_A \geq 15) を求める。W_A = 15 となるのは順位の組が (4, 5, 6) の1通りのみなので、
これが片側P値である。有意水準5%ではちょうど境界であり、棄却するかどうかは慣習による。有意水準10%であれば帰無仮説は棄却でき、補習の効果があると判断できる。
参考として、W_A のとりうる値とその場合の数を以下に示す。
| W_A | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 計 |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 場合の数 | 1 | 1 | 2 | 3 | 3 | 3 | 3 | 2 | 1 | 1 | 20 |
A群のサンプルサイズを m、B群のサンプルサイズを n、合計を N = m + n とすると、W_A のとりうる範囲は最小 \dfrac{m(m+1)}{2}(順位1〜mを占める場合)から最大 \dfrac{m(2N-m+1)}{2}(上位m個を占める場合)までである。また、W_A + W_B = \dfrac{N(N+1)}{2} が常に成り立つ。
サンプルサイズが異なる場合
2群の人数が異なる場合も同様に計算すればよい。たとえばA群3人、B群4人の場合、組合せの総数は {}_7C_3 = 35 通りとなる。
ある薬の効果を調べるため、新薬(A群、3人)と従来薬(B群、4人)を投与し、痛みの改善度(点)を測定した。
| A群(新薬) | 15 | 25 | 40 | |
| B群(従来薬) | 10 | 20 | 30 | 35 |
帰無仮説「2群の分布は同じ」に対し、「A群の方が改善度が高い」という片側対立仮説を検定する。統合して順位を付けると
| 値 | 10 | 15 | 20 | 25 | 30 | 35 | 40 |
|---|---|---|---|---|---|---|---|
| 群 | B | A | B | A | B | B | A |
| 順位 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
A群の順位和は W_A = 2 + 4 + 7 = 13 である。{}_7C_3 = 35 通りの組合せから W_A の分布を求めると
| W_A | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 場合の数 | 1 | 1 | 2 | 3 | 4 | 4 | 5 | 4 | 4 | 3 | 2 | 1 | 1 |
片側P値は
となり、有意水準5%でも10%でも帰無仮説は棄却できない。
タイ(同順位)の処理
データに同じ値(タイ)がある場合は、対応する順位の平均を割り当てる。たとえば3番目と4番目の値が等しい場合、両方に \dfrac{3 + 4}{2} = 3.5 を与える。
A群のデータが 18, 25, 30、B群が 25, 32, 40 であったとする。値25がA群とB群に1つずつある。統合して並べると
| 値 | 18 | 25 | 25 | 30 | 32 | 40 |
|---|---|---|---|---|---|---|
| 群 | A | A | B | A | B | B |
| 順位 | 1 | 2.5 | 2.5 | 4 | 5 | 6 |
値25は順位2と3に対応するので、平均の2.5を両方に割り当てる。A群の順位和は W_A = 1 + 2.5 + 4 = 7.5 となる。
正規近似
各群のサンプルサイズが大きくなると、すべての順位組合せを列挙してP値を計算することは現実的でなくなる。この場合、W_A の分布を正規分布で近似する。
A群のサンプルサイズを m、B群のサンプルサイズを n、合計 N = m + n とし、タイがない場合、帰無仮説のもとでの W_A の期待値と分散は
であり、m, n が十分大きいとき
は近似的に標準正規分布に従う。
A群12人、B群15人(合計27人)のデータに対して、ウィルコクソンの順位和検定を行ったところ、A群の順位和が w_A = 125 であった。「A群の分布がB群より低い方にずれている」という片側対立仮説を有意水準5%で検定せよ。
【解答】
帰無仮説のもとでの期待値と標準偏差を求める。
検定統計量は
標準正規分布の下側5%点は -1.645 である。Z = -2.10 < -1.645 なので帰無仮説を棄却し、A群の分布はB群より低い方にずれていると判断できる。
並べ替え検定
並べ替え検定(permutation test)は、ウィルコクソンの順位和検定と同様に2群の差を検定する手法だが、順位ではなくデータの実際の値(平均など)を検定統計量とする点が異なる。
先ほどの補習の例(A群:78, 85, 92、B群:60, 65, 72)で並べ替え検定を説明する。帰無仮説・対立仮説は順位和検定と同じである。
各群の平均は
帰無仮説が正しいとすると、6人のデータ (60, 65, 72, 78, 85, 92) からA群として3人が無作為に選ばれる。 {}_6C_3 = 20 通りの組合せそれぞれについて平均を計算し、A群の平均 \bar{X}_A が実測値の85以上となる確率を求める。
\bar{X}_A = 85 となるのは (78, 85, 92) の1通りのみであるから、
この場合、順位和検定のP値と一致する。しかし、データによっては両者のP値が異なることがある。
| ウィルコクソンの順位和検定 | 並べ替え検定 | |
|---|---|---|
| 検定統計量 | 順位和 W_A | 平均 \bar{X}_A などの実数値統計量 |
| 利点 | 外れ値に頑健(順位のため) | データの情報を直接利用 |
| P値 | データによって一致することも異なることもある | |
どちらの手法が優れているということはなく、データの特性や分析の目的に応じて使い分ける。外れ値が含まれる可能性がある場合は順位和検定が安定し、データの数値的な差を直接反映させたい場合は並べ替え検定が適している。
練習問題
| A(新肥料) | 82 | 78 | 91 | 85 |
| B(従来肥料) | 70 | 65 | 75 |
帰無仮説を「2群の収穫量の分布は同じ」、対立仮説を「A群の方が収穫量が多い」とする片側検定を、ウィルコクソンの順位和検定で行え。
統合して順位を付ける。
| 値 | 65 | 70 | 75 | 78 | 82 | 85 | 91 |
|---|---|---|---|---|---|---|---|
| 群 | B | B | B | A | A | A | A |
| 順位 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
A群の順位和:W_A = 4 + 5 + 6 + 7 = 22
組合せ総数:{}_7C_4 = 35
W_A \geq 22 となるのは順位の組が (4, 5, 6, 7) の1通りのみである。
結論:有意水準5%で帰無仮説を棄却でき、新肥料Aの方が収穫量が多いと判断できる。
m = 10, \; n = 12, \; N = 22 より
標準正規分布の下側5%点は -1.645 であり、Z = -1.65 < -1.645 なので帰無仮説を棄却する。
結論:有意水準5%で、A群の分布はB群より低い方にずれていると判断できる。
まとめ
| 項目 | 内容 |
|---|---|
| 目的 | 2つの独立な群の分布に差があるかを検定 |
| 前提 | 母集団分布の仮定不要(各群の分布の形は同じと仮定) |
| 検定統計量 | 順位和検定:順位和 W_A、並べ替え検定:平均 \bar{X}_A など |
| P値の計算 | 小標本:全組合せの列挙、大標本:正規近似 |
| 正規近似の期待値 | E[W_A] = \dfrac{m(N+1)}{2} |
| 正規近似の分散 | \text{Var}(W_A) = \dfrac{mn(N+1)}{12} |
| 別名 | マン・ホイットニーのU検定(Mann–Whitney U test) |
Python実装
SciPyにはウィルコクソンの順位和検定の関数が用意されている。
import numpy as np
from scipy import stats
from itertools import combinations
# === ウィルコクソンの順位和検定(小標本・正確検定) ===
A = np.array([78, 85, 92])
B = np.array([60, 65, 72])
# scipy.stats.mannwhitneyu で実行
stat, p_value = stats.mannwhitneyu(A, B, alternative='greater')
print("=== ウィルコクソンの順位和検定 ===")
print(f"A群: {A}")
print(f"B群: {B}")
print(f"U統計量: {stat}")
print(f"P値(片側): {p_value:.4f}")
print()
# 手動で順位和を計算
all_data = np.concatenate([A, B])
ranks = stats.rankdata(all_data)
W_A = ranks[:len(A)].sum()
W_B = ranks[len(A):].sum()
print(f"A群の順位和: W_A = {W_A}")
print(f"B群の順位和: W_B = {W_B}")
print()
# === 正規近似 ===
print("=== 正規近似の例 ===")
m, n = 12, 15
N = m + n
w_A = 125
E_W = m * (N + 1) / 2
Var_W = m * n * (N + 1) / 12
Z = (w_A - E_W) / np.sqrt(Var_W)
p_normal = stats.norm.cdf(Z)
print(f"m={m}, n={n}, w_A={w_A}")
print(f"E[W_A] = {E_W:.1f}")
print(f"Var(W_A) = {Var_W:.2f}")
print(f"Z = {Z:.4f}")
print(f"P値(片側)= {p_normal:.4f}")
print()
# === 並べ替え検定 ===
print("=== 並べ替え検定 ===")
A_perm = np.array([78, 85, 92])
B_perm = np.array([60, 65, 72])
all_perm = np.concatenate([A_perm, B_perm])
obs_mean = A_perm.mean()
count = 0
total = 0
for combo in combinations(range(len(all_perm)), len(A_perm)):
total += 1
if np.mean([all_perm[i] for i in combo]) >= obs_mean - 1e-10:
count += 1
print(f"A群の実測平均: {obs_mean:.2f}")
print(f"P値(片側): {count}/{total} = {count/total:.4f}")
print()
# === scipy.stats.permutation_test(大標本向け) ===
print("=== scipy permutation_test ===")
def stat_func(x, y, axis):
return np.mean(x, axis=axis) - np.mean(y, axis=axis)
res = stats.permutation_test(
(A_perm, B_perm),
stat_func,
alternative='greater',
n_resamples=9999
)
print(f"検定統計量(平均の差): {res.statistic:.2f}")
print(f"P値: {res.pvalue:.4f}")