拙著「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に正射影であることが明記されている)
附記:正射影による主成分分析における2つの目的関数の等価について
Deisenrothら(2020)における正射影による主成分分析の目的関数は
で与えられている。これを、Okamoto (2006)における記法に合わせて書けば
となる。は標準化得点であり、は正射影を表す。Deisenrothら(2020)は、目的関数(A.1)を最小化する正射影を求めている(p. 295)。
Okamoto (2006)は、正射影の目的関数を
と設定している。ただし、データ数を表すは(A.1)に合わせて大文字とした。Okamoto (2006)は、目的関数を最大化する正射影を求めている。
いま、次式が成り立つ。
したがって、
が成り立つ。すなわち、Deisenrothら(2020)の目的関数の最小化とOkamoto (2006)の目的関数の最大化は等価である。
#
#
主成分分析と回転
#
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')
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()
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
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