Up

重回帰分析

 

重回帰分析(multiple linear regression analysis)のプログラムを<岡本安晴「心理学データ分析と測定」勁草書房>の第2章の式に基づいて作成した。プログラムファイルとサンプルデータファイルは、圧縮ファイルMRgrsnPrg.zipにまとめた。

重回帰モデルは

と表せる。式(1)のモデルを、例えば表2.1.1のデータに当てはめる。

 

2.1.1 (物理、数学、身長)の50人分のデータ

(53, 73, 167)        (65, 53, 152)        (54, 50, 145)

(59, 58, 153)        (58, 49, 176)        (51, 52, 148)

(52, 49, 159)        (63, 69, 153)        (64, 63, 158)

(75, 83, 161)        (66, 58, 171)        (59, 57, 154)

(75, 90, 172)        (65, 76, 167)        (70, 61, 160)

(62, 60, 152)        (58, 44, 166)        (79, 98, 160)

(65, 65, 161)        (63, 54, 161)        (60, 47, 173)

(64, 67, 165)        (67, 71, 168)        (52, 53, 165)

(60, 70, 162)        (63, 70, 171)        (69, 72, 173)

(57, 58, 159)        (58, 65, 165)        (51, 51, 157)

(60, 63, 163)        (50, 42, 151)        (52, 43, 177)

(67, 69, 149)        (59, 67, 167)        (44, 35, 168)

(79, 85, 157)        (54, 66, 180)        (75, 82, 150)

(60, 74, 156)        (62, 63, 165)        (54, 48, 164)

(69, 73, 166)        (74, 87, 163)        (72, 81, 160)

(56, 66, 165)        (70, 77, 174)        (64, 60, 166)

(71, 72, 145)        (70, 69, 151)       

 

プログラムでは、最小2乗法の基準で(1)式の係数を求めている。

プログラムを実行すると、入力データファイル名の設定が求められる(図1)。

図1

 

入力データファイルは、図2のような形式で用意する。

図2

 

第1文字がスラッシュ / で始まる行の次の行に、独立変数の数を書く。この第1文字がスラッシュで始まる行までは、ファイルは読み飛ばされるので、コメントなどを自由に書くことができる。

独立変数の数を書いた次の行に、従属変数名と独立変数名をタブ、あるいは半角空白文字で区切って書き並べる。

次の行から、1行に1組(従属変数と独立変数)のデータを、上の変数名の順序に合わせて書いていく。最後のデータの組を書いたら、その次の行は第1文字がスラッシュ / である行を置いて、データの終わりであることを示す。

データファイルが、プログラムファイルと同じフォルダ内にあるときは、データファイル名のみを入力すればよい(図3)。データファイル名を設定してEnterキーを押すと、次に出力ファイル名の設定が求められる。

図3

 

出力ファイル名はテキストファイル名(拡張子が「.txt」)を設定する(図4)。出力ファイル名の設定後、Enterキーを押すと計算が始まる。

図4

 

計算終了後、出力ファイルを開くと、表2.1.1のデータの場合、以下のようになっている。

 

Input data file = Data211.txt

 

 

Labels...

Y:  Physics

X[0]: (Const)

X[1]: Math

X[2]: Height

 Input data...

      53.0   73.0  167.0

      65.0   53.0  152.0

      54.0   50.0  145.0

      59.0   58.0  153.0

      58.0   49.0  176.0

      51.0   52.0  148.0

     ・

     ・

     ・

      72.0   81.0  160.0

      56.0   66.0  165.0

      70.0   77.0  174.0

      64.0   60.0  166.0

      71.0   72.0  145.0

      70.0   69.0  151.0

 

b[0]<(Const)> = 43.0634604

b[1]<Math> = 0.4944112

b[2]<Height> = -0.0766585

 

Physics = 43.0634604 + 0.4944112 * Math + -0.0766585 * Height + Residual

 

R2 = 0.6802908

R  = 0.8247974

 

b[0]<(Const)>:

      t = 3.2620618   df = 47   p-value = 0.0020633

b[1]<Math>:

      t = 9.9499663   df = 47   p-value = 0.0000000

b[2]<Height>:

      t = -0.9704341   df = 47   p-value = 0.3367980

 

95% Confidence Intervals:

b[0]<(Const)>:

             [16.50587, 69.62105]

b[1]<Math>:

             [0.39445, 0.59437]

b[2]<Height>:

             [-0.23557, 0.08226]

 

まず、入力データファイル名が出力されている。続いて、変数名が出力され、その後、読み込まれたデータ値が出力されている。これらにより、データが正しく読み込まれたかどうかのチェックができる。

読み込みデータの出力後、算出されたの推定値がb[j]の値として変数名とともに出力され、最後に重回帰モデル(1)の係数b[j]の値を代入した形で式が書かれている。

式に続いて、多重決定係数と重相関係数Rの値が、R2およびRの値として書かれている。

次に、各係数の値のt値、自由度、およびp値(両側検定)が出力されている。

最後に、各係数の95%信頼区間が書き出されている。

 

