Up

被験者間2要因分散分析

 

被験者間2要因の分散分析を行うPythonスクリプトを、<岡本安晴「データを使いこなすための統計入門」22世紀アートpp. 115-128>に説明されている式に基づいて作成した。スクリプトとサンプルデータは圧縮ファイルanova_two_ind.zipとしてまとめた。Jupyter Notebook用のものは圧縮ファイルanova_two_ind_jn.zipとした。それぞれダウウンロード・解凍して自由に利用されたい。

 

被験者間2要因分散分析の基本式は、全分散を、以下のように平方和に分解するものである。

 

ここで、

これより、平均平方和は次式で与えられる。

自由度dfは次式で与えられる。

このとき、F値とF分布のパラメータは次の通りである。

主効果A

主効果B

交互作用AB

 

上の式に基づいて、リスト1に示すスクリプトを用意した。このスクリプトのファイルとサンプルデータファイルはまとめて圧縮ファイルfiles.zipとした。

 

リスト1 被験者間2要因分散分析Pythonスクリプト例

import csv

import numpy as np

 

 

fin_name = input('Data file name(*.csv) = ')

with open(fin_name, 'r') as f:

    data = [v for v in csv.reader(f)]

 

fout_name = input('Output file name(*.txt) = ')

fout = open(fout_name, 'w')

fout.write('Data file name = {}\n'.format(fin_name))

 

print('Data file...')

fout.write('\nData...\n')

for v in data:

    for w in v:

        print('{0: >7s}'.format(w), end = '')

        fout.write('{0: >7s}'.format(w))

    print()

    fout.write('\n')

 

ck_cnt = data[0][1:]

cnts = np.bincount(ck_cnt)

print(cnts)

a = len(cnts) - 1

ck_cnt = data[1][1:]

cnts = np.bincount(ck_cnt)

b = len(cnts) - 1

N = len(data) - 2

print('a = ', a)

print('b = ', b)

print('N = ', N)

 

Y = np.zeros((N, a, b))

for i in range(N):

    for j in range(a):

        for k in range(b):

            Y[i][j][k] = float(data[i+2][1 + k + j*b])

 

for i in range(N):

    for j in range(a):

        for k in range(b):

            print('{0:>7.1f}'.format(Y[i][j][k]), end = '')

    print()

 

Yppp = Y.mean()

print('Y... = ', Yppp)

fout.write('\nY... = {}\n'.format(Yppp))

Ypjk = np.zeros((a, b))

for j in range(a):

    for k in range(b):

        Ypjk[j][k] = Y[:,j,k].mean()

 

print('\nY.jk =')

fout.write('\nY.jk =\n')

for j in range(a):

    for k in range(b):

        print('{0:>10.2f}'.format(Ypjk[j][k]), end = '')

        fout.write('{0:>10.2f}'.format(Ypjk[j][k]))

 

print()

fout.write('\n')

 

Ypjp = np.zeros(a)

for j in range(a):

    Ypjp[j] = Y[:,j,:].mean()

print('Y.j. = ')

fout.write('\nY.j. =\n')

for j in range(a):

    print('{0:>10.2f}'.format(Ypjp[j]), end = '')

    fout.write('{0:>10.2f}'.format(Ypjp[j]))

print()

fout.write('\n')

 

Yppk = np.zeros(b)

for k in range(b):

    Yppk[k] = Y[:,:,k].mean()

print('Y..k =')

fout.write('\nY..k =\n')

for k in range(b):

    print('{0:>10.2f}'.format(Yppk[k]), end = '')

    fout.write('{0:>10.2f}'.format(Yppk[k]))

print()

fout.write('\n')

              

SS_A = b * N * np.sum((Ypjp - Yppp)**2)

 

SS_B = a * N * np.sum((Yppk - Yppp)**2)

 

SS_AB = 0.0

for j in range(a):

    for k in range(b):

        SS_AB += (Ypjk[j][k] - Ypjp[j] - Yppk[k] + Yppp)**2

SS_AB *= N

 

SS_T = np.sum((Y - Yppp)**2)

SS_S_AB = SS_T - SS_A - SS_B - SS_AB

 

dfT = a * b * N

dfA = a - 1

dfB = b - 1

dfAB = (a - 1) * (b - 1)

dfS_AB = a * b * (N-1)

 

MS_A = SS_A / dfA

MS_B = SS_B / dfB

MS_AB = SS_AB / dfAB

MS_S_AB = SS_S_AB / dfS_AB

 

F_A = MS_A / MS_S_AB

F_B = MS_B / MS_S_AB

F_AB = MS_AB / MS_S_AB

 

import scipy.stats as ss

 

p_a = 1.0 - ss.f.cdf(F_A, dfA, dfS_AB)

p_b = 1.0 - ss.f.cdf(F_B, dfB, dfS_AB)

p_ab = 1.0 - ss.f.cdf(F_AB, dfAB, dfS_AB)

 

print('\n')

