ノンパラメトリック検定 完全ガイド — Mann-Whitney U・Wilcoxon・Kruskal-Wallis

新しい薬を飲んだグループと飲まなかったグループで、回復までの日数に差があるか調べたい——こういう「2つのグループの差」を検定する定番はt検定です。ところがt検定は「データが正規分布に従う」ことを暗黙に仮定しています。回復日数のように右に裾を引いた分布だったり、たった1人の異常に長引いた患者(外れ値)が混じっていたり、そもそも「効果あり=5段階評価の4以上」のような順序尺度のデータだったりすると、t検定の前提は崩れてしまいます。

こんなとき頼りになるのがノンパラメトリック検定です。データの値そのものではなく、順位(小さい順に並べたときの番号)だけを使って群を比べます。順位に置き換えてしまえば、分布の形がどうであろうと、外れ値がどれほど極端であろうと、検定の枠組みは変わりません。「分布の形を仮定しない(=パラメータに依存しない)」からノンパラメトリックと呼ばれます。

ノンパラメトリック検定は実務のあらゆる場面で活躍します。たとえば、サンプル数が一桁しかない小規模な臨床試験や材料試験(正規性の確認すらできない)、アンケートの満足度(1〜5の順序尺度)の比較、センサの故障で稀に巨大な値が混じる計測データの群間比較。いずれも「正規分布を信じきれない」状況で、安心して差を検出できる道具です。

本記事の内容

  • 「順位で比べる」という発想と、なぜそれが頑健なのか
  • Mann-Whitney U検定(独立2群、t検定の代替)の統計量の導出
  • Wilcoxon符号順位検定(対応あり)の仕組み
  • Kruskal-Wallis検定(3群以上、一元配置ANOVAの代替)への拡張
  • U統計量の正規近似と連続性補正、効果量(順位双列相関)
  • パラメトリックとノンパラの検定力比較と使い分け
  • scipy.stats を使ったPython実装と結果の読み取り

前提知識

この記事を読む前に、以下の記事を読んでおくと理解が深まります。

順位で比べるとはどういうことか

まずは直感から入りましょう。2つのグループAとBがあり、それぞれ何個かの測定値を持っているとします。これらが「同じ集団から来た」のか「Bの方が大きい集団から来た」のかを判定したい。

パラメトリックな発想(t検定)では、「各群の平均を計算して、その差が標準誤差に比べて大きいか」を見ます。平均は全データの値を足し算するので、1つでも巨大な外れ値が混じると平均がぐいっと引っ張られます。

ノンパラメトリックの発想はまったく違います。全データを混ぜて小さい順に一列に並べ、各データに「順位」という背番号を振るのです。そして「群Aの背番号は小さい方に固まっているか、大きい方に固まっているか」を見ます。値そのものは捨てて、大小関係(順序)だけを残すわけです。

全データを混ぜて順位化し、群ごとに順位和を求める概念図

この図では、群Aが $\{12, 18, 9\}$、群Bが $\{25, 15, 31\}$ という6個のデータを混ぜて昇順に並べ、$9, 12, 15, 18, 25, 31$ に対して順位 $1, 2, 3, 4, 5, 6$ を振っています。群Aは順位 $\{1, 2, 4\}$ を占めるので順位和は $R_A = 7$、群Bは順位 $\{3, 5, 6\}$ で順位和は $R_B = 14$ になります。Bの方が大きい順位を多く占めている——これがそのまま「Bの方が大きい集団かもしれない」という証拠になります。図の核心は、実数値そのものではなく順位で群を比べるという点です。

なぜこれが頑健なのでしょうか。仮に群Bの $31$ が $3100$ だったとしても、順位はやはり「6位(最大)」のままです。値が10倍100倍に化けても順位は1つも動きません。外れ値の「値の大きさ」は順位化で吸収され、「順位」という情報だけが残る。これがノンパラメトリック検定が外れ値に強い理由です。

順位という共通言語を手にしたところで、次はなぜパラメトリック検定の前提が崩れる場面があるのか、その限界を具体的に確認していきます。

パラメトリック検定の限界

