Pythonによる対応ありone-way ANOVA(一元配置分散分析)と多重比較
目標
対応ありone-way ANOVA(一元配置分散分析)と多重比較のプログラムをPythonで書く。対応無しのone-way ANOVAについては、 Unpaired One-way ANOVA And Multiple Comparisons In Python“を参照してください。
ANOVAとは
ANOVA(analysis of variance)は、サンプル内のグループの平均値の差について、要因間で優位な差があるかどうかを確かめる統計的仮設検定の方法です。
内容の詳細については割愛します。下記サイトなどをご覧ください。
one-way ANOVA(一元配置分散分析)とは、3つ以上のサンプルの平均を比較する分散分析テストです。 帰無仮説は、全てのグループのサンプルが同じ平均の母集団から取られたというものです。
対応のある分散分析とは、同じ被験者に対して繰り返し条件を変えて実験したような場合のデータを扱うことを意味します。
実装
以下は、対応のあるone-way ANOVAの実装例です。
ライブラリのインポート
ANOVAの検定をおこなうために以下のライブラリをインポートします。
import statsmodels.api as sm from statsmodels.formula.api import ols import pandas as pd import numpy as np import statsmodels.stats.anova as anova
データの用意
以下のようなデータを使用します。id_nは被験者であり、条件はA、B、Cの3つです。
id_1 | id_2 | id_3 | id_4 | id_5 | id_6 | id_7 | |
condition A | 85 | 90 | 88 | 69 | 78 | 98 | 87 |
condition B | 55 | 82 | 67 | 64 | 78 | 54 | 49 |
condition C | 46 | 95 | 59 | 80 | 52 | 73 | 70 |
test_data.csvという名前で以下のようなファイルを作成します。
85, 90, 88, 69, 78, 98, 87 55, 82, 67, 64, 78, 54, 49 46, 95, 59, 80, 52, 73, 70
データの読み込みと格納
open(‘file_name’, ) as f: でファイルを読み込みます。fを区切って各数値をitemsに格納していきます。各行について、itemsを取得したら、csv_lines[0], csv_lines[1], csv_lines[2]に格納します。
csv_line = [] with open('test_data.csv', ) as f: for i in f: items = i.split(',') for j in range(len(items)): if 'n' in items[j]: items[j] = float(items[j][:-1]) else: items[j] =float(items[j]) print(items) csv_line.append(items)
各行のデータにgroupA, groupB, groupCと名付けました。(csv_lineに入れずに直接groupA, groupB, groupCに入れることもできますが、自分が分かりやすくするためこのようにしました)
ラベルを付けて、各グループのデータをセットし、pd.DataFrameを作成。
groupA = csv_line [0] groupB = csv_line [1] groupC = csv_line [2] tdata = pd.DataFrame({'A':groupA, 'B':groupB, 'C':groupC}) tdata.index = range(1,10) tdata
tdataは以下のようになります。

もしも、平均や分散などデータの統計的値を見たい場合は、DataFrame.describe()を実行.
tdata.describe()

ANOVAの実行
得点、条件、被験者のデータからpd.DataFrameを作成する。
- subjects: ‘id1’, ‘id2’, ‘id3’, ‘id4’, ‘id5’, ‘id6’, ‘id7’, ‘id1’, ‘id2’, ‘id3’, ‘id4’, ‘id5’, ‘id6’, ‘id7’, ‘id1’, ‘id2’, ‘id3’, ‘id4’, ‘id5’, ‘id6’, ‘id7’
- points: groupA + groupB + groupC = 85, 90, 88, 69, 78, 98, 87, 55, 82, 67, 64, 78, 54, 49, 46, 95, 59, 80, 52, 73, 70.
- conditions: ‘A’, ‘A’, ‘A’, ‘A’, ‘A’, ‘A’, ‘A’, ‘B’, ‘B’, ‘B’, ‘B’, ‘B’, ‘B’, ‘B’, ‘C’, ‘C’, ‘C’, ‘C’, ‘C’, ‘C’, ‘C’
subjects=['id1','id2','id3','id4','id5','id6','id7'] points = np.array(group0 +group1 + group2) conditions = np.repeat(['A','B','C'],len(groupA)) subjects = np.array(subjects+subjects+subjects) df = pd.DataFrame({'Point':points,'Conditions':conditions,'Subjects':subjects})
anova.AnovaRM(df, ‘Point’, ‘Subjects’, [‘Conditions’])でANOVAを実行。
aov=anova.AnovaRM(df, 'Point','Subjects',['Conditions']) result=aov.fit() print(result) >> Anova ======================================== F Value Num DF Den DF Pr > F ---------------------------------------- Conditions 5.4182 2.0000 12.0000 0.0211 ========================================
p値が小さいほど、帰無仮説が棄却されるようになる。統計的に優位な場合、つまりp値が0.05未満(通常≤0.05)の場合は、多重比較を実行します。 このp値は、対応のある分散分析と対応のない分散分析で異なります。
Tukeyの多重比較
テューキーの範囲検定(tuky’s HSD, honestly significant difference test)を行うには、pairwise_tukeyhsd(endog, groups, alpha=0.05)を使用します。引数endogは従属変数のデータの配列(A[0] A[1]… A[6] B[1] … B[6] C[1] … C[6])です。引数groupsは、従属変数に対応する名前(A、A…A、B…B、C…C)のリストです。alphaは有意水準です。
def tukey_hsd(group_names , *args ): endog = np.hstack(args) groups_list = [] for i in range(len(args)): for j in range(len(args[i])): groups_list.append(group_names[i]) groups = np.array(groups_list) res = pairwise_tukeyhsd(endog, groups) print (res.pvalues) #print only p-value print(res) #print result
結果の出力
次の場合は、Group AとGroup Bの平均に有意差があるという結果になります。
print(tukey_hsd(['A', 'B', 'C'], tdata['A'], tdata['B'],tdata['C'])) >> [0.02259466 0.06511251 0.85313142] Multiple Comparison of Means - Tukey HSD, FWER=0.05 ===================================================== group1 group2 meandiff p-adj lower upper reject ----------------------------------------------------- A B -20.8571 0.0226 -38.9533 -2.7609 True A C -17.1429 0.0651 -35.2391 0.9533 False B C 3.7143 0.8531 -14.3819 21.8105 False ----------------------------------------------------- None