From 0206d0263b016391fda2d4c980f7f06920bc65d4 Mon Sep 17 00:00:00 2001 From: Kees Mulder Date: Thu, 12 Dec 2019 15:37:31 +0100 Subject: [PATCH 1/2] Also re-order the structure matrix When an oblique rotation has changed the variance order of the factors, the factors are reordered to ensure the first has the greatest variance. However, the structure matrix was assigned using the loadings before reordering, which causes these orders to sometimes be different. This can cause a lot of surprise for the user; if the factors have been given interpretation, or names, a user may be stumped that the resulting factor scores do not match this interpretation at all, and correlate with different items than the ones with the strongest loadings. The proposed change is to also reorder the structure matrix, so that the factor scores are always in the same order as the factor loadings. This should theoretically solve the issue everywhere, but the package authors should be careful in whether this change has repercussions elsewhere. See also: https://stackoverflow.com/questions/59284044/factor-order-differs-between-loadings-and-scoring-with-oblimin-rotation-how-i --- factor_analyzer/factor_analyzer.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/factor_analyzer/factor_analyzer.py b/factor_analyzer/factor_analyzer.py index 3c95dae..007623b 100644 --- a/factor_analyzer/factor_analyzer.py +++ b/factor_analyzer/factor_analyzer.py @@ -653,8 +653,11 @@ def fit(self, X, y=None): # resort the factors according to their variance variance = self._get_factor_variance(loadings)[0] - loadings = loadings[:, list(reversed(np.argsort(variance)))].copy() + new_order = list(reversed(np.argsort(variance))) + loadings = loadings[:, new_order].copy() + structure = structure[:, new_order].copy() + self.phi_ = phi self.structure_ = structure From 6c07ffbcd6c0c9de6f29656300806dc5b8de1687 Mon Sep 17 00:00:00 2001 From: Kees Mulder Date: Thu, 12 Dec 2019 15:53:10 +0100 Subject: [PATCH 2/2] Also reorder structure matrix only if possible There was a small error in the PR where sometimes structure is None which can not be reordered, which should be fixed now, --- factor_analyzer/factor_analyzer.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/factor_analyzer/factor_analyzer.py b/factor_analyzer/factor_analyzer.py index 007623b..174adfe 100644 --- a/factor_analyzer/factor_analyzer.py +++ b/factor_analyzer/factor_analyzer.py @@ -655,8 +655,9 @@ def fit(self, X, y=None): variance = self._get_factor_variance(loadings)[0] new_order = list(reversed(np.argsort(variance))) loadings = loadings[:, new_order].copy() - structure = structure[:, new_order].copy() - + + if structure is not None: + structure = structure[:, new_order].copy() self.phi_ = phi self.structure_ = structure