How to replicate a call to lavaan() given a fitted lavaan object?

115 צפיות
מעבר להודעה הראשונה שלא נקראה

ddu...@g.uky.edu

לא נקראה,
24 באוק׳ 2018, 22:22:5024.10.2018
עד lavaan
I am writing a function which takes as its argument a fitted lavaan object. This function will manipulate the data somewhat, perform the same analysis on the manipulated data, and then do some comparisons (fit, loadings, whatever). I can see that the basic call to lavaan is available in lavInspect(fit, "call") and all the optional specifications are in lavInspect(fit, "options"). But... 

(1) I do not see where the model specification is stored (i.e., that you feed to lavaan along with the data and the options). Also, 
(2) lavInspect(fit, "data") loses track of which variables are ordered. And in general, 
(3) I cannot figure out how to generate a new call to lavaan that replicates the old call precisely.

Basically, I want to do the following, but I don't know how to do any of it:

My_Data <- lavInspect(fit, "data")  # oops, lost track of which variables are ordered
## the function will magically modify the data. Pay no attention to the man behind the curtain.
My_Model <-   lavInspect(fit, "model")  # oops, that doesn't exist
My_Options <-  ## no idea... every specification from "call" and "options" other than data and model
new_fit
<- lavaan(model = My_Model, data = My_Data, My_Options) # no idea how to make the options right here


Thanks in advance for any help. I am very new to R (and therefore lavaan), so please forgive if this is very simple.
ההודעה נמחקה

Terrence Jorgensen

לא נקראה,
26 באוק׳ 2018, 5:38:2526.10.2018
עד lavaan
It sounds like you could just use lavaan's update() method to re-fit the model to new data, holding all other options constant.  Here is an example that re-fits the help-page example, and the only change is that you make it a multiple-group model by adding the group= argument.

example(cfa)
fitg <- update(fit, group = "school")

(1) I do not see where the model specification is stored (i.e., that you feed to lavaan along with the data and the options).

The model syntax is translated into a parameter table, which is what lavaan actually uses to represent a model.

parTable(fit)

But aren't you keeping that the same?  If you only change the data, then the update() method can just use the same parameter table from the fitted object.

(2) lavInspect(fit, "data") loses track of which variables are ordered.

You can use the lavNames() function:

lavNames(fit, type = "ov.ord")

But again, you don't need to do that if you use update() because it will use all the original arguments.

(3) I cannot figure out how to generate a new call to lavaan that replicates the old call precisely.

Basically, I want to do the following, but I don't know how to do any of it:

My_Data <- lavInspect(fit, "data")  # oops, lost track of which variables are ordered
## the function will magically modify the data. Pay no attention to the man behind the curtain.
My_Model <-   lavInspect(fit, "model")  # oops, that doesn't exist
My_Options <-  ## no idea... every specification from "call" and "options" other than data and model
new_fit
<- lavaan(model = My_Model, data = My_Data, My_Options) # no idea how to make the options right here

Here's how update() can help.  As an arbitrary transformation, I simply mean-center the variables.  I use a multigroup model example here in case that comes up for your, because it is more complex than the simple-group case (which would not necessitate adding the grouping variable back to My_Data). 

fitg <- update(fit, group = "school")

## extract and transform data
My_Data <- lavInspect(fitg, "data") # list of data, 1 per group
new_list
<- lapply(My_Data, FUN = scale, center = TRUE, scale = FALSE)


## reassemble data (for multigroup models)
new_data
<- data.frame(NULL)
groupvar
<- lavInspect(fitg, "group")
for (g in seq_along(new_list)) {
    temp
<- data.frame(new_list[[g]])
    temp
[ , groupvar] <- names(new_list)[g]
    new_data
<- rbind(new_data, temp)
}
## for single group models, only need this 1 line:
#  new_data <- do.call(rbind, new_list)


## fit model to new data
new_fit
<- update(fitg, data = new_data )


Terrence D. Jorgensen
Assistant Professor, Methods and Statistics
Research Institute for Child Development and Education, the University of Amsterdam

ההודעה נמחקה

ddu...@g.uky.edu

לא נקראה,
26 באוק׳ 2018, 6:59:1026.10.2018
עד lavaan
Hi Dr. Jorgensen,

Thank you so much! This works perfectly, and you saved me hours of googling - I had (obviously) completely missed the "update" function when I read through the documentation for lavaan. You saved me hours of time; my plan was to do a bit of regex magic to create a character string for the the lavaan call, and then eval(parse()) on it.  [[ That may not sounds like hours of time to you, but I learned what a regular expression was less than 48 hours ago ]] Also, I learned about seq_along(), so it's a double bonus. 

Since you follow SEMNet also, you'll get to see what monstrosity I have created sometime next week.

-David
השב לכולם
השב למחבר
העבר לנמענים
0 הודעות חדשות