# Interpreting discrepancies between R and SPSS with exploratory factor analysis

I am a graduate student in computer science. I have been doing some exploratory factor analysis for a research project. My colleagues (who are leading the project) use SPSS, while I prefer to use R. This didn't matter until we discovered a major discrepancy between the two statistical packages.

We are using principal axis factoring as the extraction method (please note that I am well aware of the difference between PCA and factor analysis, and that we are not using PCA, at least not intentionally). From what I've read, this should correspond to "principal axis" method in R, and either "principal axis factoring" or "unweighted least squares" in SPSS, according to R documentation. We are using an oblique rotation method (specifically, promax) because we expect correlated factors, and are interpreting the pattern matrix.

Running the two procedures in R and SPSS, there are major differences. The pattern matrix gives different loadings. Although this gives more or less the same factor to variable relationships, there is up to a 0.15 difference between corresponding loadings, which seems more than would be expected by just a different implementation of the extraction method and promax rotations. However, that is not the most startling difference.

The cumulative variance explained by the factors is around 40% in the SPSS results, and 31% in the R results. This is a huge difference, and has led to my colleagues wanting to use SPSS instead of R. I have no problem with this, but a difference that big makes me think that we might be interpreting something incorrectly, which is a problem.

Muddying the waters even more, SPSS reports different types of explained variance when we run unweighted least squares factoring. The proportion of explained variance by Initial Eigenvalues is 40%, while the proportion of explained variance from Extraction Sums of Squared Loadings (SSL) is 33%. This leads me to think that the Initial Eigenvalues is not the appropriate number to look at (I suspect this is the variance explained before rotation, though which it's so big is beyond me). Even more confusing, SPSS also shows Rotation SSL, but does not calculate the percentage of explained variance (SPSS tells me that having correlated factors means I cannot add SSLs to find the total variance, which makes sense with the math I've seen). The reported SSLs from R do not match any of these, and R tells me that it describes 31% of the total variance. R's SSLs match the Rotation SSLs the most closely. R's eigenvalues from the original correlation matrix do match the Initial Eigenvalues from SPSS.

Also, please note that I have played around with using different methods, and that SPSS's ULS and PAF seem to match R's PA method the closest.

My specific questions:

1. How much of a difference should I expect between R and SPSS with factor analysis implementations?
2. Which of the Sums of Squared Loadings from SPSS should I be interpreting, Initial Eigenvalues, Extraction, or Rotation?
3. Are there any other issues that I might have overlooked?

My calls to SPSS and R are as follows:

SPSS:

FACTOR
/VARIABLES <variables>
/MISSING PAIRWISE
/ANALYSIS <variables>
/PRINT INITIAL KMO AIC EXTRACTION ROTATION
/FORMAT BLANK(.35)
/CRITERIA FACTORS(6) ITERATE(25)
/EXTRACTION ULS
/CRITERIA ITERATE(25)
/ROTATION PROMAX(4).


R:

library(psych)
fa.results <- fa(data, nfactors=6, rotate="promax",
scores=TRUE, fm="pa", oblique.scores=FALSE, max.iter=25)

• Can't check it because I don't use R, but I suspect that there is lapse in the documentation. fm="pa" should correspond to /EXTRACTION PAF. Also, try to compare the solutions prior any rotation, because mild differences in rotation algos may mix up with the extraction method differences. – ttnphns Mar 17 '12 at 6:26
• Thanks for taking a look! I will try comparing the solutions before rotation. I should mention that I've tried both /EXTRACTION ULS and /EXTRACTION PAF, and there is very little difference in the loadings (but neither is really close to the R "pa" method). The reason I show /EXTRACTION ULS above is because that's the command that gives the various SSLs. – Oliver Mar 17 '12 at 6:39
• Principal axis method and unweighted least squares methods can give similar results sometimes but they are fundamentally different algorithmically. I believe that equivalences between R and SPSS are as as follows: "pa"=PAF, "minres"=ULS, "gls"=GLS, "ml"=ML – ttnphns Mar 17 '12 at 6:54
• Also, check the treatment of missing values. In your SPSS code, you delete them pairwise. In you R code - ...? – ttnphns Mar 17 '12 at 7:04
• I've compared the pre-rotation SSLs from R and they match the Extraction SSLs in the ULS solution from SPSS (unfortunately, the PAF solution in SPSS did not give me these values). I think that the promax rotation seems to be the culprit. Well, either that or the way SPSS prints out Rotation SSLs. Maybe R makes an estimate of the total variance explained by the final SSLs, while SPSS tells me that no such estimate is appropriate. – Oliver Mar 17 '12 at 16:09

First of all, I second ttnphns recommendation to look at the solution before rotation. Factor analysis as it is implemented in SPSS is a complex procedure with several steps, comparing the result of each of these steps should help you to pinpoint the problem.

Specifically you can run

FACTOR
/VARIABLES <variables>
/MISSING PAIRWISE
/ANALYSIS <variables>
/PRINT CORRELATION
/CRITERIA FACTORS(6) ITERATE(25)
/EXTRACTION ULS
/CRITERIA ITERATE(25)
/ROTATION NOROTATE.


to see the correlation matrix SPSS is using to carry out the factor analysis. Then, in R, prepare the correlation matrix yourself by running

r <- cor(data)


Any discrepancy in the way missing values are handled should be apparent at this stage. Once you have checked that the correlation matrix is the same, you can feed it to the fa function and run your analysis again:

fa.results <- fa(r, nfactors=6, rotate="promax",
scores=TRUE, fm="pa", oblique.scores=FALSE, max.iter=25)


If you still get different results in SPSS and R, the problem is not missing values-related.

