R/multisimsum.R

Defines functions multisimsum

Documented in multisimsum

#' @title Analyses of simulation studies with multiple estimands at once, including Monte Carlo error
#' @description `multisimsum` is an extension of [simsum()] that can handle multiple estimated parameters at once.
#' `multisimsum` calls [simsum()] internally, each estimands at once.
#' There is only one new argument that must be set when calling `multisimsum`: `par`, a string representing the column of `data` that identifies the different estimands.
#' Additionally, with `multisimsum` the argument `true` can be a named vector, where names correspond to each estimand (see examples).
#' Otherwise, constant values (or values identified by a column in `data`) will be utilised.
#' See `vignette("E-custom-inputs", package = "rsimsum")` for more details.
#' @param par The name of the variable containing the methods to compare.
#' Can be `NULL`.
#' @inheritParams simsum
#' @return An object of class `multisimsum`.
#' @export
#' @details
#' The following names are not allowed for `estvarname`, `se`, `methodvar`, `by`, `par`: `stat`, `est`, `mcse`, `lower`, `upper`, `:methodvar`.
#' @examples
#' data("frailty", package = "rsimsum")
#' ms <- multisimsum(
#'   data = frailty,
#'   par = "par", true = c(trt = -0.50, fv = 0.75),
#'   estvarname = "b", se = "se", methodvar = "model",
#'   by = "fv_dist"
#' )
#' ms
multisimsum <- function(data,
                        par,
                        estvarname,
                        se = NULL,
                        true = NULL,
                        methodvar = NULL,
                        ref = NULL,
                        by = NULL,
                        ci.limits = NULL,
                        df = NULL,
                        dropbig = FALSE,
                        x = FALSE,
                        control = list()) {
  ### Check arguments
  arg_checks <- checkmate::makeAssertCollection()
  # 'methodvar', 'ref', 'par' must be a single string value
  checkmate::assert_string(x = par, add = arg_checks)
  # 'methodvar', 'par' must be in 'data'
  checkmate::assert_subset(x = methodvar, choices = names(data), add = arg_checks)
  checkmate::assert_subset(x = par, choices = names(data), add = arg_checks)
  # Report
  if (!arg_checks$isEmpty()) checkmate::reportAssertions(arg_checks)
  ### <- The above assumes that the other checks will be run by repeated calls to simsum() below

  ### Set control parameters
  control.default <- list(mcse = TRUE, level = 0.95, power_df = NULL, na.rm = TRUE, char.sep = "~", dropbig.max = 10, dropbig.semax = 100, dropbig.robust = TRUE)
  control.tmp <- unlist(list(
    control[names(control) %in% names(control.default)],
    control.default[!(names(control.default) %in% names(control))]
  ), recursive = FALSE)
  control <- control.tmp

  ### Factorise 'par', 'methodvar'
  data <- .factorise(data = data, cols = c(par, methodvar))

  ### Check that levels of factors are ok
  .validate_levels(data = data, cols = c(par, methodvar), char = ifelse(!is.null(control$char.sep), control$char.sep, "~"))

  ### Set reference method if 'ref' is not specified
  if (!is.null(methodvar)) {
    if (is.null(ref)) {
      if (length(methodvar) > 1) {
        ref <- .compact_method_columns(data = data, methodvar = methodvar)$reftable[[":methodvar"]][1]
      } else {
        ref <- levels(data[[methodvar]])[1]
        data[[methodvar]] <- relevel(data[[methodvar]], ref = ref)
      }
      message(paste("'ref' method was not specified,", ref, "set as the reference"))
    }
  }

  ### Throw a warning if `ref` is specified and `methodvar` is not
  if (is.null(methodvar) & !is.null(ref)) {
    warning("'ref' method is specified while 'methodvar' is not: 'ref' will be ignored")
    ref <- NULL
  }

  ### Split data by 'par'
  par_split <- .split_by(data = data, by = par)

  ### Call 'simsum' on each element of 'par_split'; save data if 'x = TRUE'
  par_simsum <- vector(mode = "list", length = length(par_split))
  if (x) par_data <- vector(mode = "list", length = length(par_split))
  for (i in seq_along(par_split)) {
    if (rlang::is_named(true) | is.null(true)) {
      run <- simsum(data = par_split[[i]], estvarname = estvarname, true = true[names(par_split)[i]], se = se, methodvar = methodvar, ref = ref, by = by, ci.limits = ci.limits, df = df, dropbig = dropbig, x = x, control = control)
    } else {
      run <- simsum(data = par_split[[i]], estvarname = estvarname, true = true, se = se, methodvar = methodvar, ref = ref, by = by, ci.limits = ci.limits, dropbig = dropbig, x = x, control = control)
    }
    par_simsum[[i]] <- run[["summ"]]
    if (x) par_data[[i]] <- run[["x"]]
  }
  names(par_simsum) <- names(par_split)

  ### Add a column with the parameter to each slot, and turn it into factor
  for (i in seq_along(par_simsum)) par_simsum[[i]][[par]] <- names(par_simsum)[i]

  ### Bind summ slots
  summ <- .br(x = par_simsum)
  summ <- .factorise(data = summ, cols = par)
  row.names(summ) <- NULL

  ### Include stuff into object to return
  obj <- list()
  obj$summ <- summ
  obj$par <- par
  obj$estvarname <- estvarname
  obj$true <- true
  obj$se <- se
  obj$methodvar <- methodvar
  obj$ref <- ref
  obj$dropbig <- dropbig
  obj$ci.limits <- ci.limits
  obj$df <- df
  obj$by <- by
  obj$control <- control
  if (x) {
    obj$x <- .br(par_data)
    rownames(obj$x) <- NULL
  }

  ### Return object of class simsum
  class(obj) <- c("multisimsum", "list")
  return(obj)
}

Try the rsimsum package in your browser

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

rsimsum documentation built on Aug. 17, 2022, 5:07 p.m.