Factor Analysis

Exploratory and confirmatory factor analysis for high-dimensional optimization data.

The factor_analyzer subpackage provides tools for exploratory factor analysis (EFA) and confirmatory factor analysis (CFA). These are useful for understanding the latent structure in high-dimensional parameter spaces or response data.


Suitability Tests

Before running factor analysis, check whether your data is suitable using the Kaiser-Meyer-Olkin (KMO) test and Bartlett’s test of sphericity:

import numpy as np
from spotoptim.factor_analyzer.factor_analyzer import (
    calculate_kmo,
    calculate_bartlett_sphericity,
)

np.random.seed(0)
X = np.random.randn(100, 5)
X[:, 1] = X[:, 0] + np.random.randn(100) * 0.3
X[:, 3] = X[:, 2] + np.random.randn(100) * 0.5

kmo_all, kmo_model = calculate_kmo(X)
chi2, p_value = calculate_bartlett_sphericity(X)

print(f"KMO measure   : {kmo_model:.4f}")
print(f"Bartlett chi2 : {chi2:.2f}")
print(f"Bartlett p    : {p_value:.6f}")
KMO measure   : 0.4990
Bartlett chi2 : 402.61
Bartlett p    : 0.000000

A KMO value above 0.6 and a significant Bartlett test (low p-value) suggest the data is suitable for factor analysis.


Exploratory Factor Analysis

FactorAnalyzer extracts latent factors from the data:

import numpy as np
from spotoptim.factor_analyzer.factor_analyzer import FactorAnalyzer

np.random.seed(0)
X = np.random.randn(100, 5)
X[:, 1] = X[:, 0] + np.random.randn(100) * 0.3
X[:, 3] = X[:, 2] + np.random.randn(100) * 0.5

fa = FactorAnalyzer(n_factors=2, rotation="varimax")
fa.fit(X)

loadings = fa.loadings_
print(f"Loadings shape: {loadings.shape}")
print(f"Factor loadings:\n{np.round(loadings, 3)}")
Loadings shape: (5, 2)
Factor loadings:
[[ 0.96  -0.042]
 [ 0.998  0.02 ]
 [-0.059  0.996]
 [-0.094  0.891]
 [-0.102  0.021]]

Rotation Methods

Common rotation methods: "varimax" (orthogonal), "promax" (oblique), or None (no rotation).


See Also