Nothing
# ============================================================================ #
# formula-design.R
# ============================================================================ #
#
# Shared accessors for BayesTools formula-design metadata.
#
# ============================================================================ #
# Return the BayesTools formula design for a brma formula parameter.
.fitted_formula_design <- function(object, parameter, required = TRUE) {
design <- NULL
if (!is.null(object[["fit"]])) {
design <- BayesTools::JAGS_formula_design(object[["fit"]], parameter)
}
if (is.null(design)) {
design <- .object_formula_design(object, parameter)
}
if (is.null(design) && required) {
stop(
"Fitted formula design metadata for parameter '", parameter,
"' is missing. Refit the model with the current RoBMA/BayesTools build.",
call. = FALSE
)
}
return(design)
}
# Return formula design metadata stored on or reconstructed from a brma object.
.object_formula_design <- function(object, parameter) {
if (!is.null(object[["formula_design"]][[parameter]])) {
return(object[["formula_design"]][[parameter]])
}
source <- .fitted_formula_source(parameter)
if (is.null(source) ||
is.null(object[["data"]]) ||
is.null(object[["data"]][[source]])) {
return(NULL)
}
if (!is.null(object[["priors"]]) &&
!is.null(object[["priors"]][[source]])) {
return(.object_bayestools_formula_design(
object = object,
parameter = parameter,
source = source
))
}
return(.object_data_formula_design(
object = object,
parameter = parameter,
source = source
))
}
# Reconstruct BayesTools formula design for objects that store data and priors
# but do not have a fitted JAGS object, e.g. only_priors objects.
.object_bayestools_formula_design <- function(object, parameter, source) {
formula_design <- BayesTools::JAGS_formula(
formula = .create_fit_formula_list(data = object[["data"]], parameter = source),
parameter = parameter,
data = .create_fit_formula_data_list(data = object[["data"]], parameter = source),
prior_list = .create_fit_formula_prior_list(priors = object[["priors"]], parameter = source),
formula_scale = .data_standardize_continuous_predictors(object[["data"]])
)[["formula_design"]]
return(formula_design)
}
# Build minimal formula design metadata for data-only objects. These objects do
# not have priors, so BayesTools::JAGS_formula() cannot be used.
.object_data_formula_design <- function(object, parameter, source) {
formula <- .create_fit_formula_list(data = object[["data"]], parameter = source)
data <- object[["data"]][[source]]
terms <- attr(data, "terms")
if (is.null(terms)) {
terms <- stats::terms(formula, data = data)
}
model_matrix <- stats::model.matrix(terms, data = data)
column_names <- colnames(model_matrix)
assign <- attr(model_matrix, "assign")
term_labels <- attr(terms, "term.labels")
term_labels <- gsub(":", "__xXx__", term_labels, fixed = TRUE)
if (is.null(assign)) {
assign <- seq_len(ncol(model_matrix)) - 1L
}
qr_x <- qr(model_matrix)
aliased <- rep(FALSE, ncol(model_matrix))
if (qr_x[["rank"]] < ncol(model_matrix)) {
aliased[qr_x[["pivot"]][seq(qr_x[["rank"]] + 1L, ncol(model_matrix))]] <- TRUE
}
names(aliased) <- column_names
predictors <- all.vars(formula)
predictors <- predictors[predictors %in% names(data)]
predictor_types <- stats::setNames(
vapply(data[predictors], .formula_design_predictor_type, character(1)),
predictors
)
model_terms <- term_labels
if (isTRUE(attr(terms, "intercept") == 1L)) {
model_terms <- c("intercept", model_terms)
}
model_terms_type <- stats::setNames(
vapply(model_terms, .formula_design_term_type, character(1), predictor_types = predictor_types),
model_terms
)
xlevels <- lapply(data[vapply(data, is.factor, logical(1))], levels)
design <- list(
parameter = parameter,
formula = formula,
model_frame = data,
model_matrix = model_matrix,
column_names = column_names,
raw_column_names = column_names,
assign = assign,
terms = terms,
contrasts = attr(model_matrix, "contrasts"),
xlevels = xlevels,
predictors = predictors,
predictor_types = predictor_types,
model_terms = model_terms,
model_terms_type = model_terms_type,
prior_list = NULL,
formula_scale = NULL,
rank = qr_x[["rank"]],
qr_pivot = qr_x[["pivot"]],
aliased = aliased,
transformed_terms = list(),
random_effects = list(),
jags_data_names = list()
)
class(design) <- c("BayesTools_formula_design", "list")
return(design)
}
# Classify a formula predictor for minimal data-only designs.
.formula_design_predictor_type <- function(x) {
if (is.factor(x) || is.character(x)) {
return("factor")
}
return("continuous")
}
# Classify a formula term from the predictor types.
.formula_design_term_type <- function(term, predictor_types) {
if (identical(term, "intercept")) {
return("continuous")
}
components <- unlist(strsplit(term, "__xXx__", fixed = TRUE), use.names = FALSE)
if (any(predictor_types[components] == "factor", na.rm = TRUE)) {
return("factor")
}
return("continuous")
}
# Map a BayesTools formula parameter to the RoBMA data/prior source.
.fitted_formula_source <- function(parameter) {
switch(
parameter,
"mu" = "mods",
"log_tau" = "scale",
NULL
)
}
# Map a RoBMA formula source name to the BayesTools formula parameter.
.fitted_formula_parameter <- function(source) {
switch(
source,
"mods" = "mu",
"scale" = "log_tau",
source
)
}
# Return fitted model terms, optionally converted to user-facing interaction names.
.fitted_formula_terms <- function(object, parameter, include_intercept = TRUE,
display = TRUE, required = TRUE) {
design <- .fitted_formula_design(
object = object,
parameter = parameter,
required = required
)
if (is.null(design)) {
return(NULL)
}
terms <- design[["model_terms"]]
if (!include_intercept) {
terms <- terms[terms != "intercept"]
}
if (display) {
terms <- .formula_design_display_names(terms)
}
return(terms)
}
# Return a fitted formula with an evaluation environment suitable for model.frame().
.fitted_formula_evaluable <- function(object, design, source) {
formula <- design[["formula"]]
if (is.null(formula)) {
return(NULL)
}
stored_formula <- attr(object[["data"]][[source]], "formula")
if (!is.null(stored_formula) && !is.null(environment(stored_formula))) {
environment(formula) <- environment(stored_formula)
} else {
environment(formula) <- baseenv()
}
return(formula)
}
# Return fitted formula column display names keyed by internal matrix names.
.fitted_formula_column_display_map <- function(design) {
if (is.null(design[["column_names"]]) || is.null(design[["raw_column_names"]])) {
return(NULL)
}
if (length(design[["column_names"]]) != length(design[["raw_column_names"]])) {
return(NULL)
}
return(stats::setNames(
.formula_design_display_names(design[["raw_column_names"]]),
design[["column_names"]]
))
}
# Convert BayesTools' JAGS-safe interaction separator to formula syntax.
.formula_design_display_names <- function(x) {
return(gsub("__xXx__", ":", x, fixed = TRUE))
}
# ---------------------------------------------------------------------------- #
# .get_model_matrix
# ---------------------------------------------------------------------------- #
#
# Extract the fitted location model matrix X from a brma object.
#
# ---------------------------------------------------------------------------- #
.get_model_matrix <- function(object) {
is_mods <- .is_mods(object)
is_PET <- .is_PET(object)
is_PEESE <- .is_PEESE(object)
if (!is_mods) {
K <- nrow(object[["data"]][["outcome"]])
X <- matrix(1, nrow = K, ncol = 1)
colnames(X) <- "(Intercept)"
attr(X, "assign") <- 0L
} else {
design <- .fitted_formula_design(object, "mu", required = TRUE)
X <- design[["model_matrix"]]
attr(X, "assign") <- design[["assign"]]
attr(X, "rank") <- design[["rank"]]
attr(X, "aliased") <- design[["aliased"]]
attr(X, "term_labels") <- .fitted_formula_terms(
object = object,
parameter = "mu",
include_intercept = FALSE,
display = TRUE,
required = TRUE
)
raw_colnames <- .fitted_formula_column_display_map(design)
if (!is.null(raw_colnames)) {
attr(X, "raw_colnames") <- raw_colnames
}
}
if (is_PET || is_PEESE) {
outcome_data <- object[["data"]][["outcome"]]
direction <- if (.effect_direction(object) == "negative") -1 else 1
assign <- attr(X, "assign")
raw_colnames <- attr(X, "raw_colnames")
aliased <- attr(X, "aliased")
term_labels <- attr(X, "term_labels")
if (is.null(assign)) {
assign <- seq_len(ncol(X)) - 1L
}
next_assign <- max(assign) + 1L
if (is_PET) {
X <- cbind(X, PET = direction * outcome_data[["sei"]])
assign <- c(assign, next_assign)
raw_colnames <- c(raw_colnames, PET = "PET")
aliased <- c(aliased, PET = FALSE)
term_labels <- c(term_labels, "PET")
next_assign <- next_assign + 1L
}
if (is_PEESE) {
X <- cbind(X, PEESE = direction * outcome_data[["sei"]]^2)
assign <- c(assign, next_assign)
raw_colnames <- c(raw_colnames, PEESE = "PEESE")
aliased <- c(aliased, PEESE = FALSE)
term_labels <- c(term_labels, "PEESE")
next_assign <- next_assign + 1L
}
attr(X, "assign") <- assign
if (!is.null(raw_colnames) && length(raw_colnames) == ncol(X)) {
attr(X, "raw_colnames") <- raw_colnames
}
if (!is.null(aliased) && length(aliased) == ncol(X)) {
attr(X, "aliased") <- aliased
}
if (!is.null(term_labels)) {
attr(X, "term_labels") <- term_labels
}
}
attr(X, "rank") <- qr(X)[["rank"]]
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.