Nothing
#' @title Helper Functions For `partables`-Class Objects
#'
#' @description For tasks such as comparing two parameter
#' tables inside a `partables`-class object.
#'
#' @name partables_helpers
NULL
#' @details
#'
#' The function [identical_partables()] compare two
#' `lavaan` parameter tables and see whether they
#' are identical. (Adapted from a similar function
#' in the package `semhelpinghands`).
#'
#' @param object1 A `lavaan` parameter
#' table or similar object.
#'
#' @param object2 A `lavaan` parameter
#' table or similar object.
#'
#' @return
#' The function [identical_partables()]
#' returns either `TRUE` or `FALSE`.
#'
#' @examples
#'
#' library(lavaan)
#' mod1 <-
#' "
#' x3 ~ x1
#' x2 ~ x4
#' "
#' mod2 <-
#' "
#' x2 ~ x4
#' x3 ~ x1
#' "
#' fit1 <- sem(mod1, dat_path_model)
#' fit2 <- sem(mod2, dat_path_model)
#' pt1 <- parameterTable(fit1)
#' pt2 <- parameterTable(fit2)
#' identical_partables(pt1, pt2)
#'
#' @rdname partables_helpers
#' @export
identical_partables <- function(object1,
object2) {
if (!is_partable(object1) ||
!is_partable(object2)) {
stop("At least one of the objects is not a parameter table.")
}
if (!identical(nrow(object1),
nrow(object2))) {
return(FALSE)
}
if (!identical(sum(object1$free > 0),
sum(object2$free > 0))) {
return(FALSE)
}
if (!identical(sort(object1$op),
sort(object2$op))) {
return(FALSE)
}
if (!identical(sort(union(object1$lhs, object1$rhs)),
sort(union(object2$lhs, object2$rhs)))) {
return(FALSE)
}
# Drop nonessential columns
object1$est <- NULL
object2$est <- NULL
object1$se <- NULL
object2$se <- NULL
pt1 <- fix_cov(object1)
pt2 <- fix_cov(object2)
tmp1 <- pt1[order(pt1$group,
pt1$op, pt1$lhs, pt1$rhs), ]
tmp2 <- pt2[order(pt2$group,
pt2$op, pt2$lhs, pt2$rhs), ]
rownames(tmp1) <- NULL
rownames(tmp2) <- NULL
if (!identical(tmp1[, c("group", "lhs", "op", "rhs")],
tmp2[, c("group", "lhs", "op", "rhs")])) {
return(FALSE)
}
if (!identical(tmp1$free > 0,
tmp2$free > 0)) {
return(FALSE)
}
if (!is.null(tmp1$label) &&
!is.null(tmp2$label)) {
if (!identical(tmp1$label,
tmp2$label)) {
return(FALSE)
}
}
if (!is.null(tmp1$exo) &&
!is.null(tmp2$exo)) {
if (!identical(tmp1$exo,
tmp2$exo)) {
return(FALSE)
}
}
if (!is.null(tmp1$ustart) &&
!is.null(tmp2$ustart)) {
tmp1u <- tmp1[which(tmp1$ustart > 0), ]
tmp2u <- tmp2[which(tmp2$ustart > 0), ]
if (!identical(tmp1u$start,
tmp2u$start)) {
return(FALSE)
}
}
return(TRUE)
}
#' @noRd
check_lor <- function(object1, object2) {
}
#' @param x An object to be checked.
#'
#' @details
#' The function [is_partable()] tries
#' to
#' check whether an object is "likely"
#' to be a parameter table that can be
#' used by [lavaan::lavaan()] and its
#' wrappers, such as [lavaan::sem()].
#'
#' Note that there is no guarantee the
#' the parameter table makes sense or
#' will not lead to error when fitted.
#' It can only check whether it has the
#' required columns.
#'
#' @return
#' The function [is_partable()]
#' returns either `TRUE` or `FALSE`.
#'
#' @examples
#'
#' is_partable(pt1)
#'
#' @rdname partables_helpers
#' @export
is_partable <- function(x) {
if (!inherits(x, what = "data.frame")) {
# stop("x is not a data-frame-like object.")
return(FALSE)
}
# Must at least have these columns
min_names <- c("id",
"lhs",
"op",
"rhs",
"free",
"ustart")
if (!all(min_names %in% colnames(x))) {
# stop("x does not have minimally required columns.")
return(FALSE)
}
return(TRUE)
}
#' @details
#' The function [same_variables()]
#' check whether all parameter labels
#' in a `partables`-class object use
#' the same observed variables.
#'
#' @return
#' The function [same_variables()]
#' returns either `TRUE` or `FALSE`.
#'
#' @examples
#'
#' out <- model_set(fit1,
#' fit_models = FALSE)
#' same_variables(get_partables(out))
#'
#'
#' @rdname partables_helpers
#' @export
same_variables <- function(x) {
if (length(x) == 1) {
return(TRUE)
}
out0 <- lapply(x, function(xx) {
out <- tryCatch(lavaan::lavaan(xx))
out
})
if (any(sapply(out0, inherits, what = "error"))) {
stop("One or more parameter tables result in error.")
}
all_names <- lapply(out0,
lavaan::lavNames,
"ov")
all_names0 <- all_names[[1]]
for (xx in all_names[-1]) {
if (!setequal(all_names0, xx)) {
return(FALSE)
}
}
return(TRUE)
}
#' @details
#' The function [get_partables()]
#' extract the `partable` object from
#' a `model_set`-class object.
#'
#' @return
#' The function [get_partables()]
#' returns a `partables`-class
#' object.
#'
#' @examples
#'
#' out <- model_set(fit1,
#' fit_models = FALSE)
#' get_partables(out)
#'
#' @rdname partables_helpers
#' @export
get_partables <- function(x) {
out <- x$models
if (!inherits(out, what = "partables")) {
return(NULL)
}
out
}
#' @details
#' The function [to_partables()]
#' combine objects to create a
#' `partables`-class object.
#' The objects to be combined can be
#' a `lavaan`-class object (e.g.,
#' the output of [lavaan::sem()])
#' or a parameter table of `lavaan`.
#'
#' @return
#' The function [to_partables()]
#' returns a `partables`-class
#' object, created from the objects
#' supplied.
#'
#' @param ... The objects to be combined.
#'
#' @examples
#'
#' fit1 <- sem(mod1, dat_path_model)
#' fit2 <- sem(mod2, dat_path_model)
#' pt1 <- parameterTable(fit1)
#' pt2 <- parameterTable(fit2)
#'
#' to_partables(fit1, fit2)
#' to_partables(pt1, pt2)
#'
#' @rdname partables_helpers
#' @export
to_partables <- function(...) {
ddd <- list(...)
ddd_names <- sapply(as.list(match.call()[-1]), deparse)
if (!is.null(names(ddd_names))) {
i <- which(sapply(names(ddd_names), function(x) {nchar(x) > 0}))
if (length(i) > 0) {
ddd_names[i] <- names(ddd_names)[i]
ddd_names <- unname(ddd_names)
}
}
out <- lapply(ddd,
function(x) {
if (inherits(x, "lavaan")) {
return(lavaan::parameterTable(x))
}
if (is_partable(x)) {
return(x)
}
stop("At least one object is neither a lavaan object ",
"nor a parameter table.")
})
names(out) <- ddd_names
class(out) <- c("partables", class(out))
out
}
#' @noRd
fix_cov <- function(x) {
i <- which(x$op == "~~")
if (length(i) == 0) {
return(x)
}
jj <- x[i, "rhs"] > x[i, "lhs"]
ii <- i[jj]
a <- x[ii, "lhs"]
x[ii, "lhs"] <- x[ii, "rhs"]
x[ii, "rhs"] <- a
return(x)
}
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.