Home

拙著「Pythonでデータ分析」の第7章「主成分分析」の更新と附記

 

スクリプトを更新した。なお、主成分分析における回転については、Okamoto (2006)で説明している。正射影の観点による主成分分析の2つの目的関数の関係については、本サイトの後半附記で論じた。

更新スクリプトはリスト1に示した。スクリプトファイルは、他のファイルとともに圧縮ファイルc07files.zipにまとめた。ダウンロード展開して自由に利用されたい。

リスト1のスクリプトPCA.pyを実行すると、入力データファイル名の入力が求められる。

 

データファイル(*.xlsx) =

 

入力データファイルは、Excelファイルの形式で用意する。図1に例を示す。

図1

 

1行目に変数名を設定する。変数値は、2行目以降に書く。1列目は、各データの識別値である。主成分分析の対象となる変数は2列目以降である。

入力データ名として、例えば、図1のExcelデータ「科目データ.xlsx」を次のように設定する。

 

データファイル(*.xlsx) = 科目データ.xlsx

 

入力データ名を設定して、Enterキーを押すと、次のスクリプトでExcelファイルの内容がdataに読み込まれる。

 

in_fl_nm = input('データファイル(*.xlsx) = ')

with pd.ExcelFile(in_fl_nm) as f:

    data = pd.read_excel(f)

 

dataに読み込まれた内容から、主成分分析の対象となるデータ値が次のスクリプトによりXに取り出される。

 

X = data.values[:,1:]

X = np.array(X, dtype='float')      #   型をfloatに明示的設定

                                    #   Excelファイルの第1列目の値が

                                    #   文字列型のときに必要

 

Xは次のコードによりZに標準化される。

 

Z = ss.zscore(X)

 

標準化得点Zに対して、拙著p.117の式に基づき、次のコードのように特異値分解が行われる。

 

U, Lmbd, Vh = np.linalg.svd(Z/(n**0.5), full_matrices = False)

 

特異値分解が終わると、特異値のグラフが図2のように表示される。

図2

 

グラフは、保存ボタンをクリックするとファイルに保存することができる。

右上の閉じるボタンをクリックすると、フォームは閉じられて、主成分分析において求める主成分の数の入力が求められる。

 

                        Lambda        Cum_Sqr              %

       Lambda-1        1.83432        3.36473       56.07889

       Lambda-2        1.40444        5.33718       88.95305

       Lambda-3        0.53507        5.62349       93.72475

       Lambda-4        0.46458        5.83932       97.32205

       Lambda-5        0.31091        5.93599       98.93309

       Lambda-6        0.25301        6.00000      100.00000

 

Number of components =

 

主成分の数を図2のグラフ、あるいは端末に表示されている特異値Lambdaの表から選ぶ。例えば、上の例の場合、主成分数を2とする場合は、次のように設定する。

 

Number of components = 2

 

主成分数を設定すると、それに基づいて、まず成分パターンのマップの描画が提示されるが、その際の横軸(X軸)の表す成分の指定が求められる。

 

xdim =

 

横軸として第1成分を指定するときは、次のように入力する。

 

xdim = 1

 

横軸の表す成分の指定を上のように入力すると、次は縦軸(Y軸)の表す成分の指定が求められる。

 

xdim = 1

ydim =

 

次のように、第2成分を指定してみる。

 

xdim = 1

ydim = 2

 

縦軸(Y軸)の表す成分が入力されると、パターン図が表示される(図3)。

図3

 

図3のフォームを閉じると、次の描画における横軸(X軸)の表す成分を聞いてくる。

 

xdim = 1

ydim = 2

 

Set the component number (from 1 to 2) to plot the pattern.

If you do not want to plot the pattern, set the number less than 1.

xdim =

 

横軸の成分を設定すると、次に縦軸の成分を聞いてくるが、横軸の成分として1より小さい整数を設定すると、主成分分析の初期解の処理は終わり、次にバリマックス回転に進む。

バリマックス回転が終了すると、回転後の成分パターンの描画における横軸の成分を聞いてくる。

 

xdim =

 

横軸の成分を設定すると、次に縦軸の成分を聞いてくるので、設定する。

 

