|
9 | 9 | #' |
10 | 10 | #' **performance** provides posterior predictive check methods for a variety |
11 | 11 | #' of frequentist models (e.g., `lm`, `merMod`, `glmmTMB`, ...). For Bayesian |
12 | | -#' models, the model is passed to [`bayesplot::pp_check()`]. |
| 12 | +#' models, posterior predictions are computed with |
| 13 | +#' `modelbased::estimate_prediction()` and plotted with the same machinery as |
| 14 | +#' for other supported models. |
13 | 15 | #' |
14 | 16 | #' If `check_predictions()` doesn't work as expected, try setting |
15 | 17 | #' `verbose = TRUE` to get hints about possible problems. |
|
38 | 40 | #' @param verbose Toggle warnings. |
39 | 41 | #' @param ... Additional arguments passed on to downstream functions. For |
40 | 42 | #' frequentist models, these are forwarded to `simulate()`; for Bayesian models |
41 | | -#' (e.g., `stanreg`, `brmsfit`), they are forwarded to `bayesplot::pp_check()`. |
| 43 | +#' (e.g., `stanreg`, `brmsfit`), they are forwarded to |
| 44 | +#' `modelbased::estimate_prediction()`. |
42 | 45 | #' @param object Deprecated, please use `model` instead. |
43 | 46 | #' |
44 | 47 | #' @return A data frame of simulated responses and the original response vector. |
@@ -203,57 +206,50 @@ check_predictions.stanreg <- function( |
203 | 206 | c("density", "discrete_dots", "discrete_interval", "discrete_both") |
204 | 207 | ) |
205 | 208 |
|
206 | | - # convert to type-argument for pp_check |
207 | | - pp_type <- switch(type, density = "dens", "bars") |
208 | | - |
209 | 209 | insight::check_if_installed( |
210 | | - "bayesplot", |
211 | | - "to create posterior prediction plots for Stan models" |
| 210 | + "modelbased", |
| 211 | + "to create posterior predictive checks for Bayesian models" |
212 | 212 | ) |
213 | 213 |
|
214 | | - # for plotting |
215 | | - resp_string <- insight::find_terms(model)$response |
| 214 | + out <- modelbased::estimate_prediction( |
| 215 | + model, |
| 216 | + iterations = iterations, |
| 217 | + keep_iterations = TRUE, |
| 218 | + re_formula = re_formula, |
| 219 | + verbose = verbose, |
| 220 | + ... |
| 221 | + ) |
216 | 222 |
|
217 | | - if (inherits(model, "brmsfit")) { |
218 | | - out <- as.data.frame( |
219 | | - bayesplot::pp_check(model, type = pp_type, ndraws = iterations, ...)$data |
220 | | - ) |
221 | | - } else { |
222 | | - out <- as.data.frame( |
223 | | - bayesplot::pp_check(model, plotfun = pp_type, nreps = iterations, ...)$data |
| 223 | + iter_columns <- startsWith(colnames(out), "iter_") |
| 224 | + if (!any(iter_columns)) { |
| 225 | + insight::format_error( |
| 226 | + "Could not retrieve posterior predictive draws for the Bayesian model." |
224 | 227 | ) |
225 | 228 | } |
226 | 229 |
|
227 | | - # bring data into shape, like we have for other models with `check_predictions()` |
228 | | - if (pp_type == "dens") { |
229 | | - d_filter <- out[!out$is_y, ] |
230 | | - d_filter <- datawizard::data_to_wide( |
231 | | - d_filter, |
232 | | - id_cols = "y_id", |
233 | | - values_from = "value", |
234 | | - names_from = "rep_id" |
235 | | - ) |
236 | | - d_filter$y_id <- NULL |
237 | | - colnames(d_filter) <- paste0("sim_", colnames(d_filter)) |
238 | | - d_filter$y <- out$value[out$is_y] |
239 | | - out <- d_filter |
240 | | - } else { |
241 | | - colnames(out) <- c("x", "y", "CI_low", "Mean", "CI_high") |
242 | | - # to long, for plotting |
243 | | - out <- datawizard::data_to_long( |
244 | | - out, |
245 | | - select = c("y", "Mean"), |
246 | | - names_to = "Group", |
247 | | - values_to = "Count" |
248 | | - ) |
| 230 | + out <- as.data.frame(out[iter_columns]) |
| 231 | + colnames(out) <- sub("^iter_", "sim_", colnames(out)) |
| 232 | + |
| 233 | + resp_string <- insight::find_terms(model)$response |
| 234 | + pattern <- "^(scale|exp|expm1|log|log1p|log10|log2|sqrt)" |
| 235 | + |
| 236 | + if ( |
| 237 | + !is.null(resp_string) && |
| 238 | + length(resp_string) == 1 && |
| 239 | + grepl(paste0(pattern, "\\("), resp_string) |
| 240 | + ) { |
| 241 | + out <- .backtransform_sims(out, resp_string) |
249 | 242 | } |
250 | 243 |
|
251 | | - # make x cateogorical for bernoulli/categorical/multinomial models |
252 | | - if (minfo$is_bernoulli || minfo$is_categorical || minfo$is_multinomial) { |
253 | | - out$x <- as.factor(out$x) |
| 244 | + response <- insight::get_response(model) |
| 245 | + if (is.data.frame(response)) { |
| 246 | + response <- eval( |
| 247 | + str2lang(insight::find_response(model)), |
| 248 | + envir = insight::get_response(model) |
| 249 | + ) |
254 | 250 | } |
| 251 | + out$y <- response |
255 | 252 |
|
256 | | - attr(out, "is_stan") <- TRUE |
257 | 253 | attr(out, "check_range") <- check_range |
258 | 254 | attr(out, "response_name") <- resp_string |
259 | 255 | attr(out, "bandwidth") <- bandwidth |
|
0 commit comments