I do simulation research and create different datasets for different CFA models. During a series of simulations, I would like to handle errors resulting from e.g. randomization. Specifically - I would like to be able to repeat the sampling procedure in the case of lavaan::cfa errors, but in the case of just warnings, I would only mark them in the output data.
Additionally - the lavaan error breaks the loop, while the warning does not break the loop.
Unfortunately, the "normal" tryCatch procedure (probably) deletes the created variable in both cases, and returns NULL on also warnings. Please, look at my code:
# I do a simple procedure that just inherites lavaan:cfa
my_fit_function <- function(input_model,input_frame){
tryCatch(
{
my_fit <- cfa(input_model, data=input_frame)
return(my_fit)
# and here should be some info about warnings
}, warning = function(warning_condition) {
message("warning; do i have output variable?:")
message(exists("my_fit"))
message(warning_condition)
}, error=function(error_message) {
message("error; do i have output variable?:")
message(exists("my_fit"))
message(error_message)
}
)
}
While execution on dataset that ends with a lavaan warning on the original procedure gives:
fit <- cfa(model, data=df)
(...) lavaan WARNING: covariance matrix of latent variables (...)
exists("fit")
> TRUE
I got my variable and everything seems OK, BUT when i use my procedure i got something like this:
fit <- my_fit_function(model, df)
> warning; do i have output variable?:
> FALSE
> 0
fit
> NULL
so the original function itself rather executes, but at the tryCatch level my_fit returns NULL to me.
What am I doing wrong, or I don't understand? I would be grateful for the tip.
CodePudding user response:
OK, to be honest, i'm still confused why lavaan object is making a mess with standard tryCatch function, but i found some solution ispired by code here
The function that works for me goes like this:
my_fit_function <- function(input_model,input_frame){
tryCatch(my_fit <-cfa(input_model, data=input_frame)),
error = function(e)
{ cat(paste("Lavaan model not secified correctly -",
e,sep="\n")) return(NULL) } )
}
This results a NULL only when i got real error with data or model specification, at errors it still makes an model. Unfortunately, I cannot detect any warnings in this procedure, only an error. Hence, I cannot mark apart error OR warning in the output. But at least I don't have any bugs in functions preventing loop development - this form does not close the loop with error-break.
Maybe it will be useful to someone.
CodePudding user response:
tryCatch
returns the value of its first argument expr
when everything goes as planned. When it doesn't it returns the return value of the condition handlers. In your use case in the question you have
- the fitting function call,
cfa
which should returnmy_fit
; - two condition handlers,
warning
anderror
.
When there is something wrong, control is passed to the handlers and they take as their argument the warning or error. There is no point to print whether my_fit
exists because if the handlers are being executed then it does not exist, it was not created. In this case, my_fit
is the condition and conditionMessage
will retrieve the message R would have printed hadn't it been caught.
The example below is the example in help("cfa")
with an added variable x10
in order to throw an error, see also here. The warning and error handlers are kept as simple as possible to illustrate what is said above.
library(lavaan)
#> This is lavaan 0.6-12
#> lavaan is FREE software! Please report any bugs.
my_fit_function <- function(input_model,input_frame){
my_fit <- tryCatch(
{
cfa(input_model, data=input_frame)
},
# here should be some info about warnings
warning = function(w) w,
# and here about errors
error = function(e) e
)
my_fit
}
HS.model <- ' visual =~ x1 x2 x3
textual =~ x4 x5 x6
speed =~ x7 x8 x9 x10 '
fit <- my_fit_function(HS.model, HolzingerSwineford1939)
if(inherits(fit, "error")) {
conditionMessage(fit)
} else {
summary(fit, fit.measures = TRUE)
}
#> [1] "lavaan ERROR: missing observed variables in dataset: x10"
Created on 2022-10-15 with reprex v2.0.2