Up

被験者内2要因分散分析

 

Pythonスクリプトとサンプルデータファイルは圧縮ファイルanova_two_rel.zipにまとめた。Jupyter Notebook用は圧縮ファイルanova_two_rel_jn.zipとした。これらはダウンロード・解凍して自由に利用されたい。

 

 被験者内2要因分散分析のモデルを以下のように設定する。

被験者内2要因、AおよびB、のモデルにおける平方和を次のように分解する。ただし、は、番目の被験者に対する要因Aの水準、要因Bの水準におけるデータであり、要因Aの水準数は、要因Bの水準数は、被験者数はであるとする。

ここで、

である。

 上記の各平方和の平均の期待値は次のようになる。

 以上より、分散分析表を表1のように作成する。

 

表1 分散分析表

変動因

平方和

自由度

平均平方和

F比

被験者間

 

 

被験者内

 

 

残差(A)

 

残差(B)

 

A×B

残差(A×B)

 

全体

 

 

 

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

 

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

 

import csv

import numpy as np

import scipy.stats as ss

 

 

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...')

for v in data:

    for w in v:

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

    print()

 

ck_cnt = data[0][1:]

cnts = np.bincount(ck_cnt)

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)

fout.write('\na = {}\n'.format(a))

print('b = ', b)

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

print('N = ', N)

fout.write('N = {}\n'.format(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])

 

print('\nYijk =')

fout.write('\nYijk =\n')

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 = '')

            fout.write('{0:>7.1f}'.format(Y[i][j][k]))

    print()

    fout.write('\n')

 

Yppp = Y.mean()

print('\nY... = {0:<10.2f}'.format(Yppp))

fout.write('\nY... = {0:<10.2f}\n'.format(Yppp))

 

Yijp = np.zeros((N,a))

for i in range(N):

    for j in range(a):

        Yijp[i][j] = Y[i,j,:].mean()

 

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')

 

Yipp = np.zeros(N)

for i in range(N):

    Yipp[i] = Y[i,:,:].mean()

   

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')

 

Yipk = np.zeros((N,b))

for i in range(N):

    for k in range(b):

        Yipk[i][k] = Y[i,:,k].mean()

 

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

 

SS_S = a * b * np.sum((Yipp - Yppp)**2)

 

SS_WS = SS_T - SS_S

 

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

 

SS_AS = 0.0

for i in range(N):

    for j in range(a):

        SS_AS += (Yijp[i][j] - Yipp[i] - Ypjp[j] + Yppp)**2

SS_AS *= b

 

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

 

SS_BS = 0.0

for i in range(N):

    for k in range(b):

        SS_BS += (Yipk[i][k] - Yipp[i] - Yppk[k] + Yppp)**2

SS_BS *= a

 

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_ABS = SS_T - (SS_S + SS_A + SS_AS + SS_B + SS_BS + SS_AB)

 

df_T = N * a * b - 1

df_S = N - 1

df_WS = N * (a * b - 1)

df_A = a - 1

df_AS = (N - 1) * (a - 1)

df_B = b - 1

df_BS = (N - 1) * (b - 1)

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

df_ABS = (N - 1) * (a - 1) * (b - 1)

 

MS_S = SS_S / df_S

MS_A = SS_A / df_A

MS_AS = SS_AS / df_AS

MS_B =  SS_B / df_B

MS_BS = SS_BS / df_BS

MS_AB = SS_AB / df_AB

MS_ABS = SS_ABS / df_ABS

 

F_A = MS_A / MS_AS

F_B = MS_B / MS_BS

F_AB = MS_AB / MS_ABS

 

p_a = 1.0 - ss.f.cdf(F_A, df_A, df_AS)

p_b = 1.0 - ss.f.cdf(F_B, df_B, df_BS)

p_ab = 1.0 - ss.f.cdf(F_AB, df_AB, df_ABS)

 

print('\n')