t検定やANOVAは強力ですが、次の3つの前提に支えられています。

  1. 正規性: 各群のデータが(近似的に)正規分布に従う。
  2. 等分散性: 群間で分散が等しい(標準的なt検定の場合)。
  3. 間隔尺度以上: データが平均を計算できる数値(温度や長さなど)である。

これらが満たされるなら、t検定・ANOVAは最も検出力が高い検定です(正規分布のもとで最適)。問題は、現実のデータがこの前提から外れる場合です。

正規性が怪しいとき。 反応時間、所得、故障までの時間など、片側に裾を引く分布は山ほどあります。標本が大きければ中心極限定理で平均は正規に近づきますが、標本が小さいとそうもいきません。

外れ値が混じるとき。 平均と分散はどちらも外れ値に弱い統計量です。たった1つの異常値が平均を動かし、分散を膨らませ、t統計量の分母(標準誤差)を大きくして、本来あるはずの差を「有意でない」と見誤らせます。

順序尺度のとき。 アンケートの「とても不満=1 〜 とても満足=5」のような順序尺度では、「満足4と満足5の差」と「不満1と普通3の差」が同じ”2″の重みを持つわけではありません。こういうデータで平均を計算するのは、そもそも意味があやしいのです。順位だけを使うノンパラ検定なら、この問題を自然に回避できます。

外れ値が検定結論に与える影響を、後ほど数値実験(頑健性の節)で実際に目撃します。ここではまず、最も基本となるMann-Whitney U検定の中身を組み立てていきましょう。

Mann-Whitney U検定

何を検定するのか

Mann-Whitney U検定(Wilcoxon順位和検定とも呼ばれ、両者は等価)は、独立した2群が同じ分布から来たかどうかを順位で検定します。t検定のノンパラ版という位置づけです。

帰無仮説は「2群の分布は同じ(位置のずれがない)」、対立仮説は「一方の群の値がもう一方より系統的に大きい(または異なる)」です。より厳密には、群Aから1つ、群Bから1つ無作為に取り出したとき、$P(X_A < X_B)$ が $1/2$ から離れているかを検定します。

U統計量の定義と導出

群Aの大きさを $n_1$、群Bを $n_2$ とします。前節のとおり全 $N = n_1 + n_2$ 個のデータを混ぜて順位を振り、群Aの順位和を $R_1$ とします。U統計量は次で定義されます。

$$ \begin{equation} U_1 = R_1 – \frac{n_1(n_1 + 1)}{2} \end{equation} $$

この式の意味を導出しましょう。$U_1$ は「群Aの各データが、群Bの何個のデータを上回っているか」の総数として定義されます。つまり

$$ U_1 = \sum_{i=1}^{n_1}\sum_{j=1}^{n_2} \mathbf{1}(x_i > y_j) $$

ここで $\mathbf{1}(\cdot)$ は条件が真なら1、偽なら0を返す指示関数、$x_i$ は群A、$y_j$ は群Bのデータです。

このペア比較のカウントが、なぜ順位和の式 $(1)$ になるのでしょうか。群Aのあるデータ $x_i$ の全体順位を $r_i$ とすると、$r_i$ は「$x_i$ 以下のデータの個数」です。その内訳は「$x_i$ 以下の群Aのデータ」と「$x_i$ 以下の群Bのデータ」に分かれます。$x_i$ より小さい群Aのデータの個数を $a_i$ 個とすると、

$$ r_i = (\text{$x_i$ 以下の群Aの個数}) + (\text{$x_i$ 以下の群Bの個数}) = (a_i + 1) + (\text{$x_i$ が上回る群Bの個数}) $$

両辺を群A全体で足し合わせます。群A内での順位の和 $\sum_i (a_i + 1)$ は、$n_1$ 個を小さい順に並べたときの $1 + 2 + \dots + n_1 = n_1(n_1+1)/2$ にちょうど等しくなります。残りが $U_1$ の定義そのものです。よって

$$ R_1 = \sum_{i=1}^{n_1} r_i = \frac{n_1(n_1+1)}{2} + U_1 $$