メインプログラムのリスト(スクリプト)を以下に示す。メインプログラムを含めたプログラムのソースコードファイル(スクリプト)とサンプルデータファイルは、圧縮ファイルMRgrsnPrg.zipとしてまとめた。

 

from math import *

import numpy as np

import numpy.linalg as nl

from splitstring import *

from calc_p_from_t import *

from calc_t_from_p import *

 

def CheckStr(str):

    ck = False

    if len(str) > 0:

        if str[0] == '/':

            ck = True

    return ck

 

#

#       Prepare the input data file

#

s_in = input("Input data file = ")

f_in = open(s_in, "r")

#

#       Set the contents of the input data file in the object data

#

data_f = f_in.readlines()

f_in.close()

 

#

#       Prepare the output file

#

s_out = input("Output data file = ")

f_out = open(s_out, "w")

f_out.write("Input data file = " + s_in + "\n\n")

 

pos = 0

while not CheckStr(data_f[pos]):

    print(data_f[pos])

    pos += 1

 

pos += 1

 

splitStr = CSplit(' ', '\t', '\n')

splitStr.set_string(data_f[pos])

p = int(splitStr.seek_nonempty(0))

print("Number of independent variables, p = {}\n".format(p))

p += 1

pos += 1

splitStr.set_string(data_f[pos])

YLabel = splitStr.seek_nonempty(0)

XLabel = ['(Const)']

for i in range(1, p):

    XLabel.append(splitStr.seek_nonempty(i))

 

f_out.write('\nLabels...\n')

f_out.write('Y:  {}\n'.format(YLabel))

for i in range(p):

    f_out.write('X[{0}]: {1}\n'.format(i, XLabel[i]))

 

 

y = []

x = []

n = 0

pos += 1

while not CheckStr(data_f[pos]):

    splitStr.set_string(data_f[pos])

    y.append(float(splitStr.seek_nonempty(0)))

    x.append([1])

    for j in range(1, p):

        x[n].append(float(splitStr.seek_nonempty(j)))

    n += 1

    pos += 1

 

Y = np.matrix(y)

Y = np.transpose(Y)

X = np.matrix(x)

f_out.write(" ")

f_out.write("Input data...\n")

for i in range(n):

    f_out.write("{0:10}".format(Y[i,0]))

    for j in range(1, p):

        f_out.write("{0:7}".format(X[i, j]))

    f_out.write('\n')

 

XpXinv = nl.inv(np.transpose(X) * X)

b = XpXinv * np.transpose(X) * Y

f_out.write('\n')

for j in range(p):

    f_out.write("b[{0}]<{1}> = {2:.7f}\n".format(j, XLabel[j], b[j, 0]))

 

f_out.write('\n')

eq_str = YLabel + " = " + ("{0:.7f}".format(b[0, 0]))

for j in range(1, p):

    eq_str += " + " + "{0:.7f} * {1}".format(b[j, 0], XLabel[j])

eq_str += " + Residual"

f_out.write(eq_str + '\n')

 

sumY = 0.0

for i in range(n):

    sumY += Y[i, 0]

meanY = sumY / n

Yhat = X * b

SSReg = 0.0

SSTot = 0.0

for i in range(n):

    SSReg += (Yhat[i, 0] - meanY) ** 2.0

    SSTot += (Y[i, 0] - meanY) ** 2.0

 

R2 = SSReg / SSTot

R  = sqrt(R2)

f_out.write('\nR2 = {0:.7}\n'.format(R2))

f_out.write('R  = {0:.7}\n'.format(R))

 

SSE = np.transpose(Y - X * b) * (Y - X * b)

MSE = SSE[0, 0] / (n - p)

s2_b = MSE * XpXinv

t = []

for j in range(p):

    t.append(b[j, 0] / sqrt(s2_b[j,j]))

 

calc_p = C_cum_t(n - p)

p_v = []

for j in range(p):

    tp = calc_p.v(t[j])

    if tp < 0.5:

        p_v.append(2.0 * tp)

    else:

        p_v.append(2.0 * (1.0 - tp))

           

f_out.write('\n')

for j in range(p):

    f_out.write('b[{0}]<{1}>:\n      t = {2:.7f}   df = {3}   p-value = {4:.7f}\n'.\

                format(j, XLabel[j], t[j], n - p, p_v[j]))

 

calc_t = CCalc_t(n - p)

t_a2 = calc_t.v(1.0 - 0.025)

L_Int = []

U_Int = []

for j in range(p):

    L_Int.append(b[j, 0] - sqrt(s2_b[j, j]) * t_a2)

    U_Int.append(b[j, 0] + sqrt(s2_b[j, j]) * t_a2)

f_out.write('\n')

f_out.write('95% Confidence Intervals:\n')

for j in range(p):

    f_out.write('b[{0}]<{1}>:\n             [{2:.5f}, {3:.5f}]\n'.\

                format(j, XLabel[j], L_Int[j], U_Int[j]))

 

f_out.close()

 

 

 

Up