Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 62 additions & 8 deletions R/modsem_mplus.R
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@
#'
#' @param output.std Should \code{STANDARDIZED} be added to \code{OUTPUT}?
#'
#' @param cleanup Should the \code{Mplus} files (\code{.inp}, \code{.dat} and \code{.out})
#' created during estimation be deleted when \code{modsem_mplus()} exits? Default is
#' \code{FALSE}, meaning the files are kept in the working directory.
#'
#' @param ... arguments passed to other functions
#'
#' @return modsem_mplus object
Expand Down Expand Up @@ -64,6 +68,7 @@ modsem_mplus <- function(model.syntax,
rcs.scale.corrected = TRUE,
output.std = TRUE,
categorical = NULL,
cleanup = FALSE,
...) {
if (!requireNamespace("MplusAutomation", quietly = TRUE))
stop("modsem_mplus() requires the 'MplusAutomation' package; please install it.")
Expand Down Expand Up @@ -172,15 +177,26 @@ modsem_mplus <- function(model.syntax,
rdata = data[usevariables],
)

results <- MplusAutomation::mplusModeler(model,
modelout = "mplusResults.inp",
run = 1L)
fprefix <- getMplusFilePrefix()
if (cleanup)
on.exit(cleanupMplusFiles(fprefix), add = TRUE)

results <- MplusAutomation::mplusModeler(
model,
modelout = paste0(fprefix, ".inp"),
run = 1L,
writeData = "always",
hashfilename = FALSE
)

coefsTable <- coef(results)
mplusParTable <- mplusTableToParTable(coefsTable,
intTerms = intTerms,
intTermsMplus = intTermsMplus,
indicators = indicators,
parTable.in = parTable)
mplusParTable <- mplusTableToParTable(
coefsTable,
intTerms = intTerms,
intTermsMplus = intTermsMplus,
indicators = indicators,
parTable.in = parTable
)

# coef and vcov
TECH1 <- MplusAutomation::get_results(results, element = "tech1")
Expand Down Expand Up @@ -693,3 +709,41 @@ cbind0 <- function(...) {

cbind(...)
}


mplusFilePrefixExists <- function(fprefix) {
inp <- paste0(fprefix, ".inp")
dat <- paste0(fprefix, ".dat")
out <- paste0(fprefix, ".out")
file.exists(inp) || file.exists(dat) || file.exists(out)
}


cleanupMplusFiles <- function(fprefix) {
files <- paste0(fprefix, c(".inp", ".dat", ".out"))
unlink(files[file.exists(files)])
}


getMplusFilePrefix <- function(max.iter = 20) {
randid <- generateRandomCharId(n=12)
fprefix <- paste0("mplusResults", randid)

if (!mplusFilePrefixExists(fprefix))
return(fprefix)

for (i in seq_len(max.iter)) {
id <- generateRandomCharId(2)
fprefix <- paste0(fprefix, id)

if (!mplusFilePrefixExists(fprefix))
return(fprefix)
}

mod_msg_warn(
"Unable to create a unique name for Mplus files!",
"Previous results might get overwritten..."
)

fprefix
}
6 changes: 6 additions & 0 deletions R/utils.R
Original file line number Diff line number Diff line change
Expand Up @@ -848,3 +848,9 @@ std1 <- function(v) {

(v - mu) / sigma
}


generateRandomCharId <- function(n = 36) {
chars <- c(letters, LETTERS, as.character(0:9))
paste0(sample(chars, size = n, replace = TRUE), collapse = "")

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve the user's RNG state when generating filenames

Because modsem_mplus() now calls this helper on every fit, sample() advances .Random.seed just to choose a scratch filename. In workflows that set a seed before fitting an Mplus model and then run simulations or Monte Carlo standardization afterward, the post-fit random draws silently change even though the model fit itself did not previously consume R RNG state; use a non-RNG temp name or restore the RNG state around this call.

Useful? React with 👍 / 👎.

}
5 changes: 0 additions & 5 deletions man/modsem-package.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions man/modsem_mplus.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading