๖qชอ
ผฺลฌQๆ@
@๖qชออA๖qฦขค๖ฯฬPฎษๆมฤf[^iฯสj
ฬฯฎ๐เพท้fล ่AฎiPj
iPj
ษๆมฤ\ํณ๊้Bฝญฬ๐@ช๑ฤณ๊ฤข้ชAลฌQๆ@ฬ๎ษๆ่AผฺA๖qืs๑๐฿้๛@iช{A2014App.95-97j๐ศบษฝB
ผฺลฌQๆ@อAคสซicommunalityjชPๆ่ๅซญศ้ฦขคwCEbhP[XชณญA๖qพ_เผฺ฿็๊้B
๊สษAs๑ฬANฬs๑ษๆ้ลฌ2ๆ฿อAมูlช๐ฬมูlชๅซขเฬฉ็
ยฦมฝเฬล^ฆ็๊้Bฑ๊อGbJ[gEOฬ่iEckart and Young, 1936jฦฤฮ๊ฤข้ชAป๊ๆ่ศOษญ\ณ๊ฤข้(e.g. Schmidt, 1906)ฦGifi
(1990), p.518อเพตฤข้B
ขAฎiPjฬถำf[^อWพ_ปณ๊ฤข้ฦตAปฬมูช๐๐
ฦจญBฑฬฦซANฬลฌQๆ฿อAมูlฬๅซขเฬฉ็
ย๐I๑ล
ล^ฆ็๊้BฎiQjฦฎiPj๐ไืA๖qชฝฯ0AชU1ฬWปพ_ล ้ฑฦษำท้ฦ
ล^ฆ็๊้ฑฦชํฉ้BฑฑลAอf[^ล ้BฝA
ๆ่A
ล ้B
ๅฌชชอลเ`ฎอฏถฎชgํ๊้ชAๅฌชชอฬ๊อAf[^ฬณหeษๆ้ณkล ้ฬษฮตฤAใLiRjอf[^ษฮท้๖qfiPjษๆ้๖qพ_ฦ๖qืฬ่lล ้Bf[^๐๘ฆๆญณkตฝเฬiๅฌชชอjฦf[^๐ๆญ\ท่li๖qชอjชlฦตฤ๊vท้ฑฦอฉRศฑฦล ้ฦพฆๆคB
ฎiPjๆ่Aฎ๐พ้B
ผำฬih,hjฌชษฺตฤAฎ๐พ้B
ฑฑลA
ๆ่A
ชฑฉ๊้BทศํฟAคสซอP๐ดฆ้ฑฦอศขB
ณฅs๑ษฮตฤAฎชฌ่งยB
ฑฬอA๑]ฦฤฮ๊ฤข้B
ผฺลฌ2ๆ@ฬXNvg๐XgPฬๆคษ์ฌตฤฝBt@CอAฦ฿ฤณkt@Cfa_direct_files.zipฦตฝB
อf[^t@CอAExcelt@Cฦตฤ}Pa,bฬๆคษpำท้B}Pa,bฬf[^อAช{i2014jA\5.1.1๐อตฝเฬล ้B
}Pa
}Pb
Psฺษฯผ๐่ท้BP๑ฺอAP[XIDฬิ๐่ท้BP[XIDฬิอAฎล ๊ฮCำล ่Aธลศญฤเ_ศลเๆขชA๖qพ_ฬoอษจขฤpข็๊้ชAชอษอpข็๊ศขBQ๑ฺศ~ษAf[^l๐่ท้B
XgPฬXNvg๐ภsท้ฦAอf[^t@Cผ๐ทขฤญ้BฬแลอA}Pฬf[^t@CผData6Subj100.xlsxช่ณ๊ฤข้Bอf[^t@CอAXNvgt@CฦฏถtH_เษ ้เฬฦท้B
Input file name(*.xlsx) =
Data6Subj100.xlsx
Output file name(*.txt) = Results.txt
อf[^t@Cผ๐่ท้ฦAoอt@Cผฬ่ช฿็๊้BKศeLXgt@Cผ๐่ท้BใฬแลอAResults.txtช่ณ๊ฤข้Boอt@CอAXNvgฦฏถtH_เษถณ๊้B
oอeLXgt@Cผ๐่ท้ฦAvZชn่Aึs๑ฬลLlฬXN[vbgช\ฆณ๊้i}QjB
}Q
}Qฬ๊A๖qอQชKล ้ฦปfณ๊้B
}QฬWindow๐ยถ้ฦA๖qqฬlฬ่ชuq = vฦ฿็๊้i}RjB
}R
}RลอAQช่ณ๊ฤข้B
๖qq๐่ตฤAEnterL[๐ทฦAผฺลฌ2ๆ@ษๆ้vZชn้B
vZชIนท้ฦA๑]Oฬ๖qืสAฬlฬzuช๚lฦตฤ\ฆณ๊้i}SjB
}S
}SฬWindow๐ยถ้ฦAษ\ฆท้zuฬกฒiXฒjฬ\ท๖qฬw่ช฿็๊้i}TjB
}T
๖qฦตฤOศบฬฎl๐่ท้ฦA๚lษๆ้zuฬ\ฆชIนท้B
zuษ\ฆท้๖qฦตฤOศบฬฎl๐่ตฤA๚lษๆ้zuฬ\ฆ๐Iนท้ฦAษo}bNX๑]ษๆ้ผ๐๑]ชsํ๊้B
o}bNX๑]อAฬ๎๐ลฌปท้เฬฦตฤAซงER{i2024jAp.137ฬASYษๆ่sมฝiXgQjB
o}bNX๑]ใฬzuอA}Uฬๆคษ\ฆณ๊้B
}U
}UฬWindow๐ยถ้ฦAฬzuฬ\ฆษpข้กฒฬ\ท๖qฬ่ช฿็๊้B
๖qฦตฤOศบฬฎl๐่ท้ฦAo}bNX๑]ใฬzuฬ\ฆอIนท้B
ษAฮ๐๑]ฦตฤR[eB~๑]ชsํ๊้B
R[eB~๎อ
ล^ฆ็๊AซงER{i2024jAp.140ฬASY๐QlษตฤXgQษฆทXNvg๐pำตฝB
ฮ๐๑]ชIนท้ฦAXNvgฬภsIนล ้i}VjB
}V
๑]Oฬ๚๐ฬ๖qพ_ชAfi.csvษAo}bNX๑]ใฬ๖qพ_ชfv.csvษAR[eB~๑]ใฬ๖qพ_ชfq.csvษถณ๊ฤข้ฑฦชฆณ๊ฤข้Bฑ๊็ฬCSVt@CอAExcelลJญฑฦชลซ้BExcelลJฉ๊ฝCSVt@CอAgฃq๐.xlsxษฯXตฤExcelt@Cฦตฤถท้ฑฦชลซ้B
ภsIนใAoอt@CResults.txt๐JญฦAศบฬๆคล ้B
Input fie = Data6Subj100.xlsx.
var_names =
['Jpn' 'Eng' 'Hist' 'Math' 'Phys'
'Chem']
1: [48 46 60 47 68 44]
2: [54 49 63 61 49 45]
3: [48 55 47 49 49 47]
E
E
E
98: [84 84 96 69 60 69]
99: [39 51 39 59 60 65]
100: [47 45 60 68 72 70]
mean sd
Jpn
58.750 15.213
Eng
59.310 15.591
Hist
59.310 15.059
Math
60.520 13.056
Phys
60.090 13.287
Chem
58.940 13.981
R =
Jpn
Eng
Hist
Math
Phys
Chem
Jpn 1.00000 0.84066 0.87327 0.23810 0.19741 0.29807
Eng 0.84066 1.00000 0.82001 0.20751 0.12885 0.24563
Hist 0.87327 0.82001 1.00000 0.27644 0.20387 0.24637
Math 0.23810 0.20751 0.27644 1.00000 0.60998 0.67641
Phys 0.19741 0.12885 0.20387 0.60998 1.00000 0.84128
Chem 0.29807 0.24563 0.24637 0.67641 0.84128 1.00000
Eigen values of R
Cum.Sum
Cum.Prop(%)
1
3.25276
3.25276
54.21
2
1.86791
5.12067
85.34
3
0.42494
5.54561
92.43
4
0.20646
5.75207
95.87
5
0.14753
5.89960
98.33
6
0.10040
6.00000
100.00
Before rotation
Factor-1 Factor-2
Communalitites
Jpn
0.82210
0.48694
0.91297
Eng
0.77575
0.52727
0.87981
Hist
0.81441
0.48464
0.89813
Math
0.64182
-0.53731
0.70064
Phys
0.62907
-0.67123
0.84628
Chem
0.71006
-0.61535
0.88285
Varimax rotation
Factor-1 Factor-2 Communalities
Jpn
0.94506 -0.14083
0.91297
Hist
0.93763 -0.13776
0.89813
Eng
0.93454 -0.08029
0.87981
Chem
0.16272 -0.92540
0.88285
Phys
0.06463 -0.91766
0.84628
Math
0.15901 -0.82180
0.70064
Contri
2.702
2.419
Quartimin rotation
Correlation between factors...
Factor-1 Factor-2
comp.1 1.00000 -0.26029
comp.2 -0.26029 1.00000
Factor loadings
Factor-1 Factor-2
Jpn
0.94954 -0.02195
Eng
0.94735
0.03888
Hist
0.94236 -0.01976
Phys
-0.06404 -0.93452
Chem
0.03549 -0.92974
Math
0.04640 -0.82376
Structure matrix
Factor-1 Factor-2
Jpn
0.95526 -0.26911
Hist
0.94751 -0.26505
Eng
0.93723 -0.20770
Chem
0.27749 -0.93897
Phys
0.17921 -0.91785
Math
0.26082 -0.83584
ซง_ฝER{ฯถi2024jๅฌชชอฦ๖qชอFมูlช๐๐oญ_ฦตฤDคงoล
Gifi, A. (1990). Nonlinear multivariate
analysis. John Wiley & Sons.
ช{ภฐi2019jขณ็ทฏศขPythonลf[^ชอFฝฯส๐อAxCYvชอDPoล
ช{ภฐi2014jSwf[^ชอฦช่Ff[^ฬฉ๛ฦSฬช่๛Dค[
XgP@ผฺลฌ2ๆ@ฬXNvgifa_direct_main.pyj
import scipy.stats as ss
import pandas as pd
import numpy as np
from mymodule import * # arrng_pttn, draw_map,
from rotate import * # Varimax_Orthomax,
Oblique_Quartimin
fin_nm = input('Input file
name(*.xlsx) = ')
df_data = pd.read_excel(fin_nm)
# Excelt@Cฬว
fout_nm = input('Output file
name(*.txt) = ')
fout = open(fout_nm, 'w')
# oอpeLXgt@CฬI[v
fout.write(f'Input fie = {fin_nm}.\n')
var_names = np.array(df_data.keys())
caseIDs = np.array(df_data[var_names[0]])
var_names = var_names[1:]
# ฯผXg
print('var_names =\n', var_names)
fout.write(f'var_names
=\n{var_names}\n\n')
N = len(caseIDs)
print('n =', len(caseIDs))
X =
np.array(df_data.values)[:,1:]
# ฯlฬz๑is๑j
for i, v in zip(caseIDs, X):
print(i, v)
fout.write(f'{i}: {v}\n')
means = np.mean(X, axis=0)
sds = np.std(X, axis=0)
print()
print(f'{"
":10s}{"mean":>10s}{"sd":>10s}')
fout.write(f'\n\n{"
":10s}{"mean":>10s}{"sd":>10s}\n')
for i, v in enumerate(var_names):
print(f'{v:<10s}{means[i]:>10.3f}{sds[i]:>10.3f}')
fout.write(f'{v:<10s}{means[i]:>10.3f}{sds[i]:>10.3f}\n')
X = ss.zscore(X, axis=0)
# Wพ_ป
print(np.mean(X, axis=0))
print(np.std(X, axis=0))
R = np.corrcoef(X, rowvar=False) # ึs๑
print()
print('ึs๑')
fout.write('\nR =\n')
print(f'{" ":>10s}',
end='')
fout.write(f'{" ":>10s}')
for v in var_names:
print(f'{v:>10s}',
end='')
fout.write(f'{v:>10s}')
fout.write('\n')
print()
for i, s in enumerate(var_names):
print(f'{s:>10s}',
end='')
fout.write(f'{s:>10s}')
for j in
range(len(var_names)):
print(f'{R[i][j]:>10.5f}', end='')
fout.write(f'{R[i][j]:>10.5f}')
print()
fout.write('\n')
Lmbd, V = np.linalg.eigh(R) # ึs๑ฬลLช๐
idx = np.argsort(-Lmbd)
# ลLlฬ~ษภืึฆ้ฝ฿ฬCfbNX
Lmbd = Lmbd[idx]
n_vars = len(var_names)
cum_sum = np.cumsum(Lmbd)
print('\nึs๑ฬลLl')
fout.write('\n\nEigen values of R\n')
print(f'{"Cum.Sum":>40s}{"Cum.Prop(%)":>15s}')
fout.write(f'{"Cum.Sum":>40s}{"Cum.Prop(%)":>15s}\n')
for i in range(n_vars):
print(f'{i+1:>10d}{Lmbd[i]:>15.5f}', end ='')
print(f'{cum_sum[i]:>15.5f}{100*cum_sum[i]/cum_sum[n_vars-1]:>15.2f}')
fout.write(f'{i+1:>10d}{Lmbd[i]:>15.5f}')
fout.write(f'{cum_sum[i]:>15.5f}{100*cum_sum[i]/cum_sum[n_vars-1]:>15.2f}\n')
"""
ลLlฬXN[vbg
"""
plt.title('Scree plot', fontsize=16)
plt.plot(np.arange(n_vars)+1, Lmbd,
ls='-')
plt.ylabel('Eigen values',
fontsize=14)
plt.tight_layout()
plt.show()
q = int(input('q = ')) # ๖qฬอ
if q <= 0:
q = 1
if q > n_vars:
q = n_vars
"""
ผฺลฌ2ๆ@
"""
U, Lmbd, Vh = np.linalg.svd(X)
print('Vh.T[:q] =\n', Vh.T[:q])
print('np.diag(Lmbd[:q]) =\n',
np.diag(Lmbd[:q]))
A = Vh[:q].T @ np.diag(Lmbd[:q]) /
(N**0.5)
"""
คสซ
"""
communlty = np.sum(A ** 2, axis=1)
print('\n๚๐')
fout.write('\n\nBefore rotation\n')
print(f'{" ":10s}', end='')
fout.write(f'\n{" ":10s}')
for i in range(q):
tstr =
f"Factor-{i+1}"
print(f'{tstr:>15s}',
end='')
fout.write(f'{tstr:>15s}')
print(f'{"Communalities":>15s}')
fout.write(f'{"Communalitites":>15s}\n')
for i in range(n_vars):
print(f'{var_names[i]:<10s}', end='')
fout.write(f'{var_names[i]:<10s}')
for j in range(q):
print(f'{A[i][j]:>15.5f}', end='')
fout.write(f'{A[i][j]:>15.5f}')
print(f'{communlty[i]:>15.5f}')
fout.write(f'{communlty[i]:>15.5f}\n')
"""
๚lฬ}bv
"""
dim1 = 1
dim2 = 2 if q >= 2 else 1
while True:
draw_map(var_names,
A.T[dim1-1], A.T[dim2-1],
'Before Rotation',
f'Factor-{dim1}', f'Factor-{dim2}')
dim1 = int(input('dim_x =
'))
if dim1 <= 0:
break
if dim1 > q:
dim1
= q
dim2 = int(input('dim-y =
'))
if dim2 <= 0:
break
if dim2 > q:
dim2
= q
"""
o}bNX๑]
"""
var_rot = Varimax_Orthomax(A)
A_vmax = var_rot.rotate()
print('\no}bNX๑]')
fout.write('\n\nVarimax rotation\n')
v_names, pttn = arrng_pttn(var_names,
A_vmax)
dim1 = 1
dim2 = 2 if q >= 2 else 1
while True:
draw_map(var_names,
A_vmax.T[dim1-1], A_vmax.T[dim2-1],
'Varimax rotation', f'dim-{dim1}', f'dim-{dim2}')
dim1 = int(input('dim_x =
'))
if dim1 <= 0:
break
if dim1 > q:
dim1
= q
dim2 = int(input('dim-y =
'))
if dim2 <= 0:
break
if dim2 > q:
dim2
= q
comm_vmax = np.sum(pttn**2, axis=1)
contrib = np.sum(pttn**2, axis=0)
print('\no}bNX๑]ใฬ๖qp^[')
print(f'{" ":10s}', end='')
fout.write(f'\n{" ":10s}')
for i in range(q):
vs = f'Factor-{i+1}'
print(f'{vs:>10s}',
end='')
fout.write(f'{vs:>10s}')
print(f'{"Communalities":>15s}')
fout.write(f'{"Communalities":>15s}\n')
for i in range(n_vars):
print(f'{v_names[i]:<10s}', end='')
fout.write(f'{v_names[i]:<10s}')
for j in range(q):
print(f'{pttn[i][j]:>10.5f}', end='')
fout.write(f'{pttn[i][j]:>10.5f}')
print(f'{comm_vmax[i]:>15.5f}')
fout.write(f'{comm_vmax[i]:>15.5f}\n')
print(f'{"Contri":<10s}',
end='')
fout.write(f'{"Contri":<10s}')
for j in range(q):
print(f'{contrib[j]:>10.3f}',
end='')
fout.write(f'{contrib[j]:>10.3f}')
print()
print()
fout.write('\n\n')
"""
R[eB~๑]
"""
q_rot = Oblique_Quartimin(A)
A_qrot, Phi = q_rot.rotate()
v_names, pttn = arrng_pttn(var_names,
A_qrot)
print('\nR[eB~๑]ใฬ๖qp^[\n')
fout.write('\nQuartimin rotation\n')
print(f'{" ":10s}', end='')
fout.write(f'\n{" ":10s}')
for i in range(q):
vs = f'Factor-{i+1}'
print(f'{vs:>15s}',
end='')
fout.write(f'{vs:>15s}')
print()
fout.write('\n')
for i in range(n_vars):
print(f'{v_names[i]:<10s}', end='')
fout.write(f'{v_names[i]:<10s}')
for j in range(q):
print(f'{pttn[i][j]:>15.5f}', end='')
fout.write(f'{pttn[i][j]:>15.5f}')
print()
fout.write('\n')
"""
\ขs๑
"""
Strctr = A_qrot @ Phi
v_names, pttn = arrng_pttn(var_names,
Strctr)
print('\n\ขs๑')
fout.write('\n\nStructure matrix\n')
print(f'{" ":10s}', end='')
fout.write(f'{" ":10s}')
for i in range(q):
vs = f'Factor-{i+1}'
print(f'{vs:>15s}',
end='')
fout.write(f'{vs:>15s}')
print()
fout.write('\n')
for i in range(n_vars):
print(f'{v_names[i]:<10s}', end='')
fout.write(f'{v_names[i]:<10s}')
for j in range(q):
print(f'{pttn[i][j]:>15.5f}', end='')
fout.write(f'{pttn[i][j]:>15.5f}')
print()
fout.write('\n')
fout.close()
print(f'\n{fout_nm} is saved.\n')
XgQ@๑]ฬXNvgirotate.pyj
"""
Y.Okamoto,
2025.06
Qlถฃ
ซง_ฝER{ฯถiQOQSj
ๅฌชชอฦ๖qชอAคงoล
"""
import numpy as np
import scipy.optimize as so
class Varimax_Orthomax:
def __init__(self, C):
"""
C: ืs๑
"""
self.C = C
def rotate(self):
"""
ซงER{i2014jAp.137
"""
p = len(self.C)
Mw =
np.identity(p) - np.ones((p,p))/p # w==1
Gmma
= self.C
while True:
Gmma2 = Gmma * Gmma
S_tilde = Gmma * (Mw @ Gmma2)
U, Delta, Vh = np.linalg.svd(self.C.T @ S_tilde)
T = U @ Vh
Gmma_new = self.C @ T
ck = np.sum((Gmma - Gmma_new)**2)
Gmma = Gmma_new
#print(ck)
if ck < 1.0e-6:
break
return Gmma
# ๑]ใฬs๑
class Oblique_Quartimin():
"""
C: ืs๑
"""
def __init__(self, C):
self.C = C
def rotate(self):
"""
ซงER{i2014jAp.140
"""
p, m
= np.shape(self.C)
Gmma
= self.C
Phi
= np.identity(m)
T =
np.identity(m)
def
calc_tjk(gmma, phi, j, k):
class Gammas():
def __init__(self, C, Phi, j, k):
#self.c = Gmma
self.C = C
self.Phi = Phi
self.j = j
self.k = k
def f_gammas(self, t):
"""
Quartimin criterion
"""
c = self.C
Phi = self.Phi
p = np.shape(c)[0]
j = self.j
k = self.k
v = 0.0
for i in range(p):
g2_ij = (1 - 2*t*Phi[j][k] + (t**2)) * (c[i][j]**2)
g2_ik = (t**2) * (c[i][j]**2) + \
2 * t * c[i][j] * c[i][k] + c[i][k]**2
v += g2_ij * g2_ik
return v
calc_g = Gammas(gmma, phi, j, k)
result = so.minimize_scalar(calc_g.f_gammas, [-10, 10])
#print(result)
return result.x
n_try = 0
while True:
Gmma0 = Gmma
for j in range(m):
for k in range(m):
if j != k:
# j < k ๐ j != k ษฯX
tjk = calc_tjk(Gmma, Phi, j, k)
tjj = (1 - 2 * tjk * Phi[j][k] + (tjk**2)) ** 0.5
T_jk = np.identity(m)
T_jk[j][j] = tjj
T_jk[j][k] = tjk
Gmma = Gmma @ T_jk
inv_T_jk = np.linalg.inv(T_jk)
Phi = inv_T_jk @ Phi @ (inv_T_jk.T)
T = T @ T_jk
n_try += 1
ck = np.sum((Gmma0 - Gmma) ** 2)
#print('ck =', ck, '
n_try =', n_try)
if (ck < 1.0e-6) or (n_try > 50):
break
else:
T = np.identity(m)
return Gmma, Phi # ๑]ใฬืs๑ฦคชUs๑
XgR@ฯฬฎ๑Azuฬ`ๆXNvgimymodule.pyj
import copy
import numpy as np
import matplotlib.pyplot as plt
def arrng_pttn(names, A):
v_nms = copy.copy(names)
pttn = copy.copy(A)
n = len(v_nms)
q = len(pttn[0])
vals = np.empty(n)
for i in range(n):
mx_p
= np.argsort(-np.abs(pttn[i]))
vals[i] = np.abs(pttn[i][mx_p[0]]) * (0.1**mx_p[0])
idx = np.argsort(-vals)
return v_nms[idx], pttn[idx]
def draw_map(names, xcoord, ycoord,
stitle, sxlabel, sylabel):
plt.figure(figsize=(5, 5))
plt.title(stitle,
fontsize=14)
plt.xticks([-1, 0, 1])
plt.yticks([-1, 0, 1])
plt.xlabel(sxlabel,
fontsize=12)
plt.ylabel(sylabel,
fontsize=12)
plt.plot([-1, 1], [0, 0],
c='k', lw=1)
plt.plot([0, 0], [-1, 1],
c='k', lw=1)
n = len(names)
for i in range(n):
plt.plot(xcoord[i], ycoord[i], 'bo', mfc='none')
for i in range(n):
plt.text(xcoord[i], ycoord[i], names[i], c='k')
plt.tight_layout()
plt.show()