分散分析

はじめに

Rの分散分析のPython版です。

分散分析(Analysis of Variance、ANOVA、アノーヴァ)は、複数の群の平均値が等しいかどうかを調べる方法です。ここではとりあえず一元配置分散分析(oneway-anova)だけ扱います。

なお、分散分析をする前に、しかるべき方法でデータを可視化して、どのようなデータを扱っているかをよく見るようにしましょう。

SciPyによる方法

2群の平均値を比べるには $t$ 検定を使いますが、一般に2群以上の平均値が等しいかどうか調べるには一元配置分散分析を使います。Rでは oneway.test という関数を使いますが、Python(SciPy)では scipy.stats.f_oneway を使います。f_ は $F$ 分布を使うことから来ているのだと思います。

注意すべきは、Rの oneway.test が等分散を仮定しないWelchの方法(var.equal=FALSE)がデフォルトなのに対し、こちらは等分散を仮定する(equal_var=True)がデフォルトです。等分散であることが初めからわかっている場合を除き、equal_var=False を付けましょう。

from scipy import stats

x = [1, 3]
y = [5, 8, 5]
z = [4, 2]
stats.f_oneway(x, y, z, equal_var=False)
F_onewayResult(statistic=np.float64(3.391304347826088), pvalue=np.float64(0.1998454186043655))

$F = 3.3913$、$p = 0.1998$ です。

あるいは次のようにしてもかまいません。

from scipy import stats

groups = [
    [1, 3],
    [5, 8, 5],
    [4, 2]
]
stats.f_oneway(*groups, equal_var=False)

pingouinによる方法

よりRに近い簡便さを望むなら、Pingouin パッケージを使います(pip install pingouin)。等分散を仮定しないWelchの分散分析は次のように行えます。

import pandas as pd
import pingouin as pg

df = pd.DataFrame({
    "score": [1, 3, 5, 8, 5, 4, 2],
    "group": [1, 1, 2, 2, 2, 3, 3]
})

pg.welch_anova(data=df, dv="score", between="group")
  Source  ddof1  ddof2         F     p_unc     np2
0  group      2    2.4  3.391304  0.199845  0.6875

$p = 0.1998$ で有意ではありませんが、仮に有意なら、伝統的にはGames–Howell法を使ってどのペアが異なるかを調べます。

pg.pairwise_gameshowell(data=df, dv="score", between="group", effsize="hedges")
   A  B  mean_A  mean_B  diff        se         T        df      pval    hedges
0  1  2     2.0     6.0  -4.0  1.414214 -2.828427  2.666667  0.143617 -1.781447
1  1  3     2.0     3.0  -1.0  1.414214 -0.707107  2.000000  0.784182 -0.404061
2  2  3     6.0     3.0   3.0  1.414214  2.121320  2.666667  0.247435  1.336085

pval は多重比較調整済みの $p$ 値です。hedges は Hedges' $g$ という効果量です。

なお、各群の分散が等しいと仮定できる場合は通常の(Welchでない)分散分析をしてからTukeyのHSD法でどのペアが有意かを調べます。