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

<pre><code>score_new_data &lt;- function(fit, new_data, original_data) {
    means &lt;- sapply(original_data[,row.names(fit$correlation)], mean)
    sds &lt;- sapply(original_data[,row.names(fit$correlation)], sd)
    z &lt;- as.matrix(scale(new_data[,row.names(fit$correlation)], 
                         center = means,
                        scale = sds))
    z %*% solve(fit$correlation, fit$loadings)
}
</code></pre>

<p>So for example, </p>

<pre><code>bfi &lt;- na.omit(bfi)
variables &lt;- c("A1", "A2", "A3", "A4", "C1", "C2", "C3", "C4")
data &lt;- bfi[,variables]
fit &lt;- factanal(data, factors = 2, scores = "regression", rotation = "varimax")
</code></pre>

<p>This is a typical factor analysis.</p>

<p>And now supply some new data along with the fit of the factor analysis and the original data:</p>

<pre><code> score_new_data(fit, data[1:5, ], data)
</code></pre>

<p>And it generates the following:</p>

<pre><code>&gt; 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
</code></pre>

<p>The answer here provides additional details: <a href="https://stackoverflow.com/a/4146131/180892">https://stackoverflow.com/a/4146131/180892</a></p>

<p>If you look at the code for <code>factanal</code> you can also learn more about what the regression method of scoring involves:</p>

<pre><code>  Lambda &lt;- fit$loadings # lambda are the loadings
  zz &lt;- scale(z, TRUE, TRUE) # matrix of data is z standardized
  # cv is correlation matrix
  sc &lt;- zz %*% solve(cv, Lambda)
</code></pre>

CC BY-SA 4.0
2018-08-07T05:50:37.257Z
Beautiful! I get it now. Thanks again Jeromy!
thevengefulco
CC BY-SA 4.0
2018-08-08T00:15:25.240Z
I just adjusted the function so that it uses the means and sds of the original data for standardizing the new data.
Jeromy Anglim
CC BY-SA 4.0
2018-08-07T03:20:17.557Z
2018-08-08T00:14:52.390Z
2018-08-08T00:14:52.390Z
Jeromy Anglim
<p>Using this simple R code, I have performed a factor analysis on my dataset:</p>

<pre><code>factanal(df, factors = 6, scores = "regression", rotation = "varimax")
</code></pre>

<p>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 <code>factanal</code> 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.</p>

<p>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).</p>

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

<regression>
Generating a factor score for additional data using R and factanal
thevengefulco
# Generating a factor score for additional data using R and factanal

(Asked by: username_0 on 2018-08-06)

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?

**Tags:** regression


---

## 1 answers

### Answer by username_1 on 2018-08-07. Score: 2 | Accepted 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)

> **Comments:**
> **username_0**: Beautiful! I get it now. Thanks again Jeromy!  
> **username_1**: I just adjusted the function so that it uses the means and sds of the original data for standardizing the new data.  

---