これを $U_1$ について解けば、定義式 $(1)$ が得られます。順位和さえ計算すれば、ペアごとの比較を明示的に数えなくてもUが求まる——これが式 $(1)$ の御利益です。

同様に群Bについて $U_2 = R_2 – n_2(n_2+1)/2$ を定義できます。2つのUには美しい関係があります。

$$ \begin{equation} U_1 + U_2 = n_1 n_2 \end{equation} $$

これは直感的にも明らかです。「AがBを上回るペア数」と「BがAを上回るペア数」を足せば、全ペア数 $n_1 n_2$ になる(同点がなければ)からです。検定では小さい方 $U = \min(U_1, U_2)$ を統計量に使うのが慣例です。

Uが取る値の意味

$U_1$ がどんな値を取るかを考えると、検定のロジックが見えてきます。群Aの値がすべて群Bより小さければ、Aは1つもBを上回れないので $U_1 = 0$。逆に群Aがすべて大きければ $U_1 = n_1 n_2$。両群がよく混ざっていれば $U_1 \approx n_1 n_2 / 2$ になります。

つまり$U$ が $0$ や $n_1 n_2$ に近いほど2群はくっきり分離しており、$n_1 n_2 / 2$ に近いほど混ざり合っている。この対応関係を図で確かめましょう。

2群の分布の重なりとU統計量の対応(重なりが小さいほどUは端に寄る)

3つのパネルは、2群の平均差を $0, 1.5, 4$ と広げたものです。重なりが大きいときは $U/(n_1 n_2) = P(A < B) \approx 0.5$(混ざっている)、重なりが小さくなるほど $P(A < B)$ が $1$ に近づき、$U$ は端へ寄っていきます。$U/(n_1 n_2)$ がそのまま「群Bが群Aを上回る確率」の推定値になっている点に注目してください。後で効果量を定義するとき、この量が主役になります。

先ほどの小さな例($A = \{12, 18, 9\}$, $B = \{25, 15, 31\}$)で計算すると、$R_1 = 7$ なので $U_1 = 7 – 3\cdot4/2 = 1$、そして $U_2 = 9 – 1 = 8$ です。確かに $U_1 + U_2 = 9 = n_1 n_2$ を満たしています。$U = \min(1, 8) = 1$ は $0$ に近く、「Bの方が大きい」傾向を示しています。

これで2群が独立な場合の統計量が手に入りました。では、「同じ対象を処置前と処置後で測った」ような対応のあるデータではどうすればよいでしょうか。次のWilcoxon符号順位検定がその答えです。

Wilcoxon符号順位検定

対応データの差を順位化する

同じ患者の「投薬前」と「投薬後」の血圧、同じ被験者の「学習前」と「学習後」のテスト得点——このようにペアになったデータでは、ペア内の差 $d_i = (\text{後}) – (\text{前})$ に注目します。差がゼロを中心に対称に散らばっていれば「効果なし」、片側に偏っていれば「効果あり」です。これは対応のあるt検定のノンパラ版にあたります。

Wilcoxon符号順位検定の手順は次のとおりです。

  1. 各ペアの差 $d_i$ を計算する(差がゼロのペアは除外)。
  2. 差の絶対値 $|d_i|$ を小さい順に並べ、順位を振る。
  3. 各順位に、元の差の符号(正なら $+$、負なら $-$)を付ける。
  4. 正の順位の和 $W_+$ と負の順位の和 $W_-$ を計算する。
  5. 検定統計量 $W = \min(W_+, W_-)$ を使う。

「絶対値で順位を付け、符号を後付けする」のがポイントです。差の大きさの情報を順位として残しつつ、向き(増えたか減ったか)を符号で保持するわけです。

対応データの差を絶対値で順位付けし、符号付き順位和を求める

左の図は各ペアの差を棒で表し、その絶対値の順位を添えたものです。右は正の順位和 $W_+$ と負の順位和 $W_-$ の比較で、もし「効果なし(差が対称)」なら両者は帰無の期待値 $n(n+1)/4$ の周りで釣り合うはずです。$W_+$ と $W_-$ が大きく食い違うほど、「差が一方向に偏っている=効果がある」証拠が強くなります。