xdim = 1

ydim = 2

 

縦軸の成分を設定すると、指定した成分によるパターンの図が表示される(図4)。

図4

 

図4のフォームを閉じると、次のパターンの図で用いる横軸の成分を聞いてくる。

 

xdim =

 

描画する成分の組み合わせを設定すると、その成分でのパターンの図が描画される。1より小さい整数を設定すると、バリマックス回転後の処理は終了する。

続いて、プロマックス回転が行われるが、斜交軸のため直交座標を前提とするパターンの描画は行われない。

プログラムは、次のメッセージの表示で終了する。

 

Results.txt was saved.

 

保存されたファイルを開いてみる。

ファイルを開くとき、図5のダイアログボックスが表示されることがある。

図5

 

これは、出力ファイルにUTF-8以外の文字コードが含まれるときに出される。Excelファイルの日本語コードはs-jisである。図5のようにs-jisを指定すると開くことができる。

出力ファイルResults.txtを開くと、以下のようになっている。

 

 

Data = 科目データ.xlsx

 

var_names

['データID', '国語', '英語', '歴史', '数学', '物理', '科学']

X =

[['生徒1' 48 46 60 47 68 44]

 ['生徒2' 54 49 63 61 49 45]

 ['生徒3' 48 55 47 49 49 47]

   ・

   ・

   ・

['生徒18' 62 73 63 60 64 67]

 ['生徒19' 66 60 61 64 43 63]

 ['生徒20' 70 66 71 50 55 52]]

n_data = 20

n_vars = 6

 

                        Lambda        Cum_Sqr              %

       Lambda-1        1.83432        3.36473       56.07889

       Lambda-2        1.40444        5.33718       88.95305

       Lambda-3        0.53507        5.62349       93.72475

       Lambda-4        0.46458        5.83932       97.32205

       Lambda-5        0.31091        5.93599       98.93309

       Lambda-6        0.25301        6.00000      100.00000

 

パターン行列

                        comp-1         comp-2

             国語        0.75184        0.61221

             英語        0.81468        0.43846

             歴史        0.78026        0.54381

             数学        0.80603       -0.44283

             物理        0.59683       -0.71379

             科学        0.72185       -0.63568

 

主成分

             ID         comp-1         comp-2

            生徒1       -1.14263       -0.31126

            生徒2       -0.85614        0.13922

            生徒3       -1.39156       -0.16393

       ・

       ・

       ・

           生徒19       -0.25673        0.31686

           生徒20       -0.11365        0.95938

 

 

バリマックス回転

 

パターン行列(バリマックス回転)

                        comp-1         comp-2

             国語        0.96874       -0.04003

             英語        0.90061       -0.21177

             歴史        0.94468       -0.11008

             数学        0.30993       -0.86587

             物理       -0.02632       -0.93005

             科学        0.11907       -0.95445

 

パターン行列(整列)(バリマックス回転)

                        comp-1         comp-2

             国語        0.96874       -0.04003

             英語        0.94468       -0.11008

             歴史        0.90061       -0.21177

             数学        0.11907       -0.95445

             物理       -0.02632       -0.93005

             科学        0.30993       -0.86587

 

成分(バリマックス回転)

             ID         comp-1         comp-2

            生徒1       -1.06183        0.52441

            生徒2       -0.54871        0.67176

            生徒3       -1.15054        0.79973

       ・

       ・

       ・

           生徒19        0.01783        0.40742

           生徒20        0.55088        0.79363

 

パターン行列(プロマックス回転)

                        comp-1         comp-2

             国語        0.98905        0.08941

             英語        0.89541       -0.09616

             歴史        0.95468        0.01422

             数学        0.19873       -0.84757

             物理       -0.15534       -0.95880

             科学       -0.00944       -0.96427

 

パターン行列(整列)(プロマックス回転)

                        comp-1         comp-2

             国語        0.98905        0.08941

             英語        0.95468        0.01422

             歴史        0.89541       -0.09616

             数学       -0.00944       -0.96427

             物理       -0.15534       -0.95880

             科学        0.19873       -0.84757

 

 

