# Generating a factor score for additional data using R and factanal

Using this simple R code, I have performed a factor analysis on my dataset:

factanal(df, factors = 6, scores = "regression", rotation = "varimax")


I have now found significant factors that I want to keep. I also have chosen to generate scores using the "regression" argument. I'm still not clear on all the steps factanal uses to provide the scores, but after some digging, I found that the "regression" argument does use what is known as Thomson's regression to generate some score. That score then seems to be turned into a z-score given all the scores.

So here is the question: Let's say that some new data comes in and I want to be able to give it a score as well. This new data happens to be one individual sample (the equivalent of one row of a new dataset).

Is there a proper way to give an individual sample a score or must the scores be generated on a population basis?

## 1 Answer

I wrote the following function that takes the fit object returned by factanal and new data that you provide (e.g., a data frame or matrix with identical variable names), along with the original data.

score_new_data <- function(fit, new_data, original_data) {
means <- sapply(original_data[,row.names(fit$correlation)], mean) sds <- sapply(original_data[,row.names(fit$correlation)], sd)
z <- as.matrix(scale(new_data[,row.names(fit$correlation)], center = means, scale = sds)) z %*% solve(fit$correlation, fit$loadings) }  So for example, bfi <- na.omit(bfi) variables <- c("A1", "A2", "A3", "A4", "C1", "C2", "C3", "C4") data <- bfi[,variables] fit <- factanal(data, factors = 2, scores = "regression", rotation = "varimax")  This is a typical factor analysis. And now supply some new data along with the fit of the factor analysis and the original data:  score_new_data(fit, data[1:5, ], data)  And it generates the following: > score_new_data(fit, data[1:5, ], data) Factor1 Factor2 61623 1.4937101 0.1714941 61629 -0.8927227 -1.7240081 61634 -0.4091523 -0.1982590 61640 0.4855813 -1.1968676 61661 -1.2631737 0.6817574  The answer here provides additional details: https://stackoverflow.com/a/4146131/180892 If you look at the code for factanal you can also learn more about what the regression method of scoring involves:  Lambda <- fit$loadings # lambda are the loadings
zz <- scale(z, TRUE, TRUE) # matrix of data is z standardized
# cv is correlation matrix
sc <- zz %*% solve(cv, Lambda)

• Beautiful! I get it now. Thanks again Jeromy! Aug 7, 2018 at 5:50
• I just adjusted the function so that it uses the means and sds of the original data for standardizing the new data. Aug 8, 2018 at 0:15