なぜ符号順位が効くのか

帰無仮説(差は0を中心に対称)のもとでは、各 $d_i$ の符号は $+$ と $-$ が等確率で、しかも符号と絶対値の大きさは独立です。すると、各順位 $k$ に正の符号が付くかどうかは確率 $1/2$ の独立なコイン投げになります。$W_+$ は「表が出た順位の和」なので、その期待値は

$$ E[W_+] = \sum_{k=1}^{n} k \cdot \frac{1}{2} = \frac{1}{2}\cdot\frac{n(n+1)}{2} = \frac{n(n+1)}{4} $$

となります。各順位が独立に $1/2$ で寄与するので、分散も計算でき、

$$ \mathrm{Var}[W_+] = \sum_{k=1}^{n} k^2 \cdot \frac{1}{4} = \frac{n(n+1)(2n+1)}{24} $$

が得られます($\sum k^2 = n(n+1)(2n+1)/6$ を使いました)。標本が大きければ $W_+$ も正規近似でき、観測された $W_+$ がこの期待値からどれだけ離れているかでp値を計算します。Mann-Whitney と同じく「順位の和の期待値からのズレ」を見る枠組みです。

2群・対応ありときたら、自然に湧く疑問は「3群以上ではどうするのか」です。次のKruskal-Wallis検定がこれに答えます。

Kruskal-Wallis検定

ANOVAの順位版

3つ以上のグループを一度に比較したいとき、パラメトリックでは一元配置分散分析(ANOVA)を使います。そのノンパラ版がKruskal-Wallis検定です。帰無仮説は「すべての群が同じ分布から来た」、対立仮説は「少なくとも1つの群が他と異なる」です。

考え方はMann-Whitneyの自然な拡張です。全 $N$ 個のデータを混ぜて順位を振り、各群の平均順位を計算します。帰無仮説が正しければ、どの群の平均順位も全体の期待平均順位 $(N+1)/2$ の近くに集まるはずです。ある群だけ平均順位が極端に高い(または低い)なら、その群は他と違う——これが検定のロジックです。

3群の順位の散らばりと平均順位、Kruskal-Wallis統計量

左の図は3群のデータを全体順位の軸上に並べ、◆で各群の平均順位を示しています。右は平均順位を帰無の期待値 $(N+1)/2$ と比べたもので、群が右にずれるほど平均順位が高くなっています。3群の平均順位のズレを1つの数 $H$ にまとめたのがKruskal-Wallis統計量です。

統計量Hの定義

各群 $g$($g = 1, \dots, k$)の大きさを $n_g$、順位和を $R_g$ とすると、Kruskal-Wallis統計量は

$$ \begin{equation} H = \frac{12}{N(N+1)}\sum_{g=1}^{k} \frac{R_g^2}{n_g} – 3(N+1) \end{equation} $$

で定義されます。一見ごつい式ですが、中身は「各群の平均順位が全体平均からどれだけ離れているか」の重み付き二乗和です。実際、群 $g$ の平均順位 $\bar{R}_g = R_g / n_g$ と全体平均順位 $\bar{R} = (N+1)/2$ を使うと、式 $(3)$ は次の形に書き直せます。

$$ H = \frac{12}{N(N+1)}\sum_{g=1}^{k} n_g\left(\bar{R}_g – \frac{N+1}{2}\right)^2 $$

この形なら意味は明快です。$\sum_g n_g (\bar{R}_g – \bar{R})^2$ は「群間の平均順位のばらつき(群サイズで重み付け)」そのもの。先頭の係数 $12/[N(N+1)]$ は、順位データの分散で割って規格化する役割を持ちます(順位 $1, \dots, N$ の分散が $N(N+1)/12$ になることに由来)。

帰無仮説が正しければ、$H$ は近似的に自由度 $k-1$ のカイ二乗分布に従います。$H$ が大きいほど群間のズレが大きく、カイ二乗分布の上側でp値が小さくなって「群間に差あり」と判定されます。$k = 2$ のときはMann-Whitney U検定と本質的に一致します。