因子間相関行列...

              comp.1    comp.2

    comp.1   1.00000  -0.26097

    comp.2  -0.26097   1.00000

 

成分(プロマックス回転)

             ID         comp-1         comp-2

            生徒1       -1.12102        0.66116

            生徒2       -0.63142        0.73886

            生徒3       -1.24479        0.94585

       ・

       ・

       ・

           生徒19       -0.03532        0.40142

           生徒20        0.44297        0.71319

 

 

主成分分析を正射影の観点から説明するものとして、次の文献がある。

Deisenroth, M. P., Faisal, A. A., & Ong, C. S. (2020). Mathematics for machine learning. Cambridge University Press.p.296に正射影であることが明記されている)

Okamoto,Y. (2006). A justification of rotation in principal component analysis: Projective viewpoint of PCA. Japan Women’s University Journal: Faculty of Integrated Arts and Social Sciences Journal,17, 59-71.

 

 

附記:正射影による主成分分析における2つの目的関数の等価について

 

Deisenroth(2020における正射影による主成分分析の目的関数は

 

 

で与えられている。これを、Okamoto (2006)における記法に合わせて書けば

 

 

となる。は標準化得点であり、は正射影を表す。Deisenrothら(2020)は、目的関数(A.1)を最小化する正射影を求めている(p. 295)。

Okamoto (2006)は、正射影の目的関数を

 

 

と設定している。ただし、データ数を表すは(A.1)に合わせて大文字とした。Okamoto (2006)は、目的関数を最大化する正射影を求めている。

いま、次式が成り立つ。

 

 

したがって、

 

 

が成り立つ。すなわち、Deisenrothら(2020)の目的関数の最小化とOkamoto (2006)の目的関数の最大化は等価である。

 

 

リスト1 主成分分析(PCA.py

 

#

#               主成分分析と回転

#

import pandas as pd

import numpy as np

import scipy.stats as ss

import matplotlib.pyplot as plt

import japanize_matplotlib

from rotate import Varimax, Promax

from PlotComp import PlotPattern

from ArrangePat import ArrangePtn

 

in_fl_nm = input('データファイル(*.xlsx) = ')

with pd.ExcelFile(in_fl_nm) as f:

    data = pd.read_excel(f)

 

f_out = open('Results.txt', 'w')

   

print('data...\n', data)

print('keys...',[k for k in data.keys()])

 

f_out.write(f'\nData = {in_fl_nm}\n')

 

print(data.values)

var_names = [v for v in data.keys()]

print('var_names', var_names)

f_out.write('\nvar_names\n')

f_out.write(f'{var_names}\n')

f_out.write(f'X =\n{data.values}')

print('data.values\n', data.values)

X = data.values[:,1:]

X = np.array(X, dtype='float')      #   型をfloatに明示的設定

                                    #   Excelファイルの第1列目の値が

                                    #   文字列型のときに必要

print('X =\n', X)

n, s = np.shape(X)

print('n =', n, '   s =', s)

Z = ss.zscore(X)

print('Z =\n', Z)

#

#          拙著、p.117

#

U, Lmbd, Vh = np.linalg.svd(Z/(n**0.5), full_matrices = False)

print('U =\n', U[:10])

print('Lmbd =', Lmbd)

print('Vh =\n', Vh)

 

n_data = n

n_vars = s

CaseID = data.values[:,0]

print(CaseID)

 

f_out.write(f'\nn_data = {n_data}\nn_vars = {n_vars}\n')

 

p = len(Lmbd)

cumsqrLmbd = np.cumsum(Lmbd**2)

cumpercent = (cumsqrLmbd / cumsqrLmbd[-1])*100

print(f'{" ":>15s}{"Lambda":>15s}{"Cum_Sqr":>15s}{"%":>15s}')

for i in range(p):

    str = f'Lambda-{i+1}'

    print(f'{str:>15s}{Lmbd[i]:>15.5f}{cumsqrLmbd[i]:>15.5f}', end = '')

    print(f'{cumpercent[i]:>15.5f}')

 

f_out.write(f'\n{" ":>15s}{"Lambda":>15s}{"Cum_Sqr":>15s}{"%":>15s}\n')

for i in range(p):

    str = f'Lambda-{i+1}'

    f_out.write(f'{str:>15s}{Lmbd[i]:>15.5f}{cumsqrLmbd[i]:>15.5f}')

    f_out.write(f'{cumpercent[i]:>15.5f}\n')

 

plt.plot(range(p), Lmbd)

plt.xticks(range(p), [v+1 for v in range(p)])

plt.ylabel('特異値', fontsize = 16)

plt.show()

 

n_comp = int(input('\nNumber of components = '))

if n_comp > n_vars:

    n_comp = n_vars

if n_comp < 1:

    n_comp = 1

if n_comp > p:

    n_comp = p

 

U1 = U[:,:n_comp]

L1 = np.diag(Lmbd[:n_comp])

V1 = Vh[:n_comp].T

 

Pat = V1 @ L1

print('\nPattern...\n', Pat)

 

f_out.write('\nパターン行列\n')

f_out.write(f'{" ":>15s}')

for i in range(n_comp):

    str_v = f'comp-{i+1}'

    f_out.write(f'{str_v:>15s}')

f_out.write('\n')

for j in range(n_vars):

    f_out.write(f'{var_names[j+1]:>15s}')

    for i in range(n_comp):

        f_out.write(f'{Pat[j][i]:>15.5f}')

    f_out.write('\n')

           

 

PComp = U1 * (n_data**0.5)

print('\nComponents...\n', PComp)

f_out.write('\n主成分\n')

f_out.write(f'{"ID":>15s}')

for i in range(n_comp):

    str_v = f'comp-{i+1}'

    f_out.write(f'{str_v:>15s}')

f_out.write('\n')

for j in range(n_data):

    f_out.write(f'{CaseID[j]:>15}')

    for i in range(n_comp):

        f_out.write(f'{PComp[j][i]:>15.5f}')

    f_out.write('\n')

 

PlotPtn = PlotPattern( Pat, var_names, n_vars, n_comp,

                       " ...主成分パターン" )

while True:

    print("\nSet the component number (from 1 to %d) to plot the pattern."%n_comp)

    print("If you do not want to plot the pattern, set the number less than 1.")

    xdim = int(input("xdim = "))

    if xdim < 1:

        break

    ydim = int(input("ydim = "))

    PlotPtn.Plot(xdim, ydim)

 

 

f_out.write('\n\nバリマックス回転\n')

 

rot = Varimax(Pat, n_vars, n_comp)

PatV = rot.rotateV()

print('PatV...\n', PatV)

 

f_out.write('\nパターン行列(バリマックス回転)\n')

f_out.write(f'{" ":>15s}')

for i in range(n_comp):

    str_v = f'comp-{i+1}'

    f_out.write(f'{str_v:>15s}')

f_out.write('\n')

for j in range(n_vars):

    f_out.write(f'{var_names[j+1]:>15s}')

    for i in range(n_comp):

        f_out.write(f'{PatV[j][i]:>15.5f}')

    f_out.write('\n')

           

ArgPtn = ArrangePtn(var_names, PatV, n_vars, n_comp)

PtnArgd = ArgPtn.arrange()

print('\nPtnArgd...\n')

for v in PtnArgd:

    print(v)

 

f_out.write('\nパターン行列(整列)(バリマックス回転)\n')

f_out.write(f'{" ":>15s}')

for i in range(n_comp):

    str_v = f'comp-{i+1}'

    f_out.write(f'{str_v:>15s}')

f_out.write('\n')

for j in range(n_vars):

    f_out.write(f'{var_names[j+1]:>15s}')

    for i in range(n_comp):

        f_out.write(f'{PtnArgd[j][1][i]:>15.5f}')

    f_out.write('\n')

#

#           拙著、p.118     

#

PCompV = PComp @ Pat.transpose() @ PatV @ np.linalg.inv(PatV.transpose() @ PatV)

 

print('\nPCompV...\n', PCompV)

f_out.write('\n成分(バリマックス回転)\n')

f_out.write(f'{"ID":>15s}')

for i in range(n_comp):

    str_v = f'comp-{i+1}'

    f_out.write(f'{str_v:>15s}')

f_out.write('\n')

for j in range(n_data):

    f_out.write(f'{CaseID[j]:>15}')

    for i in range(n_comp):

        f_out.write(f'{PCompV[j][i]:>15.5f}')

    f_out.write('\n')

 

PlotPtn = PlotPattern( PatV, var_names, n_vars, n_comp,

                       " ...バリマックス回転後パターン" )

while True:

    print("\nSet the component number (from 1 to %d) to plot the pattern for the Varimax criterion."%n_comp)

    print("If you do not want to plot the pattern, set the number less than 1.")

    xdim = int(input("xdim = "))

    if xdim < 1:

        break

    ydim = int(input("ydim = "))

    PlotPtn.Plot(xdim, ydim)

 

 

#    Promax

 

obrot = Promax(PatV, n_vars, n_comp, 4.0)

Patob, Phi = obrot.rotateP();

 

print('\nPattern Promax...\n', Patob)

 

print('\nCorr...\n', Phi)

 

ArgPtn = ArrangePtn(var_names, Patob, n_vars, n_comp)

PtnArgd = ArgPtn.arrange()

print('\nPtnArgd...')

for v in PtnArgd:

    print(v)

#

#           拙著、p.118     

#

PCompob = PComp @ Pat.transpose() @ Patob @ np.linalg.inv(Patob.transpose() @ Patob)

print('\nPCompob...\n', PCompob)

 

f_out.write('\nパターン行列(プロマックス回転)\n')

f_out.write(f'{" ":>15s}')

for i in range(n_comp):

    str_v = f'comp-{i+1}'

    f_out.write(f'{str_v:>15s}')

f_out.write('\n')

for j in range(n_vars):

    f_out.write(f'{var_names[j+1]:>15s}')

    for i in range(n_comp):

        f_out.write(f'{Patob[j][i]:>15.5f}')

    f_out.write('\n')

           

f_out.write('\nパターン行列(整列)(プロマックス回転)\n')

f_out.write(f'{" ":>15s}')

for i in range(n_comp):

    str_v = f'comp-{i+1}'

    f_out.write(f'{str_v:>15s}')

f_out.write('\n')

for j in range(n_vars):

    f_out.write(f'{var_names[j+1]:>15s}')

    for i in range(n_comp):

        f_out.write(f'{PtnArgd[j][1][i]:>15.5f}')

    f_out.write('\n')

 

f_out.write("\n\n因子間相関行列...\n")

f_out.write("%10s"%" ")

for j in range(0, n_comp):

    f_out.write("%10s"%("comp.%d"%(j + 1)))

f_out.write("\n")

for i in range(0, n_comp):

    f_out.write("%10s"%("comp.%d"%(i + 1)))

    for j in range(0, n_comp):

        f_out.write("%10.5f"%Phi[i, j])

    f_out.write("\n")

 

f_out.write('\n成分(プロマックス回転)\n')

f_out.write(f'{"ID":>15s}')

for i in range(n_comp):

    str_v = f'comp-{i+1}'

    f_out.write(f'{str_v:>15s}')

f_out.write('\n')

for j in range(n_data):

    f_out.write(f'{CaseID[j]:>15}')

    for i in range(n_comp):

        f_out.write(f'{PCompob[j][i]:>15.5f}')

    f_out.write('\n')

 

f_out.close()

print('\nResults.txt was saved.\n')

 

 

 

リスト2 パターン描画(PlotComp.py

 

import matplotlib.pyplot as mpt

import japanize_matplotlib

 

 

class PlotPattern:

    """

            Plot the scattergram of the factor pattern

    """

    def __init__(self, Patn, var_names, n_var, n_comp, msg):

        self.Patn = Patn

        self.var_names = var_names

        self.n_var = n_var

        self.n_comp = n_comp

        self.msg = msg

 

 

 

    def Plot(self, xdim, ydim):

        if (xdim < 1):

            xdim = 1

        if (xdim > self.n_comp):

            xdim = self.n_comp

        if (ydim < 1):

            ydim = 1

        if (ydim > self.n_comp):

            ydim = self.n_comp

 

        xcoord = []

        ycoord = []

        for i in range(0, self.n_var):

            xcoord.append(self.Patn[i, xdim - 1])

            ycoord.append(self.Patn[i, ydim - 1])

 

        mpt.figure(figsize=(7,7))

        mpt.axis([-1.2, 1.2, -1.2, 1.2])

        mpt.plot(xcoord, ycoord, 'bo')

        mpt.title("X軸:成分ー%d   Y軸:成分ー%d)"%(xdim, ydim) + self.msg)

        mpt.xticks([-1.0, 0.0, 1.0],[r'$-1.0$', r'$0.0$', r'$1.0$'])

        mpt.yticks([-1.0, 0.0, 1.0],[r'$-1.0$', r'$0.0$', r'$1.0$'])

        #mpt.xlabel(f'comp.{xdim}')

        #mpt.ylabel(f'comp.{ydim}')

 

        for i in range(0, self.n_var):

            mpt.text(self.Patn[i, xdim - 1] + 0.015, self.Patn[i, ydim - 1] + 0.015, self.var_names[i + 1])

 

        ax = mpt.gca()

        ax.spines['right'].set_color('none')

        ax.spines['top'].set_color('none')

        ax.xaxis.set_ticks_position('bottom')

        ax.spines['bottom'].set_position(('data', 0))

        ax.yaxis.set_ticks_position('left')

        ax.spines['left'].set_position(('data',0))

       

        mpt.show()

 

 

 

リスト3 回転(rotate.py

 

import numpy

import math

#import mymodule as mm

 

class Varimax:

    """

                 Varima rotation

    """

    def __init__(self, X, vn, vp):

        if (len(X) != vn):

            raise "Invalid value for n in Varimax"

        else:

            self.n = vn

        if ((numpy.size(X) / len(X)) != vp):

            raise "Invalid value for p in Varimax"

        else:

            self.p = vp

 

        tempA = []

        for i in range(0, self.n):

            tempA.append([])

            for j in range(0, self.p):

                tempA[i].append(X[i,j])

        self.A = numpy.matrix(tempA)

 

        if vp > 1:

            self.h = []

            for i in range(0, self.n):

                sum = 0.0

                for j in range(0, self.p):

                    sum += (self.A[i, j])**2

                self.h.append(math.sqrt(sum))

                for j in range(0, self.p):

                    self.A[i, j] /= self.h[i]

 

 

 

    def rotateV(self):

        if (self.p < 2):

            return self.A

        while True:

            ckA = []

            for i in range(0, self.n):

                ckA.append([])

                for j in range(0, self.p):

                    ckA[i].append(self.A[i, j])

                   

            for i in range(0, self.p):

                for j in range(i + 1, self.p):

                    x = []

                    y = []

                    for k in range(0, self.n):

                        x.append(self.A[k, i])

                        y.append(self.A[k, j])

                    u = []

                    v = []

                    for k in range(0, self.n):

                        u.append((x[k]**2) - (y[k]**2))

                        v.append(2.0 * x[k] * y[k])

                    cA = 0.0

                    cB = 0.0

                    cC = 0.0

                    cD = 0.0

                    for k in range(0, self.n):

                        cA += u[k]

                        cB += v[k]

                        cC += (u[k]**2) - (v[k]**2)

                        cD += 2.0 * u[k] * v[k]

                    num = cD - 2 * cA * cB / self.n

                    den = cC - ((cA**2) - (cB**2)) /self.n

                    theta4 = math.atan(num / den)

                    if (num > 0.0):

                        if (theta4 < 0.0):

                            theta4 += math.pi

                    else:

                        if (theta4 > 0.0):

                            theta4 += math.pi

                    theta = theta4 / 4.0

                    for k in range(0, self.n):

                        tx = self.A[k, i] * math.cos(theta) + self.A[k, j] * math.sin(theta)

                        ty = -self.A[k, i] * math.sin(theta) + self.A[k, j] * math.cos(theta)

                        self.A[k, i] = tx

                        self.A[k, j] = ty

 

            dif = 0.0

            for i in range(0, self.n):

                for k in range(0, self.p):

                    dif += (ckA[i][k] - self.A[i, k])**2

            if (dif < 1.0e-9):

                for i in range(0, self.n):

                    for k in range(0, self.p):

                        self.A[i, k] *= self.h[i]

                break

          

        return numpy.array(self.A)

 

 

def sgn( a ):

    if a > 0.0:

        return 1.0

    elif a < 0.0:

        return -1.0

    else:

        return 0.0

 

 

class Promax:

    """

              Promax rotation

    """

    def __init__(self, V, n_vars, n_comp, gmma):

        tempA = []

        for i in range(0, n_vars):

            tempA.append([])

            for j in range(0, n_comp):

                tempA[i].append(V[i, j])

        self.A = numpy.matrix(tempA)

        self.n = n_vars

        self.p = n_comp

        self.gmma = gmma

 

        ua = []

        for i in range(0, n_vars):

            ua.append([])

            v2 = 0.0

            for k in range(0, n_comp):

                v2 += self.A[i, k]**2

            for k in range(0, n_comp):

                ua[i].append(self.A[i, k] / (v2**0.5))

               

        mxu = []

        for i in range(0, n_comp):

            tv = 0.0

            for k in range(0, n_vars):

                if tv < abs(ua[k][i]):

                    tv = abs(ua[k][i])

            mxu.append(tv)

        u = []

        for i in range(0, n_vars):

            u.append([])

            for j in range(0, n_comp):

                u[i].append(ua[i][j] / mxu[j])

        cc = []

        for i in range(0, n_vars):

            cc.append([])

            for j in range(0, n_comp):

                cc[i].append(sgn(self.A[i, j]) * math.pow(abs(u[i][j]), self.gmma))

        self.C = numpy.matrix(cc)

 

    def rotateP(self):

        ApA = numpy.transpose(self.A) * self.A

        ApAinv = numpy.linalg.inv(ApA)

        Q = ApAinv * numpy.transpose(self.A) * self.C

        QpQinv = numpy.linalg.inv(numpy.transpose(Q) * Q)

        dD = []

        for i in range(0, self.p):

            dD.append([])

            for j in range(0, self.p):

                if j == i:

                    dD[i].append(math.sqrt(QpQinv[j, j]))

                else:

                    dD[i].append(0.0)

        D = numpy.matrix(dD)

 

        Lmbd = Q * D

 

        ALmbd = self.A * Lmbd

 

        Phi = numpy.linalg.inv(numpy.transpose(Lmbd) * Lmbd)

 

        return numpy.array(ALmbd), Phi

 

 

 

リスト4 パターンの整列(ArrangePat.py

 

class ArrangePtn:

    """

            Reordering of the rows of the factor pattern

            so that similar varibles come together

    """

    def __init__(self, var_names, Pattern, n_vars, n_comp):

        self.names = var_names

        self.Pttn = Pattern

        self.n_vars = n_vars

        self.n_comp = n_comp

        self.NamePttn = []

        for i in range(0, self.n_vars):

            self.NamePttn.append([])

            self.NamePttn[i].append(var_names[i + 1])

            self.NamePttn[i].append([])

            for j in range(0, self.n_comp):

                self.NamePttn[i][1].append(Pattern[i, j])

 

    def check(self, a, b):

        ta = 0

        for i in range(0, self.n_comp):

            if (abs(self.NamePttn[a][1][i]) > abs(self.NamePttn[a][1][ta])):

                ta = i

        tb = 0

        for i in range(0, self.n_comp):

            if (abs(self.NamePttn[b][1][i]) > abs(self.NamePttn[b][1][tb])):

                tb = i

        if (tb < ta):

            return True

        elif (tb == ta):

            if (abs(self.NamePttn[b][1][tb]) > abs(self.NamePttn[a][1][ta])):

                return True

            else:

                return False

        else:

            return False

           

 

    def arrange(self):

 

        for i in range(0, self.n_vars -1):

            k = i

            for j in range(i + 1, self.n_vars):

                if self.check(k, j):

                    k = j

            if (i < k):

                tmp = self.NamePttn[i]

                self.NamePttn[i] = self.NamePttn[k]

                self.NamePttn[k] = tmp

 

        return self.NamePttn

 

 

 

 

Home