Wilcoxon検定は多重比較・ノンパラメトリック検定の1種です。
ノンパラメトリック検定は名前をよく混合してしまいますが、以下のようにまとめられます。
検定名 | 英語名 | パラメトリック? | 対応 | コメント |
---|---|---|---|---|
ウィルコクソンの符号順位検定 | Wilcoxon signed-rank test | ノンパラメトリック | 対応あり | |
ウィルコクソンの順位和検定 | Wilcoxon rank sum test | ノンパラメトリック | 対応なし | この2つは同じ |
マン・ホイットニーのU検定 | Mann-Whitney U test | ノンパラメトリック | 対応なし |
RのSleepデータを使用します。
10人の患者に対して、2種類の薬を使用し、対照薬使用時との睡眠時間の差分を算出したデータです。
#!/usr/bin/env Rscript
data(sleep)
sleep
extra group ID
1 0.7 1 1
2 -1.6 1 2
3 -0.2 1 3
4 -1.2 1 4
5 -0.1 1 5
6 3.4 1 6
7 3.7 1 7
8 0.8 1 8
9 0.0 1 9
10 2.0 1 10
11 1.9 2 1
12 0.8 2 2
13 1.1 2 3
14 0.1 2 4
15 -0.1 2 5
16 4.4 2 6
17 5.5 2 7
18 1.6 2 8
19 4.6 2 9
20 3.4 2 10
以下のコードによって可視化します。
import pandas as pd
import matplotlib.pylab as plt
group1 = [0.7, -1.6, -0.2, -1.2, -0.1, 3.4, 3.7, 0.8, 0.0, 2.0]
group2 = [1.9, 0.8, 1.1, 0.1, -0.1, 4.4, 5.5, 1.6, 4.6, 3.4]
df = pd.DataFrame({
"group1": group1,
"group2": group2
})
# 棒グラフ(対応がある場合はこの可視化)
df.plot(kind="bar")
plt.savefig("plt.bar.sleep.png")
# 箱ひげ図(対応がない場合はこの可視化)
df.plot(kind="box", widths=0.66)
plt.savefig("plt.box.sleep.png")
【棒グラフ】
【箱ひげ図】
パッと可視化すると、group2の方が睡眠時間の増加が大きいように見えます。
Group1と2の間で睡眠時間の増加に有意差があるかををWilcoxonの符号順位検定、またはWilcoxonの順位和検定にて計算します。
Pythonの場合、Scipyのscipy.stats.wilcoxon()
を使用します(公式リファレンス)。
Python環境構築についてはコチラを参照
#!/usr/bin/env python
# Scipyのバージョンが1.5.0より大きいかによって一部挙動が代わります。
# ここでは、現状のGoogleColabに従い、1.4.1版の結果を記載します。
import sys
import scipy
import scipy.stats as st
print(f"Python {sys.version}") # 3.7.10
print(f"Scipy {scipy.__version__}") # 1.4.1
group1 = [0.7, -1.6, -0.2, -1.2, -0.1, 3.4, 3.7, 0.8, 0.0, 2.0]
group2 = [1.9, 0.8, 1.1, 0.1, -0.1, 4.4, 5.5, 1.6, 4.6, 3.4]
p_value_wilc = st.wilcoxon(group1, group2, alternative="two-sided").pvalue
print(p_value_wilc) # => 0.007632441648205508
グラフでの見た目と同様に有意差がついていることがわかります。
両側検定を目的としてウィルコクソンの順位和検定を行う際は、alternative="two-sided"
を指定する必要がある。
このオプションを指定しないと有利な方向へ片側検定を行ってしまうため。
#!/usr/bin/env python
import sys
import scipy
import scipy.stats as st
print(f"Scipy {scipy.__version__}")
# => 1.4.1
group1 = [0.7, -1.6, -0.2, -1.2, -0.1, 3.4, 3.7, 0.8, 0.0, 2.0]
group2 = [1.9, 0.8, 1.1, 0.1, -0.1, 4.4, 5.5, 1.6, 4.6, 3.4]
p_value_manh = st.mannwhitneyu(group1, group2, alternative="two-sided").pvalue
print(p_value_manh) # => 0.06932757543362658
RとPythonでは少し結果が違います。これはタイ値の扱いが関わってきます。次の節にて解説します。
#!/usr/bin/env Rscript
group1 = c(0.7, -1.6, -0.2, -1.2, -0.1, 3.4, 3.7, 0.8, 0.0, 2.0)
group2 = c(1.9, 0.8, 1.1, 0.1, -0.1, 4.4, 5.5, 1.6, 4.6, 3.4)
p_value_wilcoxon = wilcox.test(group1, group2, paired=T)$p.value
print(p_value_wilcoxon) # => 0.009090698
#!/usr/bin/env Rscript
group1 = c(0.7, -1.6, -0.2, -1.2, -0.1, 3.4, 3.7, 0.8, 0.0, 2.0)
group2 = c(1.9, 0.8, 1.1, 0.1, -0.1, 4.4, 5.5, 1.6, 4.6, 3.4)
p_value_mannwhitney = wilcox.test(group1, group2)$p.value
print(p_value_mannwhitney) # => 0.06932758
R | Python(Scipy<1.5.0) | Python (Scipy≧1.5.0) | |
---|---|---|---|
連続性補正 | 行う (correct = T) | 行わない (correction = False) | 行わない (correction = False) |
正確検定 | 自動で判定 (「タイ値がない」かつ「サンプル数が50未満」の場合正確検定を行う) | できない | 自動で判定 (「タイ値がない」かつ「サンプル数が26未満」の場合正確検定を行う) |
比較する2群間で同じ値の扱い | 破棄する (オプションで選択できない) | 破棄する (zero_method='wilcox') | 破棄する (zero_method='wilcox') |
ウィルコクソンの符号順位検定においては複数のオプションがあり、上記を調整するとRとPythonの結果を一致させることができる。