3つの代表的なノンパラ検定(Mann-Whitney・Wilcoxon・Kruskal-Wallis)が出そろいました。いずれも「順位和(または平均順位)が帰無の期待値からどれだけずれるか」を見る、という共通の骨格を持っています。次は、標本が大きいときに使う正規近似と、差の大きさを測る効果量を整理します。

正規近似と効果量

U統計量の正規近似

標本が小さいうちは、前に見たように全順列を数え上げてUの厳密分布を作れます。しかし $n_1, n_2$ が大きくなると順列の数が爆発し、計算できません。幸い、$U$ の帰無分布は標本が増えると正規分布に近づくことが知られています。帰無仮説のもとでの平均と分散は

$$ \begin{equation} \mu_U = \frac{n_1 n_2}{2}, \qquad \sigma_U^2 = \frac{n_1 n_2 (N + 1)}{12} \end{equation} $$

です。平均 $\mu_U = n_1 n_2/2$ は式 $(2)$ から当然($U_1 + U_2 = n_1 n_2$ で、帰無では両者が対称なので半々)。分散の $N+1$ や $12$ は、順位 $1, \dots, N$ の分散構造から導かれます。

これを使えば、観測した $U$ を標準化して

$$ z = \frac{U – \mu_U}{\sigma_U} $$

を計算し、標準正規分布でp値を求められます。厳密分布が正規分布にどれだけよく一致するかを見てみましょう。

Mann-Whitney U の帰無分布(厳密な列挙)と正規近似の一致

この図は $n_1 = 5$, $n_2 = 6$ のとき全 $462$ 通りの順列でUを列挙したヒストグラム(青)と、平均 $\mu_U = 15$、標準偏差 $\sigma_U \approx 5.48$ の正規分布(赤)を重ねたものです。標本がこれほど小さくても、ヒストグラムは見事に釣鐘型で、正規曲線にぴたりと重なっています。標本がさらに大きくなれば一致はもっと良くなり、正規近似が安心して使えることが視覚的に確認できます。

連続性補正

ただし1つ注意があります。$U$ は整数値しか取らない離散統計量なのに、正規分布は連続分布です。この食い違いを埋めるのが連続性補正で、$|U – \mu_U|$ から $0.5$ を引いてから標準化します。

$$ z = \frac{|U – \mu_U| – 0.5}{\sigma_U} $$

直感的には、離散の棒グラフ1本の「幅」の半分だけ内側に補正することで、連続曲線での面積(p値)を正しく見積もるわけです。

U統計量の正規近似と連続性補正の効果

この図では、離散のUに対し、観測値 $U=15$ をそのまま使う場合と $+0.5$ 補正した場合で標準化スコア $z$ が変わる様子を示しています。標本が小さいほど補正の効き目が大きく、p値が過小評価されるのを防いでくれます。scipy.stats.mannwhitneyu も既定で連続性補正を適用します。

効果量:順位双列相関

p値は「差があるか(有意か)」を教えてくれますが、「差がどれくらい大きいか」は教えてくれません。標本が大きければごく小さな差でも有意になるので、効果量を併記するのが現代的な作法です。Mann-Whitney に対応する効果量が順位双列相関(rank-biserial correlation)です。

$$ \begin{equation} r = 1 – \frac{2U}{n_1 n_2} = 2\,\hat{P}(X_A > X_B) – 1 \end{equation} $$

$U/(n_1 n_2)$ が「群Bが群Aを上回る確率」の推定値だったことを思い出すと、$r$ は $-1$(完全に一方が小さい)から $+1$(完全に一方が大きい)までの範囲を取り、$0$ が「差なし」に対応する分かりやすい指標になります。

効果量(順位双列相関)の定義と解釈の目安

左の図は $U/(n_1 n_2)$ と $r$ の直線関係を、右は効果量の大きさの目安(小 $0.1$、中 $0.3$、大 $0.5$ あたり、Cohenの基準)を示しています。たとえば $r = 0.58$ なら「群Aの方が群Bより大きい確率が約 $79\%$」を意味する、大きな効果です。p値と効果量はセットで報告すると、結果の意味がぐっと明確になります。