Next, you can compare the results of the factor analysis/extraction method itself.

FACTOR
/VARIABLES <variables>
/MISSING PAIRWISE
/ANALYSIS <variables>
/PRINT EXTRACTION
/FORMAT BLANK(.35)
/CRITERIA FACTORS(6) ITERATE(25)
/EXTRACTION ULS
/CRITERIA ITERATE(25)
/ROTATION NOROTATE.


and

fa.results <- fa(r, nfactors=6, rotate="none",
scores=TRUE, fm="pa", oblique.scores=FALSE, max.iter=25)


Again, compare the factor matrices/communalities/sum of squared loadings. Here you can expect some tiny differences but certainly not of the magnitude you describe. All this would give you a clearer idea of what's going on.

1. In my experience, it's possible to obtain very similar results, sometimes after spending some time figuring out the different terminologies and fiddling with the parameters. I have had several occasions to run factor analyses in both SPSS and R (typically working in R and then reproducing the analysis in SPSS to share it with colleagues) and always obtained essentially the same results. I would therefore generally not expect large differences, which leads me to suspect the problem might be specific to your data set. I did however quickly try the commands you provided on a data set I had lying around (it's a Likert scale) and the differences were in fact bigger than I am used to but not as big as those you describe. (I might update my answer if I get more time to play with this.)
3. This is a wild guess at this stage but have you checked if the factor extraction procedure converged in 25 iterations? If the rotation fails to converge, SPSS does not output any pattern/structure matrix and you can't miss it but if the extraction fails to converge, the last factor matrix is displayed nonetheless and SPSS blissfully continues with the rotation. You would however see a note “a. Attempted to extract 6 factors. More than 25 iterations required. (Convergence=XXX). Extraction was terminated.” If the convergence value is small (something like .005, the default stopping condition being “less than .0001”), it would still not account for the discrepancies you report but if it is really large there is something pathological about your data.
• Very nice answer. I was going to suggest (if possible) the author provide a sample correlation matrix to see where the trouble lies. Should not be too difficult to fudge it/make it ambiguous enough to share the data. Also if one can't reproduce the problem when starting directly with the same correlation matrix that partly identifies the problem. – Andy W Mar 18 '12 at 15:12
• Thanks, this is a fantastic answer. I will go through these steps once I get back to my SPSS machine. In response to #3, the solution does converge in 9 iterations, but I'll keep that in mind for any future analyses I do. It was very helpful to know that the differences aren't typically as big as I have described (I am also working with Likert scale data, 5-point). – Oliver Mar 18 '12 at 17:10
• In case anyone else wonders, the fa function in R is from the psych package. The factanal function from the base package should perform similarly, but psych is well worth using for other purposes anyway. In fact, since this is Likert data, it would be wise to use the psych package's fa.poly instead: see the help documentation. – Nick Stauner Jul 15 '14 at 14:43

Recently I have found that most factor analysis discrepancies between SPSS and R (with Psych package) clear up when data are treated missing-listwise in each program, the correlation matrix shows up exactly the same in each, and no oblique rotation is used.

One remaining discrepancy is in the series of values that show up in the scree plot indicating eigenvalues after extraction. In R's "scree(cor(mydata))" these "factors" don't match those listed in SPSS's Variance Explained table under "Extraction Sums of Squared Loadings." Note that the R scree plot's "components" do match SPSS's scree plot, which also match its Variance Explained table's "Initial Eigenvalues."

I've also found that the "Proportion Var" explained by each factor is, in R, sometimes reported as (the proportion for a given factor)/(the amount explained by all factors), while at other times it is (the proportion for a given factor)(the number of items in the analysis). So if you get the former, it is, while not a match, at least proportional to and derivable from what SPSS reports under "Extraction Sums of Squared Loadings...% of Variance."

Introducing oblimin rotation in each program, however, creates sizeable discrepancies in item loadings or factors' variance explained that I haven't been able to resolve.

The default rotation method in R is oblimin, so this will likely cause the difference. As a test run a PAF/oblimin in SPSS and R and you will find nearly identical results.

I do not know what causes the differences in pattern loadings, but I assume that the difference in % of explained variance is due to: - are you perhaps interpreting the first part (of 2 or 3) of the SPSS explained variance table which actually shows results of principal component analysis. The second part shows the results for unrotated factor analysis results and the third results after rotation (if used). - the fact that fa function (or more precisely its print method) wrongly computes SSL for oblique factors. To get the % of total variance explained by factor, you should compute the sum of squared structural loadings by factor and divide that by number of variables. However, you can not sum these up (in case of oblique rotations) to get the % of variance explained by all factors. To get this, either compute the mean communality or the total % of variance explained by orthogonal factors (eg, using none or varimax rotations), which can be summed.

• Welcome to the site, @AlesZiberna. We are trying to build a permanent repository of statistical information in the form of questions & answers. So one thing we worry about is linkrot. Could you provide an overview of the information at the link in case it goes dead, & so readers can decide if they want to pursue it? – gung - Reinstate Monica May 13 '15 at 13:59

This answer is additive to the ones above. As suggested by Gala in his answer, one should first determine if the solutions provided by R (e.g. fa in psych) and SPSS are different prior to rotation. If they're the same, then look at the rotation settings in each program. (For SPSS, you can find all the settings in the reference manual entry for FACTOR).

One important setting to look for is the Kaiser normalization. By default, SPSS does Kaiser normalization during rotation, whereas some R functions like 'fa' do not. You can control that setting in SPSS by specifying /CRITERIA = NOKAISER/KAISER, to verify if it eliminates any discrepancies between the results with each program.