1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150
|
#' Parameters bootstrapping
#'
#' Compute bootstrapped parameters and their related indices such as Confidence Intervals (CI) and p-values.
#'
#'
#' @param test The indices to compute. Character (vector) with one or more of
#' these options: `"p-value"` (or `"p"`), `"p_direction"` (or `"pd"`), `"rope"`,
#' `"p_map"`, `"equivalence_test"` (or `"equitest"`), `"bayesfactor"` (or `"bf"`)
#' or `"all"` to compute all tests. For each "test", the corresponding
#' **bayestestR** function is called (e.g. [bayestestR::rope()] or
#' [bayestestR::p_direction()]) and its results included in the summary output.
#' @param ... Arguments passed to other methods, like [`bootstrap_model()`] or
#' [`bayestestR::describe_posterior()`].
#' @inheritParams bootstrap_model
#' @inheritParams bayestestR::describe_posterior
#'
#' @return A data frame summarizing the bootstrapped parameters.
#'
#' @inheritSection bootstrap_model Using with **emmeans**
#'
#' @references
#' Davison, A. C., & Hinkley, D. V. (1997). Bootstrap methods and their
#' application (Vol. 1). Cambridge university press.
#'
#' @seealso [`bootstrap_model()`], [`simulate_parameters()`], [`simulate_model()`]
#'
#' @details This function first calls [`bootstrap_model()`] to generate
#' bootstrapped coefficients. The resulting replicated for each coefficient
#' are treated as "distribution", and is passed to [`bayestestR::describe_posterior()`]
#' to calculate the related indices defined in the `"test"` argument.
#'
#' Note that that p-values returned here are estimated under the assumption of
#' *translation equivariance*: that shape of the sampling distribution is
#' unaffected by the null being true or not. If this assumption does not hold,
#' p-values can be biased, and it is suggested to use proper permutation tests
#' to obtain non-parametric p-values.
#'
#' @examplesIf require("boot", quietly = TRUE) && require("emmeans", quietly = TRUE)
#' \donttest{
#' set.seed(2)
#' model <- lm(Sepal.Length ~ Species * Petal.Width, data = iris)
#' b <- bootstrap_parameters(model)
#' print(b)
#'
#' # different type of bootstrapping
#' set.seed(2)
#' b <- bootstrap_parameters(model, type = "balanced")
#' print(b)
#'
#' est <- emmeans::emmeans(b, trt.vs.ctrl ~ Species)
#' print(model_parameters(est))
#' }
#' @export
bootstrap_parameters <- function(model, ...) {
UseMethod("bootstrap_parameters")
}
# methods ----------------------------------------------------------------------
#' @rdname bootstrap_parameters
#' @export
bootstrap_parameters.default <- function(model,
iterations = 1000,
centrality = "median",
ci = 0.95,
ci_method = "quantile",
test = "p-value",
...) {
boot_data <- bootstrap_model(model, iterations = iterations, ...)
bootstrap_parameters(boot_data, centrality = centrality, ci = ci, ci_method = ci_method, test = test, ...)
}
#' @export
bootstrap_parameters.bootstrap_model <- function(model,
centrality = "median",
ci = 0.95,
ci_method = "quantile",
test = "p-value",
...) {
out <- .summary_bootstrap(
data = model,
test = test,
centrality = centrality,
ci = ci,
ci_method = ci_method,
...
)
class(out) <- c("bootstrap_parameters", "parameters_model", class(out))
attr(out, "boot_samples") <- model
out
}
#' @export
model_parameters.bootstrap_model <- bootstrap_parameters.bootstrap_model
# utilities --------------------------------------------------------------------
#' @keywords internal
.summary_bootstrap <- function(data, test, centrality, ci, ci_method, ...) {
# Is the p-value requested?
if (any(test %in% c("p-value", "p", "pval"))) {
p_value <- TRUE
test <- setdiff(test, c("p-value", "p", "pval"))
if (length(test) == 0) test <- NULL
} else {
p_value <- FALSE
}
parameters <- bayestestR::describe_posterior(
data,
centrality = centrality,
ci = ci,
ci_method = ci_method,
test = test,
...
)
# Remove unnecessary columns
if ("CI" %in% names(parameters) && insight::n_unique(parameters$CI) == 1) {
parameters$CI <- NULL
} else if ("CI" %in% names(parameters) && insight::n_unique(parameters$CI) > 1) {
parameters <- datawizard::reshape_ci(parameters)
}
# Coef
if (length(centrality) == 1) {
names(parameters)[names(parameters) == insight::format_capitalize(centrality)] <- "Coefficient"
}
# p-value
if (p_value) {
parameters$.row_order <- seq_len(nrow(parameters))
# calculate probability of direction, then convert to p.
p <- bayestestR::p_direction(data, null = 0, ...)
p$p <- as.numeric(bayestestR::pd_to_p(p$pd))
p$pd <- NULL
parameters <- merge(parameters, p, all = TRUE)
parameters <- parameters[order(parameters$.row_order), ]
parameters$.row_order <- NULL
}
rownames(parameters) <- NULL
attr(parameters, "ci") <- ci
parameters
}
|