道具と指標がそろったので、いよいよ実務上いちばん悩む問いに向き合います——「結局、パラメトリックとノンパラ、どちらを使えばいいのか」。

パラメトリックとノンパラの選択

検定力の比較

「ノンパラは前提が緩い分、安全だがパワーが落ちる」とよく言われます。本当でしょうか。検定力(真に差があるときに正しく差を検出する確率)をシミュレーションで比べてみます。

パラメトリックとノンパラの検定力曲線(正規分布と重い裾の分布)

左(正規分布のデータ)では、t検定とMann-Whitney の検定力曲線はほぼ重なっています。t検定がわずかに上回りますが、その差はごくわずか——正規データでも、ノンパラを使うことの”損”はおおむね数%程度(漸近相対効率は $3/\pi \approx 0.955$ と知られています)。一方、右(自由度2のt分布=裾が重く外れ値が出やすい分布)では立場が逆転し、Mann-Whitney がt検定を明確に上回っています。重い裾の分布では、外れ値に引っ張られるt検定の方がむしろ非力なのです。

ここから実践的な指針が読み取れます。

  • 正規性が確かで標本も十分 → パラメトリック(t検定・ANOVA)。検出力で最良。
  • 正規性が怪しい / 外れ値が多い / 重い裾 → ノンパラ。検出力で互角以上、しかも安全。
  • 順序尺度のデータ → ノンパラ一択(平均に意味がない)。
  • 標本が極端に小さい → 正規性の検証すらできないので、ノンパラが無難。

頑健性(外れ値に対する強さ)

検定力の話を、外れ値の観点からもう一押し確認します。2群のデータに大きさを変えた外れ値を1個だけ混入させ、t検定とMann-Whitney のp値がどう動くかを見ます。

外れ値の大きさに対するt検定とMann-Whitneyのp値の頑健性

左の図のように、群Aにぽつんと巨大な外れ値を1つ加えます。右の図がその結末です。外れ値が小さいうちはt検定もMann-Whitney も「有意(p < 0.05)」と判定します。ところが外れ値を大きくしていくと、t検定のp値は急上昇して $0.05$ をあっさり超え、「差なし」と結論を翻してしまいます。外れ値が群Aの平均を引き上げ、分散を膨らませ、本来あったB > Aの差を覆い隠すからです。対してMann-Whitney のp値は外れ値の大きさにほとんど反応せず、$0.008$ 前後で安定しています。順位化のおかげで「最大値1個」という順位情報以上の悪影響を受けないのです。これがノンパラの頑健性の正体です。

最後に、ここまで見てきた検定をどう選ぶか、一枚のフローチャートにまとめておきます。

群数・対応・尺度から検定を選ぶフローチャート

群の数(2群か3群以上か)、対応の有無(独立か対応ありか)で、Mann-Whitney・Wilcoxon・Kruskal-Wallis のどれを使うかが決まります。Kruskal-Wallis で有意が出たら、どの群同士が違うのかをDunn検定などの多重比較で事後解析します。

理屈はここまでです。実際に scipy.stats を使って、これらの検定を動かしてみましょう。

Pythonでの実装

Mann-Whitney U検定

scipy.stats.mannwhitneyu を使います。まずは対照群と処置群を比べ、U・p値・効果量を計算します。

import numpy as np
from scipy import stats

# 対照群と処置群(処置群の方が平均が高い)
rng = np.random.default_rng(42)
ctrl = rng.normal(100, 15, 18)   # n1 = 18
treat = rng.normal(112, 15, 16)  # n2 = 16

# Mann-Whitney U検定(両側)
U, p = stats.mannwhitneyu(ctrl, treat, alternative="two-sided")
n1, n2 = len(ctrl), len(treat)

# 効果量(順位双列相関) r = 1 - 2U/(n1 n2)
r_rb = 1 - 2 * U / (n1 * n2)

