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:


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?

  • 1
    $\begingroup$ 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? $\endgroup$ Jun 7, 2016 at 20:00
  • 1
    $\begingroup$ 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... $\endgroup$ Jun 8, 2016 at 18:02
  • $\begingroup$ On the right of the screen, there I see some related questions, e.g. stats.stackexchange.com/q/142285/3277. Can that help? $\endgroup$
    – ttnphns
    Jun 8, 2016 at 18:14
  • $\begingroup$ 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) $\endgroup$ Jun 8, 2016 at 18:22
  • $\begingroup$ 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. $\endgroup$ Jun 8, 2016 at 18:31

2 Answers 2


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.



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

                   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

                   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.

  • $\begingroup$ Thank you, Matt. But, what happens if you only have the cov matrix without the original raw data file. $\endgroup$ May 14, 2019 at 20:26
  • $\begingroup$ 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? $\endgroup$ May 14, 2019 at 21:09
  • $\begingroup$ this was common in the 70's as a way of avoiding printing massive tables to textbooks and reports -- sharing the cov matrix is common in psychometrics. I think in this case you have to just sample from the model-implied matrices themselves. $\endgroup$ Aug 18, 2022 at 20:20

A solution to this problem, can be to use the covariance matrix together with the mean and std devitation to create a simulation of the data. Then after testing that the simulated data follows your assumptions, you could run the analysis. I have done this, to replicate papers that did not share their data.

I would do the following...

# Set your means and stddev
mu <- c(4.23, 3.01, 2.91)
stddev <- c(1.23, 0.92, 1.32)

Then get your correlation matrix and you will be able to get your covariance.

corMat <- matrix(c(1, 0.78, 0.23,
                   0.78, 1, 0.27,
                   0.23, 0.27, 1),
                 ncol = 3)

#Create the covariance matrix:
covMat <- stddev %*% t(stddev) * corMat

Now i will use MASS library to cast the mvrnorm function...

dat1 <- mvrnorm(n = 1000, mu = mu, Sigma = covMat, empirical = FALSE)

Finally, you can use this to check if what you have done makes sense


If you are comfortable with this synthetic data, the next step will be to run your simulation.

I hope it helps someone! Best, J


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.