以前の因子分析関連では、主成分分析との関係を扱ったが、今回は回転へ行きたいと思う。
とはいえ、回転について、自分ならではで語ることあるか…というと、いろいろな他の方の解説で参考になるものも多く、自分ならではみたいな説明は難しいな、と正直感じた。
とりあえず、PythonとRで動かしつつ、有名かつ初心者がまず扱うならバリマックス回転とプロマックス回転くらいのはずなので、それらの簡単な紹介かな、と思っている。
まずは動かしてみる
PythonとRで、バリマックス回転とプロマックス回転を、実行してみて結果を比較してみようと思う。
Python
まずはバリマックス回転。
from factor_analyzer import FactorAnalyzer import pandas as pd # データの読み込み df = pd.read_csv('../../01_factor-analysis/data/factor_analysis_test_data.csv', index_col=0) # 因子分析を設定、因子数を2、バリマックス回転で fa_varimax = FactorAnalyzer(n_factors=2, rotation="varimax") # データフレーム df に適用 fa_varimax.fit(df) # 因子負荷量を取得 fa_varimax.loadings_
結果は以下。
| 第1因子 | 第2因子 | |
|---|---|---|
| 英語 | 0.154 | 0.580 |
| 国語 | -0.072 | 0.852 |
| 算数 | 0.941 | 0.009 |
| 理科 | 0.908 | -0.0005 |
| 社会 | -0.110 | 0.808 |
次にプロマックス回転。ライブラリは共通なので、読み込みのコードは省略。DataFrameも同じものを利用。
# 因子分析を設定、因子数を2、プロマックス回転で fa_promax = FactorAnalyzer(n_factors=2, rotation="promax") # データフレーム df に適用 fa_promax.fit(df) # 因子負荷量を取得 fa_promax.loadings_
結果は以下。
| 第1因子 | 第2因子 | |
|---|---|---|
| 英語 | 0.149 | 0.578 |
| 国語 | -0.080 | 0.853 |
| 算数 | 0.941 | 0.004 |
| 理科 | 0.908 | -0.012 |
| 社会 | -0.117 | 0.810 |
今回についてはデータを作った時にそもそも独立した因子で作ったからだと思うが、バリマックス回転もプロマックス回転も結果は似たような数値。
どちらにせよ、1つ目の因子が算数と理科に関する理系の因子で、2つ目の因子が国語、社会に関する文系の因子であることはわかる。元のデータとしては、ちょっとずつ関係するように作ったつもりだが、今回のデータがそうなのかもだが文系の因子に英語は影響しているようだ。
R
まずはバリマックス回転。
install.packages("psych") library(psych) # データの読み込み dat <- read.csv("../../01_factor-analysis/data/factor_analysis_test_data.csv", row.names = 1, header = TRUE, stringsAsFactors = FALSE) # 因子分析 因子数2、バリマックス回転 varimax_result <- fa(dat, nfactors = 2, rotate = "varimax") # 結果の表示 print(varimax_result$loadings)
結果は以下。
| 第1因子 | 第2因子 | |
|---|---|---|
| 英語 | 0.154 | 0.580 |
| 国語 | 0.852 | |
| 算数 | 0.941 | |
| 理科 | 0.908 | |
| 社会 | -0.110 | 0.808 |
次にプロマックス回転。ライブラリ・データは共通なので同じものを利用。
# 因子分析 因子数2、プロマックス回転 promax_result <- fa(dat, nfactors = 2, rotate = "promax") # 結果の表示 print(promax_result$loadings)
結果は以下。
| 第1因子 | 第2因子 | |
|---|---|---|
| 英語 | 0.149 | 0.578 |
| 国語 | 0.853 | |
| 算数 | 0.941 | |
| 理科 | 0.908 | |
| 社会 | -0.117 | 0.810 |
おそらく、Rの場合一定の値以下の因子については表示せず空欄なのだろう。なんとなくだが、表示のオプションがありそうな…理解していないのでわからないが笑
結果は、PythonとRで完全に一致として差し支えないのではないかと思う。(あとあと、Python側が同じ結果を目指していることも理解した。)
バリマックス回転
バリマックス回転によらずだが、回転で目指すのは因子の「単純」構造。単純構造とは何かというと、因子負荷量の絶対値が1(に近い値)か0(に近い値)にはっきり分かれること。
以前の結果のコピペにはなるが、回転無しの結果は以下の通りで、第1因子も第2因子も総合力ぽくなってしまい、結果の解釈が難しい。
| 第1因子 | 第2因子 | |
|---|---|---|
| 英語 | -0.213 | 0.561 |
| 国語 | -0.556 | 0.650 |
| 算数 | 0.759 | 0.557 |
| 理科 | 0.738 | 0.530 |
| 社会 | -0.561 | 0.592 |
特に第2因子が総合力。第1因子はまあ理系因子っぽいちゃあ理系因子っぽいのだが。これが強いと、どんどん文系科目の点数が下がり、それを第2因子でカバーみたいなイメージになってしまう。元のデータの作り方とは全然一致しない。
一方で、バリマックス回転した結果を再掲すると以下の通りで、第1因子が理系力、第2因子が文系力と解釈しやすいのではないかと思う。英語が若干文系っぽく見えているのは、全く意図していないが…笑
| 第1因子 | 第2因子 | |
|---|---|---|
| 英語 | 0.154 | 0.580 |
| 国語 | 0.852 | |
| 算数 | 0.941 | |
| 理科 | 0.908 | |
| 社会 | -0.110 | 0.808 |
バリマックス回転が提案された文献は H. F. Kaiser, “The Varimax Criterion for Analytic Rotation in Factor Analysis,” Psychometrika, vol. 23, no. 3, pp. 187–200, 1958. doi:10.1007/BF02289233 。1958年に提案された手法と考えるともうすぐ70年生きている方法なんだな。というかそれくらい昔に手計算でこれをやってたんだろうか…引用数は11588件(2025年9月現在Google Scholar)で思ったより少なく感じるが、もう手法が常識すぎて引用されないのかも。上記の論文ではバリマックス回転の提案ももちろんだが、単純構造についても提案したらしい。今度、細かくちゃんと読んでみたいと思う。Google Scholarで検索するといくつかオープンにアクセス可能なPDFがある。
で、バリマックス回転では単純構造を目指すために、因子負荷量の2乗の分散を最大化することを目指すようだ。元の因子負荷量は -1 から 1 の範囲でばらついていて、絶対値が 0 か 1 に近いものに分かれていない。そこで2乗することで、平均は真ん中としても0.5、この分散を最大化しようとすると絶対値が 0 に近いものか、 1 に近いものに分かれる、という狙いだろう。正確には「共通性」という数値で正規化した因子負荷量の2乗の分散を最大化する回転を探るようなのだが…まだ「共通性」という数値が語れるほど身についていないので、今後勉強していきたいと思う。
バリマックス回転は直交回転なので、元々の初期解の因子の直交性は保たれる。イメージとしては決まった軸の交点についてロックしてクルクル回して2乗の分散が最大化するポイントを見つける動きだろう。実際には数値計算だが…
直交回転(と次の斜交回転)については、よく解説されていて、本当にいろいろな所でいろいろな方法で解説されているので、どれかはしっくりくるのではないかと思う。そのため、自分から新しい説明方法というのは思いついていない。自分はこの前に主成分分析をすごく考えていたせいもあるのか…全く直交に違和感がなく、しっくりきたというかどれも分からない説明には思わなかった。
プロマックス回転
次にプロマックス回転なのだが、今回例に使ったデータが因子的には恣意的に直交・独立しているために、ほぼバリマックス回転で因子が単純構造になって説明ができてしまっている。そのため…プロマックス回転の効果が分かりづらいが…斜交回転の最も有名な回転がプロマックス回転だ。
プロマックス回転が提案されたのは Hendrickson, Alan E., and Paul Owen White. "Promax: A quick method for rotation to oblique simple structure." British journal of statistical psychology 17.1 (1964): 65-70 。残念ながらGoogle Scholarで調べる限り、オープンアクセスなバージョンはなさそうだ。どれぐらいちゃんと読んでみるか悩ましいが、こういう状況が、被引用数が1415 (2025年9月現在Google Scholar)でかなり少なく感じる要因かもしれない。多くの方が計算方法を解説しているが、何かしらのRやPythonのライブラリ実装を元に解説しているのかも。まあ、実用上は使えれば問題ないと思うので。
動きとしては、まずバリマックス回転をする。さらにバリマックス回転の目的関数を何乗かして、その値を目指すように斜交回転するようだ。乗数は2〜4が多いようだ。今回利用したPythonの factor_analyzer の場合、 power という引数で指定ができ、2〜4で指定できるようだ。デフォルトは4とのことが、ドキュメントで確認できた。というか、ドキュメントをよく読むとこの回転周りはRの GPArotation を参考にしているとのこと。今回使ったライブラリなので、それはまあ結果が同じになるよな、というところ。
今回は計算用に作ったデータなので、理系力と文系力が独立した直交している因子なのだが、世の中の因子はそんなことはないだろう。例えば、学校教育ではいろいろな教科があり、記憶力や論理的思考力、計算力、文章構成力などいろいろな要素、まあつまり因子が計測・習熟できるよう設計されていると思う。ある程度は独立していそうなものをあげたつもりではあるが、計算力の根底には九九を覚えるなど、意外と記憶力も大事だったりするなど、完全に独立なものは世の中にはないような気もする。論理的思考力なんて、記憶力も計算力も、文章構成力も関係するだろう。となると、因子を直交したままとする直交回転の方が実は不自然で、斜交回転というものが出てきたというのも理解しやすい。発明されてからこちらも50年以上たっても大変よく使われているというところで、とても基本な方法なのだろう。
まとめ
いろいろ回転について語ってみたいと思ったものの、正直自分らしく語るほどの内容は…無かった笑 それだけ、世の中のいろいろな解説がわかりやすい、工夫されているのだなと思った。
少しでもという部分で原点の論文を紹介してみたものの、どちらかというと数値の結果として重要なのは、コンピュータで計算させる際の最適化手法だったりするのかもしれない。逆にいうと、数式としてはかなり本質をついているので、バリマックス回転・プロマックス回転は時代を超えて使われているんだろう。考えた人たちはすごいなぁ…
(追記)
参考文献
- 回転の解説関連
- AIcia Solid Project【因子分析】因子の回転ってなんだ!?【新たな視点で因子をより深く理解する】 #088 #VRアカデミア: この数回でバリマックス、プロマックス回転も紹介してくれる。
- 田中嘉博What's バリマックス回転?(1/4):実際に3次元空間上でバリマックス回転(直交回転)をやってみる: こちらもこの関連数回で回転自体などわかりやすく説明してくれていると思う。
- Pythonドキュメント
- API documentation — factor_analyzer 0.5.1 documentation: 今回使用した
factor_analyzerのドキュメント。特に、リンクはRotatorクラスについての紹介。
- API documentation — factor_analyzer 0.5.1 documentation: 今回使用した