print(f"U統計量: {U:.1f}")
print(f"p値: {p:.5f}")
print(f"順位双列相関 r: {r_rb:.4f}")
print(f"U2 = n1*n2 - U = {n1 * n2 - U:.0f}(U1+U2 = n1 n2 の確認)")

実行すると、U統計量: 60.0p値: 0.00396順位双列相関 r: 0.5833U2 = 228 が得られます。scipy が返すUは対照群側の $U_1$ で、$U_2 = n_1 n_2 – U_1 = 288 – 60 = 228$ も式 $(2)$ どおりに成り立っています。p値が $0.004$ と小さく「2群に有意な差あり」、さらに効果量 $r = 0.58$ は「大きい効果」の水準で、処置群の方が系統的に高いことが読み取れます。p値(有意性)と効果量(差の大きさ)の両方が報告できている点が重要です。

正規近似による手計算との照合

scipy の結果が、式 $(4)$ の正規近似と整合するか確かめます。

import numpy as np
from scipy import stats

rng = np.random.default_rng(42)
ctrl = rng.normal(100, 15, 18)
treat = rng.normal(112, 15, 16)
n1, n2 = len(ctrl), len(treat)
N = n1 + n2

U, _ = stats.mannwhitneyu(ctrl, treat, alternative="two-sided")

# 正規近似の平均と標準偏差(式(4))
mu_U = n1 * n2 / 2
sigma_U = np.sqrt(n1 * n2 * (N + 1) / 12)
z = (U - mu_U) / sigma_U                       # 連続性補正なし

print(f"mu_U = {mu_U:.1f},  sigma_U = {sigma_U:.3f}")
print(f"標準化スコア z = {z:.4f}")
print(f"正規近似の両側p値 = {2 * stats.norm.cdf(z):.5f}")

このコードは mu_U = 144.0sigma_U = 28.983z = -2.8983、正規近似の両側p値 0.00375 を出力します。scipy の正確p値 $0.00396$ とほぼ一致しており、式 $(4)$ の平均・分散が正しいこと、そして標本がこの程度でも正規近似が十分実用的なことが確認できます。

Wilcoxon符号順位検定

対応のあるデータには scipy.stats.wilcoxon を使います。投薬前後の測定値で試します。

import numpy as np
from scipy import stats

# 同一被験者の投薬前 / 投薬後(対応データ)
before = np.array([72, 80, 65, 90, 78, 85, 70, 88, 75, 82])
after  = np.array([68, 83, 60, 85, 79, 79, 75, 80, 72, 84])

diff = after - before
print("各ペアの差:", diff)

W, p = stats.wilcoxon(before, after)
print(f"検定統計量 W: {W}")
print(f"p値: {p:.5f}")

出力は 各ペアの差: [-4 3 -5 -5 1 -6 5 -8 -3 2]W: 13.5p値: 0.16797 です。差は正負が入り混じっており、$W = 13.5$ は帰無の期待値 $n(n+1)/4 = 10 \cdot 11 / 4 = 27.5$ からそれほど離れていません。p値が $0.17$ と大きく、「投薬前後で有意な差があるとは言えない」という結論になります。対応のあるデータでも、差を符号付き順位に変換するだけで検定できる手軽さが見て取れます。

Kruskal-Wallis検定

3群以上には scipy.stats.kruskal です。平均の異なる3群を比較します。

import numpy as np
from scipy import stats

rng = np.random.default_rng(42)
# わざと最初の2標本を消費して上の例と乱数列を分離
_ = rng.normal(100, 15, 18)
_ = rng.normal(112, 15, 16)

g1 = rng.normal(50, 8, 12)   # 平均50
g2 = rng.normal(58, 8, 12)   # 平均58
g3 = rng.normal(66, 8, 12)   # 平均66

H, p = stats.kruskal(g1, g2, g3)
print(f"H統計量: {H:.4f}")
print(f"p値: {p:.6f}")

# 群ごとの平均順位を確認
allv = np.concatenate([g1, g2, g3])
allr = stats.rankdata(allv)
sizes = [len(g1), len(g2), len(g3)]
splits = np.cumsum([0] + sizes)
for i, name in enumerate(["g1", "g2", "g3"]):
    mr = allr[splits[i]:splits[i + 1]].mean()
    print(f"{name} の平均順位: {mr:.2f}")