fout.write('\n\n')

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

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

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

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

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

      format('S', SS_S, df_S, MS_S))

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

      format('S', SS_S, df_S, MS_S))

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

      format('SSw.s', SS_WS, df_WS))

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

      format('SSw.s', SS_WS, df_WS))

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

      format('A', SS_A, df_A, 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, df_A, MS_A, F_A, p_a))

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

      format('AS', SS_AS, df_AS, MS_AS))

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

      format('AS', SS_AS, df_AS, MS_AS))

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

      format('B', SS_B, df_B, 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, df_B, MS_B, F_B, p_b))

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

      format('BS', SS_BS, df_BS, MS_BS))

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

      format('BS', SS_BS, df_BS, MS_BS))

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

      format('AB', SS_AB, df_AB, 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, df_AB, MS_AB, F_AB, p_ab))

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

      format('ABS', SS_ABS, df_ABS, MS_ABS))

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

      format('ABS', SS_ABS, df_ABS, MS_ABS))

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

      format('SStotal', SS_T, df_T))

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

      format('SStotal', SS_T, df_T))

 

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=3)までの整数値で表す。整数値は1からaまでの昇順である。第2行目は被験者内要因Bの水準を示すものである。第1セルにBと書いて、要因Bであることを表している。要因Aの各水準内において要因Bの水準が1から要因Bの水準の数b(図2では、b=2)までの整数値が昇順に並べられている。第3行目から、各水準の組み合わせの下でのデータを設定する。図2では、例えば赤枠で囲まれたデータは、要因Aの各水準A1A2A3と要因Bの各水準B1B2の組み合わせの下での一人の被験者のデータである。要因Aと要因Bは被験者内要因(繰り返し要因)なので、各被験者は水準Aと水準Bの全ての組み合わせ条件のデータがある。赤線で囲まれたデータ「37、・・・、59」はある一人の被験者のデータである。なお、CSV形式のファイルについては、拙著<岡本安晴「いまさら聞けないPythonでデータ分析――多変量解析、ベイズ統計分析(PyStan, PyMC)――」丸善出>のpp. 33-35で説明している。拙著では、第2章においてグラフ描画の説明も行っている。

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

 

        SV        SS        df        MS         F     P(>F)

         S     49.14      5.00      9.83

     SSw.s   1515.17     30.00

         A    770.39      2.00    385.19     30.50   0.00006

        AS    126.28     10.00     12.63

         B    476.69      1.00    476.69     24.88   0.00415

        BS     95.81      5.00     19.16

        AB      0.06      2.00      0.03      0.01   0.99398

       ABS     45.94     10.00      4.59

   SStotal   1564.31     35.00

 

Output file Results.txt was saved.

 

>>> 

 

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

 

リスト2 出力ファイル例

 

Data file name = Data.csv

 

a = 3

b = 2

N = 6

 

Yijk =

   37.0   41.0   46.0   53.0   49.0   59.0

   42.0   47.0   48.0   56.0   55.0   59.0

   45.0   46.0   48.0   53.0   53.0   53.0

   37.0   50.0   47.0   55.0   48.0   57.0

   40.0   56.0   46.0   55.0   47.0   59.0

   38.0   42.0   49.0   56.0   53.0   62.0

 

Y... = 49.64    

 

Y.jk =

     39.83     47.00     47.33     54.67     50.83     58.17

 

Y.j. =

     43.42     51.00     54.50

 

Y..k =

     46.00     53.28

 

 

        SV        SS        df        MS         F     P(>F)

         S     49.14      5.00      9.83

     SSw.s   1515.17     30.00

         A    770.39      2.00    385.19     30.50   0.00006

        AS    126.28     10.00     12.63

         B    476.69      1.00    476.69     24.88   0.00415

        BS     95.81      5.00     19.16

        AB      0.06      2.00      0.03      0.01   0.99398

       ABS     45.94     10.00      4.59

   SStotal   1564.31     35.00

 

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

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

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

 

Up