print('{0: >10s}{1: >10s}{2: >10s}{3: >10s}{4: >10s}{5: >10s}'.

      format(' ', 'SS', 'df', 'MS', 'F', 'P(>F)'))

fout.write('\n{0: >10s}{1: >10s}{2: >10s}{3: >10s}{4: >10s}{5: >10s}\n'.

      format(' ', 'SS', 'df', 'MS', 'F', 'P(>F)'))

print('{0: >10s}{1: >10.2f}{2: >10.2f}{3: >10.2f}{4: >10.2f}{5: >10.5f}'.

      format('A', SS_A, dfA, MS_A, F_A, p_a))

fout.write('{0: >10s}{1: >10.2f}{2: >10.2f}{3: >10.2f}{4: >10.2f}{5: >10.5f}\n'.

      format('A', SS_A, dfA, MS_A, F_A, p_a))

print('{0: >10s}{1: >10.2f}{2: >10.2f}{3: >10.2f}{4: >10.2f}{5: >10.5f}'.

      format('B', SS_B, dfB, MS_B, F_B, p_b))

fout.write('{0: >10s}{1: >10.2f}{2: >10.2f}{3: >10.2f}{4: >10.2f}{5: >10.5f}\n'.

      format('B', SS_B, dfB, MS_B, F_B, p_b))

print('{0: >10s}{1: >10.2f}{2: >10.2f}{3: >10.2f}{4: >10.2f}{5: >10.5f}'.

      format('AB', SS_AB, dfAB, MS_AB, F_AB, p_ab))

fout.write('{0: >10s}{1: >10.2f}{2: >10.2f}{3: >10.2f}{4: >10.2f}{5: >10.5f}\n'.

      format('AB', SS_AB, dfAB, MS_AB, F_AB, p_ab))

print('{0: >10s}{1: >10.2f}{2: >10.2f}{3: >10.2f}'.

      format('S/AB', SS_S_AB, dfS_AB, MS_S_AB))

fout.write('{0: >10s}{1: >10.2f}{2: >10.2f}{3: >10.2f}\n'.

      format('S/AB', SS_S_AB, dfS_AB, MS_S_AB))

 

fout.close()

print('\nOutput file {} was saved.\n'.format(fout_name))

 

上のスクリプトを実行すると、入力データファイル名と出力用テキストファイル名の設定が求められる。

図1

 

データファイルはCSVファイルの形式で用意する。Excelで用意するときは図2に示すように用意して、保存ファイルのファイル拡張子として「.csv」を選べばよい。

図2

 

第1行目は要因Aの水準を示すものである。第1セルにAと書いて、要因Aであることを表している。第2セルからAの要因を1から水準の数a(図2ではa=2)までの整数値で表す。整数値は1からaまでの昇順である。第2行目は要因Bの水準を示すものである。第1セルにBと書いて、要因Bであることを表している。要因Aの各水準内において要因Bの水準が1から要因Bの水準の数b(図2では、b=2)までの整数値が昇順に並べられている。第3行目から、各水準の組み合わせの下でのデータを設定する。図2では、要因A1,B1のデータとして、636972が設定されおり、要因A2,B2のデータとして667173が設定されている。なお、CSV形式のファイルについては、拙著<岡本安晴「いまさら聞けないPythonでデータ分析――多変量解析、ベイズ統計分析(PyStan, PyMC――」丸善出>のpp. 33-35で説明している。拙著では、第2章においてグラフ描画の説明も行っている。

出力用テキストファイル名の設定後、計算が始まり、計算が終了すると下記のようなコンソール上への出力で終了する。

 

                  SS        df        MS         F     P(>F)

         A   1452.00      1.00   1452.00     72.60   0.00003

         B   1200.00      1.00   1200.00     60.00   0.00006

        AB     12.00      1.00     12.00      0.60   0.46086

      S/AB    160.00      8.00     20.00

 

Output file Results.txt was saved.

 

>>> 

 

出力ファイル(上の例では、Results.txt)を開くと、図2のデータの場合、リスト2の内容になっている。

 

リスト2 出力ファイル例

Data file name = Data.csv

 

Data...

      A      1      1      2      2

      B      1      2      1      2

            63     46     87     66

            69     49     92     71

            72     55     97     73

 

Y... = 70.0

 

Y.jk =

     68.00     50.00     92.00     70.00

 

Y.j. =

     59.00     81.00

 

Y..k =

     80.00     60.00

 

                  SS        df        MS         F     P(>F)

         A   1452.00      1.00   1452.00     72.60   0.00003

         B   1200.00      1.00   1200.00     60.00   0.00006

        AB     12.00      1.00     12.00      0.60   0.46086

      S/AB    160.00      8.00     20.00

 

入力データファイルから読み込んだデータが出力されているので、データが正しく読み込まれたかどうかの確認ができる。

続いて、平均値が出力されている。

最後に、分散分析表が出力されている。P(>F)p値である。

 

Up