N = len(allv)
print(f"帰無の期待平均順位 (N+1)/2 = {(N + 1) / 2:.2f}")

このコードは H統計量: 18.8754p値: 0.000080 を出力し、3群の平均順位はそれぞれ全体期待値 $(N+1)/2 = 18.5$ から段階的にずれます(g1 < g2 < g3 の順で平均順位が上がる)。$H \approx 18.9$ は自由度 $k-1 = 2$ のカイ二乗分布の上側で非常に小さなp値を与え、「少なくとも1つの群が他と異なる」と強く結論できます。式 $(3)$ の統計量が、平均順位のズレを正しく1つの値に集約していることが分かります。

すべての検定を一望する

最後に、同じ2群データに対してt検定とMann-Whitney を並べ、結論と効果量をまとめて出力します。

import numpy as np
from scipy import stats

rng = np.random.default_rng(42)
ctrl = rng.normal(100, 15, 18)
treat = rng.normal(112, 15, 16)
n1, n2 = len(ctrl), len(treat)

t_stat, t_p = stats.ttest_ind(ctrl, treat)
U, mw_p = stats.mannwhitneyu(ctrl, treat, alternative="two-sided")
r_rb = 1 - 2 * U / (n1 * n2)

print("=== 同じ2群を2通りの検定で比較 ===")
print(f"t検定           : t = {t_stat:.3f}, p = {t_p:.5f}")
print(f"Mann-Whitney    : U = {U:.0f}, p = {mw_p:.5f}")
print(f"効果量(順位双列) : r = {r_rb:.3f}")

実行すると、t検定とMann-Whitney はどちらも $p < 0.01$ で「有意差あり」という同じ結論を返します。正規分布から生成したデータなので両者がよく一致するのは検定力の比較で見たとおりです。もしこのデータに巨大な外れ値が混じれば、t検定だけが結論を覆す——という頑健性の差が、ここに効いてくるわけです。普段からこのように両方を併記して照合する習慣をつけると、結論の信頼性を自分で点検できます。

まとめ

本記事では、正規性を仮定しないノンパラメトリック検定を、順位の考え方から代表的3検定の導出・実装まで通して解説しました。

  • 順位で比べる: 全データを混ぜて順位化し、群ごとの順位和(平均順位)を比べる。値ではなく順序だけを使うので、分布の形や外れ値に頑健。
  • Mann-Whitney U検定: 独立2群の検定。$U_1 = R_1 – n_1(n_1+1)/2$ はペア比較数 $\sum \mathbf{1}(x_i > y_j)$ に等しく、$U_1 + U_2 = n_1 n_2$ が成り立つ。t検定の代替。
  • Wilcoxon符号順位検定: 対応データの差を絶対値で順位付けし符号を付ける。$W = \min(W_+, W_-)$、帰無の期待値は $n(n+1)/4$。対応t検定の代替。
  • Kruskal-Wallis検定: 3群以上の平均順位のズレを統計量 $H = \frac{12}{N(N+1)}\sum_g R_g^2/n_g – 3(N+1)$ にまとめ、自由度 $k-1$ のカイ二乗分布で評価。一元配置ANOVAの代替。
  • 正規近似と効果量: $\mu_U = n_1 n_2/2$, $\sigma_U^2 = n_1 n_2 (N+1)/12$ で正規近似でき、連続性補正で精度を上げる。効果量は順位双列相関 $r = 1 – 2U/(n_1 n_2)$。
  • 使い分け: 正規性が確かならパラメトリック、外れ値・重い裾・順序尺度・小標本ならノンパラ。正規データでもノンパラの検出力の損は数%程度、重い裾では逆にノンパラが優位。

ノンパラメトリック検定は「データを信じきれないとき」の保険であり、同時に「順位という頑健な情報」を最大限に使う賢い方法でもあります。p値だけでなく効果量を併記する習慣と合わせて、現場の意思決定を支える強力な道具になります。

次のステップとして、以下の記事も参考にしてください。