R/test_indirect_effect.R

Defines functions test_indirect_effect

Documented in test_indirect_effect

#' @title Test an Indirect Effect
#'
#' @description Test an indirect effect
#' for a `power4test` object.
#'
#' @details
#' This function is to be used in
#' [power4test()] for testing an
#' indirect effect, by setting it
#' to the `test_fun` argument.
#'
#' It uses [manymome::indirect_effect()]
#' to do the test. It can be used on
#' models fitted by [lavaan::sem()]
#' or fitted by a sequence of calls
#' to [stats::lm()], although only
#' nonparametric bootstrap confidence
#' interval is supported for models
#' fitted by regression using
#' [stats::lm()].
#'
#' @return
#' In its normal usage, it returns
#' a named numeric vector with the
#' following elements:
#'
#' - `est`: The mean of the estimated
#'  indirect effect across datasets.
#'
#' - `cilo` and `cihi`: The means of the
#'  lower and upper limits of the
#'  confidence interval (95% by
#'  default), respectively.
#'
#' - `sig`: Whether a test by confidence
#'  interval is significant (`1`) or
#'  not significant (`0`).
#'
#' @param fit The fit object, to be
#' passed to [manymome::indirect_effect()].
#'
#' @param x The name of the `x`-variable,
#' the predictor.
#'
#' @param m A character vector of the
#' name(s) of mediator(s). The path
#' moves from the first mediator in the
#' vector to the last mediator in the
#' vector. Can be `NULL` and the path
#' is a direct path without mediator.
#'
#' @param y The name of the `y`-variable,
#' the outcome variable.
#'
#' @param mc_ci Logical. If `TRUE`, the
#' default, Monte Carlo confidence
#' intervals will be formed. This argument
#' and `boot_ci` cannot be both `TRUE`.
#'
#' @param mc_out The pre-generated
#' Monte Carlo estimates generated by
#' [manymome::do_mc], stored in
#' a `power4test` object. Users should
#' not set this argument and should let
#' [power4test()] to set it automatically.
#'
#' @param boot_ci Logical. If `TRUE`,
#' the default, nonparametric bootstrap
#' confidence intervals will be formed.
#' This argument
#' and `mc_ci` cannot be both `TRUE`.
#'
#' @param boot_out The pre-generated
#' bootstrap estimates generated by
#' [manymome::do_boot], stored in
#' a `power4test` object. Users should
#' not set this argument and should let
#' [power4test()] to set it automatically.
#'
#' @param check_post_check Logical. If
#' `TRUE`, the default, and the model
#' is fitted by `lavaan`, the test
#' will be conducted only if the model
#' passes the `post.check` conducted
#' by [lavaan::lavInspect()] (with
#' `what = "post.check"`).
#'
#' @param ... Additional arguments to
#' be passed to [manymome::indirect_effect()].
#'
#' @param fit_name The name of the
#' model fit object to be extracted.
#' Default is `"fit"`. Used only when
#' more than one model is fitted in
#' each replication. This should be
#' the name of the model on which the
#' test is to be conducted.
#'
#' @param get_map_names Logical. Used
#' by [power4test()] to determine how
#' to extract stored information and
#' assign them to this function. Users
#' should not use this argument.
#'
#' @param get_test_name Logical. Used
#' by [power4test()] to get the default
#' name of this test. Users should not
#' use this argument.
#'
#' @seealso [power4test()]
#'
#' @examples
#'
#' # Specify the model
#'
#' model_simple_med <-
#' "
#' m ~ x
#' y ~ m + x
#' "
#'
#' # Specify the population values
#'
#' model_simple_med_es <-
#' "
#' y ~ m: l
#' m ~ x: m
#' y ~ x: n
#' "
#'
#' # Simulate the data
#'
#' sim_only <- power4test(nrep = 5,
#'                        model = model_simple_med,
#'                        pop_es = model_simple_med_es,
#'                        n = 100,
#'                        R = 100,
#'                        do_the_test = FALSE,
#'                        iseed = 1234)
#'
#' # Do the test in each replication
#'
#' test_ind <- power4test(object = sim_only,
#'                        test_fun = test_indirect_effect,
#'                        test_args = list(x = "x",
#'                                         m = "m",
#'                                         y = "y",
#'                                         mc_ci = TRUE))
#' print(test_ind,
#'       test_long = TRUE)
#'
#' @export

test_indirect_effect <- function(fit = fit,
                                 x = NULL,
                                 m = NULL,
                                 y = NULL,
                                 mc_ci = TRUE,
                                 mc_out = NULL,
                                 boot_ci = FALSE,
                                 boot_out = NULL,
                                 check_post_check = TRUE,
                                 ...,
                                 fit_name = "fit",
                                 get_map_names = FALSE,
                                 get_test_name = FALSE) {
  if (fit_name != "fit") {
    mc_name <- paste0(fit_name, "_mc_out")
    boot_name <- paste0(fit_name, "_boot_out")
  } else {
    mc_name <- "mc_out"
    boot_name <- "boot_out"
  }
  map_names <- c(fit = fit_name,
                 mc_out = mc_name,
                 boot_out = boot_name)
  if (get_map_names) {
    return(map_names)
  }
  if (get_test_name) {
    tmp <- paste0(c(x, m, y),
                  collapse = "->")
    args <- as.list(match.call())
    tmp2 <- character(0)
    if (isTRUE(args$standardized_x) && !isTRUE(args$standardized_y)) {
      tmp <- paste0(tmp, " ('x' standardized)")
    }
    if (!isTRUE(args$standardized_x) && isTRUE(args$standardized_y)) {
      tmp <- paste0(tmp, " ('y' standardized)")
    }
    if (isTRUE(args$standardized_x) && isTRUE(args$standardized_y)) {
      tmp <- paste0(tmp, " ('x' and 'y' standardized)")
    }
    return(paste0("test_indirect: ", tmp, collapse = ""))
  }
  if (boot_ci) mc_ci <- FALSE
  if (inherits(fit, "lavaan")) {
    fit_ok <- lavaan::lavInspect(fit, "converged") &&
              (suppressWarnings(lavaan::lavInspect(fit, "post.check") ||
               !check_post_check))
  } else {
    fit_ok <- TRUE
  }
  if (fit_ok) {
    out <- tryCatch(manymome::indirect_effect(
                                   x = x,
                                   y = y,
                                   m = m,
                                   fit = fit,
                                   mc_ci = mc_ci,
                                   mc_out = mc_out,
                                   boot_ci = boot_ci,
                                   boot_out = boot_out,
                                   progress = FALSE,
                                   ...),
                  error = function(e) e)
  } else {
    out <- NA
  }
  if (inherits(out, "error") ||
      identical(out, NA)) {
    out2 <- c(est = as.numeric(NA),
              cilo = as.numeric(NA),
              cihi = as.numeric(NA),
              sig = as.numeric(NA))
    return(out2)
  }
  ci0 <- stats::confint(out)
  out1 <- ifelse((ci0[1, 1] > 0) || (ci0[1, 2] < 0),
                  yes = 1,
                  no = 0)
  out2 <- c(est = unname(stats::coef(out)),
            cilo = ci0[1, 1],
            cihi = ci0[1, 2],
            sig = out1)
  return(out2)
}

Try the power4mome package in your browser

Any scripts or data that you put into this service are public.

power4mome documentation built on Sept. 9, 2025, 5:35 p.m.