# How to predict factor scores in Lavaan

In doing a CFA in Lavaan, I had to use the covariance matrix as an input because I was getting some errors with the original data e.g., negative variances.

I would normally have predicted factor scores using the predict() function, lavPredict functions the same, but now that I'm using the covariance matrix it's not possible to do this directly.

Is there a way to use the information from the CFA to calculate factor scores in the same way as Lavaan does it? I believe the predict() function uses the method of regression to calculate factor scores.

This is sample code to produce factor scores with raw data as input. Using this method I get an error in one of my variances:

library(lavaan)

model1 = '
Latent1 =~ X1 + X2
Latent2 =~ X3 + X4 + X5
Latent3 =~ X6 + X7
'

model1.fit = cfa(model1, data=mydata) #fit Lavaan model

predict(model1.fit) #Predict factor scores (method of regression)


This is the code to produce factor scores with covariance matrix as input. There are no error messages here, but I can't produce factor scores as there is not data to link them to:

cov = cor2cov(cor,std) #(using cor2cov function to create covariance matrix out of correlation table (cor) and standard deviations (std))

model2 = '
Latent1 =~ X1+ X2
Latent2 =~ X3 + X4 + X5
Latent3 =~ X6 + X7
'

model2.fit = cfa(model=model2, sample.cov=cov,sample.nobs=102,std.lv=FALSE)


How to proceed from here to produce factor scores using the results from Lavaan's CFA analysis?

• If you got errors with the data, you should get errors with the covariance matrix (unless you had missing data, or used something other than ML). perhaps some code would help? Jun 7, 2016 at 20:00
• Hi Jeremy, not necessarily. Some errors do go away if you just use the covariance matrix and standard deviations as input for Lavaan. The thing is that now I cannot use the predict() function, and calculating factor scores independently using the regression method is beyond my current skill set... Jun 8, 2016 at 18:02
• On the right of the screen, there I see some related questions, e.g. stats.stackexchange.com/q/142285/3277. Can that help? Jun 8, 2016 at 18:14
• Just for info, I've got the idea of using the covariance table instead of the raw data to get better models from Erin Buchanan CFA lectures, such as this one: youtube.com/… (min 6 to 9) Jun 8, 2016 at 18:22
• Hi ttnphns, not really. I saw that answer, but the matrix response is beyond my understanding. and the other one "Since the factor scores are a linear function of the observables, once you've calculated them once, you can simply use lm to fit a linear regression between the fitted scores and the observables. ", doesn't really apply since I was not able to calculate fitted scores. Jun 8, 2016 at 18:31

This question has received a number of views since it was first posed, but no answers. Here is a solution, which may be useful to future readers of this question.

To demonstrate it works I will first run a cfa() model in using the HolzingerSwineford1939. The model is taken from the lavaan tutorial page.

library(lavaan)
dat<-data.frame(HolzingerSwineford1939[,7:15])

mod<-'
visual=~x1+x2+x3
textual=~x4+x5+x6
speed=~x7+x8+x9
'

fit<-cfa(mod, data = dat)


This returns the following solution:

> summary(fit)
lavaan (0.5-22) converged normally after  35 iterations

Number of observations                           301

Estimator                                         ML
Minimum Function Test Statistic               85.306
Degrees of freedom                                24
P-value (Chi-square)                           0.000

Parameter Estimates:

Information                                 Expected
Standard Errors                             Standard

Latent Variables:
Estimate  Std.Err  z-value  P(>|z|)
visual =~
x1                1.000
x2                0.554    0.100    5.554    0.000
x3                0.729    0.109    6.685    0.000
textual =~
x4                1.000
x5                1.113    0.065   17.014    0.000
x6                0.926    0.055   16.703    0.000
speed =~
x7                1.000
x8                1.180    0.165    7.152    0.000
x9                1.082    0.151    7.155    0.000

Covariances:
Estimate  Std.Err  z-value  P(>|z|)
visual ~~
textual           0.408    0.074    5.552    0.000
speed             0.262    0.056    4.660    0.000
textual ~~
speed             0.173    0.049    3.518    0.000

Variances:
Estimate  Std.Err  z-value  P(>|z|)
.x1                0.549    0.114    4.833    0.000
.x2                1.134    0.102   11.146    0.000
.x3                0.844    0.091    9.317    0.000
.x4                0.371    0.048    7.779    0.000
.x5                0.446    0.058    7.642    0.000
.x6                0.356    0.043    8.277    0.000
.x7                0.799    0.081    9.823    0.000
.x8                0.488    0.074    6.573    0.000
.x9                0.566    0.071    8.003    0.000
visual            0.809    0.145    5.564    0.000
textual           0.979    0.112    8.737    0.000
speed             0.384    0.086    4.451    0.000


When using raw data for input the lavPredict() and predict() return predicted values for the latent variables.

> head(lavPredict(fit))
visual     textual       speed
[1,] -0.81767524 -0.13754501  0.06150726
[2,]  0.04951940 -1.01272402  0.62549360
[3,] -0.76139670 -1.87228634 -0.84057276
[4,]  0.41934153  0.01848569 -0.27133710
[5,] -0.41590481 -0.12225009  0.19432951
[6,]  0.02325632 -1.32981727  0.70885348


Running the same model with the covariance matrix as input returns the same results, but as the original poster notes yields an error when attempting to derive the factor scores.

> COV<-cov(dat)
> fit1<-cfa(mod, sample.cov = COV, sample.nobs = 301, sample.mean = colMeans(dat))
> lavPredict(fit1)
Error in lavPredict(fit1) :
lavaan ERROR: sample statistics were used for fitting and newdata is empty


The solution is fairly straightforward as what the package needs is some raw data to "chew on" so to speak. Here you amend the code to identify the original dataset as raw data input for the prediction function (lavPredict(fit1, newdata = dat)). This returns the following (which remember is the same model fitted in lavaan but using the covariance matrix as input).

> head(lavPredict(fit1, newdata = dat))
visual     textual       speed
[1,] -0.81767524 -0.13754501  0.06150726
[2,]  0.04951940 -1.01272402  0.62549360
[3,] -0.76139670 -1.87228634 -0.84057276
[4,]  0.41934153  0.01848569 -0.27133710
[5,] -0.41590481 -0.12225009  0.19432951
[6,]  0.02325632 -1.32981727  0.70885348


As you can see the results are identical.

• Thank you, Matt. But, what happens if you only have the cov matrix without the original raw data file. May 14, 2019 at 20:26
• Are you saying that you have the covariance matrix and an already fitted lavaan object (and/or model)? You just do not have the raw data that generate the covariance or the model? May 14, 2019 at 21:09