From f480287292e4ea2d14551a4e2fad161379035522 Mon Sep 17 00:00:00 2001 From: jgabry Date: Wed, 17 Jan 2024 13:51:44 -0700 Subject: [PATCH 01/12] Start preparing release of v1.11.0 --- DESCRIPTION | 4 ++-- NEWS.md | 8 ++++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index 6f678f82..74965a85 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,8 +1,8 @@ Package: bayesplot Type: Package Title: Plotting for Bayesian Models -Version: 1.10.0.9001 -Date: 2023-03-16 +Version: 1.11.0 +Date: 2024-01-17 Authors@R: c(person("Jonah", "Gabry", role = c("aut", "cre"), email = "jsg2201@columbia.edu"), person("Tristan", "Mahr", role = "aut"), person("Paul-Christian", "Bürkner", role = "ctb"), diff --git a/NEWS.md b/NEWS.md index ab8e6cb9..edad40e4 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,8 +1,12 @@ -# bayesplot 1.10.0.9000 +# bayesplot 1.11.0 -* Items for next release here +* Add 'bins' argument to many histogram plots by @paul-buerkner in #300 +* Update for new ggplot2 release by @teunbrand in #309 +* Follow ggplot2 updates on facet_grid() and facet_wrap() by @heavywatal in #305 +* Better loo_pit_qq plots by @avehtari in #307 +* Check `prob` is numeric for intervals plots by @tony-stone in #299 # bayesplot 1.10.0 From cbf7ccec15e86b449342d656f2fb955660295041 Mon Sep 17 00:00:00 2001 From: jgabry Date: Wed, 17 Jan 2024 14:02:42 -0700 Subject: [PATCH 02/12] bump ggplot and ggridges versions --- DESCRIPTION | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index 74965a85..f95748e8 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -29,8 +29,8 @@ Depends: R (>= 3.1.0) Imports: dplyr (>= 0.8.0), - ggplot2 (>= 3.0.0), - ggridges, + ggplot2 (>= 3.4.0), + ggridges (>= 0.5.5), glue, posterior, reshape2, From 4e34fb087596c594bca95706a52b1b99e63280f3 Mon Sep 17 00:00:00 2001 From: jgabry Date: Wed, 17 Jan 2024 14:02:52 -0700 Subject: [PATCH 03/12] more linewidth --- R/mcmc-intervals.R | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/R/mcmc-intervals.R b/R/mcmc-intervals.R index 8ac5e97b..24aa52f2 100644 --- a/R/mcmc-intervals.R +++ b/R/mcmc-intervals.R @@ -384,9 +384,9 @@ mcmc_areas <- function(x, } if (!is.null(border_size)) { - args_bottom$size <- border_size - args_outer$size <- border_size - args_inner$size <- border_size + args_bottom$linewidth <- border_size + args_outer$linewidth <- border_size + args_inner$linewidth <- border_size } if (color_by_rhat) { @@ -504,7 +504,7 @@ mcmc_areas_ridges <- function(x, stat = "identity" ) if (!is.null(border_size)) { - args_outer$size <- border_size + args_outer$linewidth <- border_size } layer_outer <- do.call(ggridges::geom_density_ridges, args_outer) @@ -545,7 +545,7 @@ mcmc_areas_ridges <- function(x, stat = "identity") if (!is.null(border_size)) { - args_inner$size <- border_size + args_inner$linewidth <- border_size } layer_list_inner[[par_num]] <- do.call(ggridges::geom_ridgeline, args_inner) From ea8df351ec70d534c6ae1a803ee18711f860c226 Mon Sep 17 00:00:00 2001 From: jgabry Date: Wed, 17 Jan 2024 15:21:03 -0700 Subject: [PATCH 04/12] Update visual-mcmc-diagnostics.Rmd --- vignettes/visual-mcmc-diagnostics.Rmd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vignettes/visual-mcmc-diagnostics.Rmd b/vignettes/visual-mcmc-diagnostics.Rmd index 348ec25f..d11db1de 100644 --- a/vignettes/visual-mcmc-diagnostics.Rmd +++ b/vignettes/visual-mcmc-diagnostics.Rmd @@ -154,7 +154,7 @@ schools_mod_ncp <- stan_model("schools_mod_ncp.stan") We then fit the model by calling Stan's MCMC algorithm using the `sampling` function (the increased `adapt_delta` param is to make the sampler a bit more "careful" and avoid false positive divergences), ```{r fit-models-hidden, results='hide', message=FALSE} -fit_cp <- sampling(schools_mod_cp, data = schools_dat, seed = 803214053, control = list(adapt_delta = 0.9)) +fit_cp <- sampling(schools_mod_cp, data = schools_dat, seed = 803214054, control = list(adapt_delta = 0.9)) fit_ncp <- sampling(schools_mod_ncp, data = schools_dat, seed = 457721433, control = list(adapt_delta = 0.9)) ``` and extract a `iterations x chains x parameters` array of posterior draws with From 5e51826cacd5ae5277fc43bec4f61d8301361b32 Mon Sep 17 00:00:00 2001 From: jgabry Date: Wed, 17 Jan 2024 15:29:33 -0700 Subject: [PATCH 05/12] trying fixing R cmd check NOTE --- R/helpers-mcmc.R | 10 +++++----- R/mcmc-diagnostics.R | 6 +++--- tests/testthat/test-helpers-mcmc.R | 4 ++-- vignettes/visual-mcmc-diagnostics.Rmd | 2 +- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/R/helpers-mcmc.R b/R/helpers-mcmc.R index 72458006..0111c2f5 100644 --- a/R/helpers-mcmc.R +++ b/R/helpers-mcmc.R @@ -51,13 +51,13 @@ prepare_mcmc_array <- function(x, if (is.matrix(x)) { x <- x[, pars, drop=FALSE] if (length(transformations)) { - x <- apply_transformations(x, transformations) + x <- apply_transformations(x, transformations = transformations) } x <- array(x, dim = c(nrow(x), 1, ncol(x))) } else { x <- x[, , pars, drop = FALSE] if (length(transformations)) { - x <- apply_transformations(x, transformations) + x <- apply_transformations(x, transformations = transformations) } } @@ -388,10 +388,10 @@ validate_transformations <- #' functions. #' @return x, with tranformations having been applied to some parameters. #' -apply_transformations <- function(x, transformations = list(), ...) { +apply_transformations <- function(x, ...) { UseMethod("apply_transformations") } -apply_transformations.matrix <- function(x, transformations = list()) { +apply_transformations.matrix <- function(x, ..., transformations = list()) { pars <- colnames(x) x_transforms <- validate_transformations(transformations, pars) for (p in names(x_transforms)) { @@ -400,7 +400,7 @@ apply_transformations.matrix <- function(x, transformations = list()) { x } -apply_transformations.array <- function(x, transformations = list()) { +apply_transformations.array <- function(x, ..., transformations = list()) { stopifnot(length(dim(x)) == 3) pars <- dimnames(x)[[3]] x_transforms <- validate_transformations(transformations, pars) diff --git a/R/mcmc-diagnostics.R b/R/mcmc-diagnostics.R index 23960f15..4e5ec767 100644 --- a/R/mcmc-diagnostics.R +++ b/R/mcmc-diagnostics.R @@ -360,17 +360,17 @@ mcmc_acf_bar <- #' `x <= breaks[1]`, `breaks[1] < x <= breaks[2]`, `x > breaks[2]`). #' @return A factor the same length as `x` with three levels. #' @noRd -diagnostic_factor <- function(x, breaks, ...) { +diagnostic_factor <- function(x, ...) { UseMethod("diagnostic_factor") } -diagnostic_factor.rhat <- function(x, breaks = c(1.05, 1.1)) { +diagnostic_factor.rhat <- function(x, ..., breaks = c(1.05, 1.1)) { cut(x, breaks = c(-Inf, breaks, Inf), labels = c("low", "ok", "high"), ordered_result = FALSE) } -diagnostic_factor.neff_ratio <- function(x, breaks = c(0.1, 0.5)) { +diagnostic_factor.neff_ratio <- function(x, ..., breaks = c(0.1, 0.5)) { cut(x, breaks = c(-Inf, breaks, Inf), labels = c("low", "ok", "high"), ordered_result = FALSE) diff --git a/tests/testthat/test-helpers-mcmc.R b/tests/testthat/test-helpers-mcmc.R index f346f420..3f181426 100644 --- a/tests/testthat/test-helpers-mcmc.R +++ b/tests/testthat/test-helpers-mcmc.R @@ -193,11 +193,11 @@ test_that("validate_transformations throws correct errors", { test_that("apply_transformations works", { trans <- list('beta[1]' = "exp", sigma = function(x) x^2) - arr_trans <- apply_transformations(arr, trans) + arr_trans <- apply_transformations(arr, transformations = trans) expect_equal(arr_trans[,, "sigma"], arr[,, "sigma"]^2) expect_equal(arr_trans[,, "beta[1]"], exp(arr[,, "beta[1]"])) - mat_trans <- apply_transformations(mat, trans) + mat_trans <- apply_transformations(mat, transformations = trans) expect_equal(mat_trans[, "sigma"], mat[, "sigma"]^2) expect_equal(mat_trans[, "beta[1]"], exp(mat[, "beta[1]"])) }) diff --git a/vignettes/visual-mcmc-diagnostics.Rmd b/vignettes/visual-mcmc-diagnostics.Rmd index d11db1de..b1358dd3 100644 --- a/vignettes/visual-mcmc-diagnostics.Rmd +++ b/vignettes/visual-mcmc-diagnostics.Rmd @@ -154,7 +154,7 @@ schools_mod_ncp <- stan_model("schools_mod_ncp.stan") We then fit the model by calling Stan's MCMC algorithm using the `sampling` function (the increased `adapt_delta` param is to make the sampler a bit more "careful" and avoid false positive divergences), ```{r fit-models-hidden, results='hide', message=FALSE} -fit_cp <- sampling(schools_mod_cp, data = schools_dat, seed = 803214054, control = list(adapt_delta = 0.9)) +fit_cp <- sampling(schools_mod_cp, data = schools_dat, seed = 803214055, control = list(adapt_delta = 0.9)) fit_ncp <- sampling(schools_mod_ncp, data = schools_dat, seed = 457721433, control = list(adapt_delta = 0.9)) ``` and extract a `iterations x chains x parameters` array of posterior draws with From 4073d39f9e2f68e659f181d37de418c977555e4b Mon Sep 17 00:00:00 2001 From: jgabry Date: Wed, 17 Jan 2024 16:35:00 -0700 Subject: [PATCH 06/12] allow psis_object for all ppc_loo_* plots fixes #294 --- R/ppc-loo.R | 69 +++++++++++++++++++++++------------ man/PPC-loo.Rd | 52 ++++++++++++++------------ tests/testthat/test-ppc-loo.R | 17 ++++++--- 3 files changed, 85 insertions(+), 53 deletions(-) diff --git a/R/ppc-loo.R b/R/ppc-loo.R index bbdf64d9..146c5d9a 100644 --- a/R/ppc-loo.R +++ b/R/ppc-loo.R @@ -10,7 +10,11 @@ #' @param ... Currently unused. #' @param lw A matrix of (smoothed) log weights with the same dimensions as #' `yrep`. See [loo::psis()] and the associated `weights()` method as well as -#' the **Examples** section, below. +#' the **Examples** section, below. If `lw` is not specified then +#' `psis_object` can be provided and log weights will be extracted. +#' @param psis_object If using **loo** version `2.0.0` or greater, an +#' object returned by the `psis()` function (or by the `loo()` function +#' with argument `save_psis` set to `TRUE`). #' @param alpha,size,fatten,linewidth Arguments passed to code geoms to control plot #' aesthetics. For `ppc_loo_pit_qq()` and `ppc_loo_pit_overlay()`, `size` and #' `alpha` are passed to [ggplot2::geom_point()] and @@ -71,7 +75,7 @@ #' log_radon ~ floor + log_uranium + floor:log_uranium #' + (1 + floor | county), #' data = radon, -#' iter = 1000, +#' iter = 100, #' chains = 2, #' cores = 2 #' ) @@ -89,6 +93,8 @@ #' ppc_loo_pit_qq(y, yrep, lw = lw) #' ppc_loo_pit_qq(y, yrep, lw = lw, compare = "normal") #' +#' # can use the psis object instead of lw +#' ppc_loo_pit_qq(y, yrep, psis_object = psis1) #' #' # loo predictive intervals vs observations #' keep_obs <- 1:50 @@ -138,8 +144,9 @@ NULL #' ppc_loo_pit_overlay <- function(y, yrep, - lw, + lw = NULL, ..., + psis_object = NULL, pit = NULL, samples = 100, size = 0.25, @@ -158,6 +165,7 @@ ppc_loo_pit_overlay <- function(y, y = y, yrep = yrep, lw = lw, + psis_object = psis_object, pit = pit, samples = samples, bw = bw, @@ -253,8 +261,9 @@ ppc_loo_pit_overlay <- function(y, ppc_loo_pit_data <- function(y, yrep, - lw, + lw = NULL, ..., + psis_object = NULL, pit = NULL, samples = 100, bw = "nrd0", @@ -267,6 +276,7 @@ ppc_loo_pit_data <- suggested_package("rstantools") y <- validate_y(y) yrep <- validate_predictions(yrep, length(y)) + lw <- .get_lw(lw, psis_object) stopifnot(identical(dim(yrep), dim(lw))) pit <- rstantools::loo_pit(object = yrep, y = y, lw = lw) } @@ -295,22 +305,24 @@ ppc_loo_pit_data <- #' @export ppc_loo_pit_qq <- function(y, yrep, - lw, - pit, - compare = c("uniform", "normal"), + lw = NULL, ..., + psis_object = NULL, + pit = NULL, + compare = c("uniform", "normal"), size = 2, alpha = 1) { check_ignored_arguments(...) compare <- match.arg(compare) - if (!missing(pit)) { + if (!is.null(pit)) { stopifnot(is.numeric(pit), is_vector_or_1Darray(pit)) inform("'pit' specified so ignoring 'y','yrep','lw' if specified.") } else { suggested_package("rstantools") y <- validate_y(y) yrep <- validate_predictions(yrep, length(y)) + lw <- .get_lw(lw, psis_object) stopifnot(identical(dim(yrep), dim(lw))) pit <- rstantools::loo_pit(object = yrep, y = y, lw = lw) } @@ -352,7 +364,7 @@ ppc_loo_pit <- function(y, yrep, lw, - pit, + pit = NULL, compare = c("uniform", "normal"), ..., size = 2, @@ -374,18 +386,14 @@ ppc_loo_pit <- #' @rdname PPC-loo #' @export #' @template args-prob-prob_outer -#' @param psis_object If using **loo** version `2.0.0` or greater, an -#' object returned by the `psis()` function (or by the `loo()` function -#' with argument `save_psis` set to `TRUE`). -#' @param intervals For `ppc_loo_intervals()` and `ppc_loo_ribbon()`, -#' optionally a matrix of precomputed LOO predictive intervals -#' that can be specified instead of `yrep` and `lw` (these are both -#' ignored if `intervals` is specified). If not specified the intervals -#' are computed internally before plotting. If specified, `intervals` -#' must be a matrix with number of rows equal to the number of data points and -#' five columns in the following order: lower outer interval, lower inner -#' interval, median (50%), upper inner interval and upper outer interval -#' (column names are ignored). +#' @param intervals For `ppc_loo_intervals()` and `ppc_loo_ribbon()`, optionally +#' a matrix of pre-computed LOO predictive intervals that can be specified +#' instead of `yrep` ( ignored if `intervals` is specified). If not specified +#' the intervals are computed internally before plotting. If specified, +#' `intervals` must be a matrix with number of rows equal to the number of +#' data points and five columns in the following order: lower outer interval, +#' lower inner interval, median (50%), upper inner interval and upper outer +#' interval (column names are ignored). #' @param order For `ppc_loo_intervals()`, a string indicating how to arrange #' the plotted intervals. The default (`"index"`) is to plot them in the #' order of the observations. The alternative (`"median"`) arranges them @@ -403,9 +411,9 @@ ppc_loo_intervals <- function(y, yrep, psis_object, + ..., subset = NULL, intervals = NULL, - ..., prob = 0.5, prob_outer = 0.9, alpha = 0.33, @@ -498,11 +506,10 @@ ppc_loo_intervals <- ppc_loo_ribbon <- function(y, yrep, - lw, psis_object, + ..., subset = NULL, intervals = NULL, - ..., prob = 0.5, prob_outer = 0.9, alpha = 0.33, @@ -720,3 +727,17 @@ ppc_loo_ribbon <- list(xs = xs, unifs = bc_mat) } + +# Extract log weights from psis_object if provided +.get_lw <- function(lw = NULL, psis_object = NULL) { + if (is.null(lw) && is.null(psis_object)) { + abort("One of 'lw' and 'psis_object' must be specified.") + } else if (is.null(lw)) { + suggested_package("loo", min_version = "2.0.0") + if (!loo::is.psis(psis_object)) { + abort("If specified, 'psis_object' must be a PSIS object from the loo package.") + } + lw <- loo::weights.importance_sampling(psis_object) + } + lw +} diff --git a/man/PPC-loo.Rd b/man/PPC-loo.Rd index 4dee3286..288beb49 100644 --- a/man/PPC-loo.Rd +++ b/man/PPC-loo.Rd @@ -13,8 +13,9 @@ ppc_loo_pit_overlay( y, yrep, - lw, + lw = NULL, ..., + psis_object = NULL, pit = NULL, samples = 100, size = 0.25, @@ -31,8 +32,9 @@ ppc_loo_pit_overlay( ppc_loo_pit_data( y, yrep, - lw, + lw = NULL, ..., + psis_object = NULL, pit = NULL, samples = 100, bw = "nrd0", @@ -43,10 +45,11 @@ ppc_loo_pit_data( ppc_loo_pit_qq( y, yrep, - lw, - pit, - compare = c("uniform", "normal"), + lw = NULL, ..., + psis_object = NULL, + pit = NULL, + compare = c("uniform", "normal"), size = 2, alpha = 1 ) @@ -55,7 +58,7 @@ ppc_loo_pit( y, yrep, lw, - pit, + pit = NULL, compare = c("uniform", "normal"), ..., size = 2, @@ -66,9 +69,9 @@ ppc_loo_intervals( y, yrep, psis_object, + ..., subset = NULL, intervals = NULL, - ..., prob = 0.5, prob_outer = 0.9, alpha = 0.33, @@ -81,11 +84,10 @@ ppc_loo_intervals( ppc_loo_ribbon( y, yrep, - lw, psis_object, + ..., subset = NULL, intervals = NULL, - ..., prob = 0.5, prob_outer = 0.9, alpha = 0.33, @@ -105,10 +107,15 @@ additional advice specific to particular plots.} \item{lw}{A matrix of (smoothed) log weights with the same dimensions as \code{yrep}. See \code{\link[loo:psis]{loo::psis()}} and the associated \code{weights()} method as well as -the \strong{Examples} section, below.} +the \strong{Examples} section, below. If \code{lw} is not specified then +\code{psis_object} can be provided and log weights will be extracted.} \item{...}{Currently unused.} +\item{psis_object}{If using \strong{loo} version \verb{2.0.0} or greater, an +object returned by the \code{psis()} function (or by the \code{loo()} function +with argument \code{save_psis} set to \code{TRUE}).} + \item{pit}{For \code{ppc_loo_pit_overlay()} and \code{ppc_loo_pit_qq()}, optionally a vector of precomputed PIT values that can be specified instead of \code{y}, \code{yrep}, and \code{lw} (these are all ignored if \code{pit} is specified). If not @@ -153,10 +160,6 @@ compares computed PIT values to the standard uniform distribution. If calculated from the PIT values to the theoretical standard normal quantiles.} -\item{psis_object}{If using \strong{loo} version \verb{2.0.0} or greater, an -object returned by the \code{psis()} function (or by the \code{loo()} function -with argument \code{save_psis} set to \code{TRUE}).} - \item{subset}{For \code{ppc_loo_intervals()} and \code{ppc_loo_ribbon()}, an optional integer vector indicating which observations in \code{y} (and \code{yrep}) to include. Dropping observations from \code{y} and \code{yrep} manually before passing @@ -166,15 +169,14 @@ are passed along with \code{subset} then \strong{bayesplot} can do the subsettin internally for \code{y}, \code{yrep} \emph{and} \code{psis_object}. See the \strong{Examples} section for a demonstration.} -\item{intervals}{For \code{ppc_loo_intervals()} and \code{ppc_loo_ribbon()}, -optionally a matrix of precomputed LOO predictive intervals -that can be specified instead of \code{yrep} and \code{lw} (these are both -ignored if \code{intervals} is specified). If not specified the intervals -are computed internally before plotting. If specified, \code{intervals} -must be a matrix with number of rows equal to the number of data points and -five columns in the following order: lower outer interval, lower inner -interval, median (50\%), upper inner interval and upper outer interval -(column names are ignored).} +\item{intervals}{For \code{ppc_loo_intervals()} and \code{ppc_loo_ribbon()}, optionally +a matrix of pre-computed LOO predictive intervals that can be specified +instead of \code{yrep} ( ignored if \code{intervals} is specified). If not specified +the intervals are computed internally before plotting. If specified, +\code{intervals} must be a matrix with number of rows equal to the number of +data points and five columns in the following order: lower outer interval, +lower inner interval, median (50\%), upper inner interval and upper outer +interval (column names are ignored).} \item{prob, prob_outer}{Values between \code{0} and \code{1} indicating the desired probability mass to include in the inner and outer intervals. The defaults @@ -240,7 +242,7 @@ fit <- stan_lmer( log_radon ~ floor + log_uranium + floor:log_uranium + (1 + floor | county), data = radon, - iter = 1000, + iter = 100, chains = 2, cores = 2 ) @@ -258,6 +260,8 @@ ppc_loo_pit_overlay(y, yrep, lw = lw) ppc_loo_pit_qq(y, yrep, lw = lw) ppc_loo_pit_qq(y, yrep, lw = lw, compare = "normal") +# can use the psis object instead of lw +ppc_loo_pit_qq(y, yrep, psis_object = psis1) # loo predictive intervals vs observations keep_obs <- 1:50 diff --git a/tests/testthat/test-ppc-loo.R b/tests/testthat/test-ppc-loo.R index c73838f9..878d9389 100644 --- a/tests/testthat/test-ppc-loo.R +++ b/tests/testthat/test-ppc-loo.R @@ -35,6 +35,7 @@ test_that("ppc_loo_pit_overlay returns ggplot object", { skip_if_not_installed("rstanarm") skip_if_not_installed("loo") expect_gg(ppc_loo_pit_overlay(y, yrep, lw, samples = 25)) + expect_gg(ppc_loo_pit_overlay(y, yrep, psis_object = psis1, samples = 25)) }) test_that("ppc_loo_pit_overlay warns about binary data", { @@ -65,9 +66,11 @@ test_that("ppc_loo_pit_qq returns ggplot object", { skip_if_not_installed("rstanarm") skip_if_not_installed("loo") expect_gg(p1 <- ppc_loo_pit_qq(y, yrep, lw)) + expect_gg(p2 <- ppc_loo_pit_qq(y, yrep, psis_object = psis1)) expect_equal(p1$labels$x, "Uniform") - expect_gg(p2 <- ppc_loo_pit_qq(y, yrep, lw, compare = "normal")) - expect_equal(p2$labels$x, "Normal") + expect_equal(p1$data, p2$data) + expect_gg(p3 <- ppc_loo_pit_qq(y, yrep, lw, compare = "normal")) + expect_equal(p3$labels$x, "Normal") }) test_that("ppc_loo_pit functions work when pit specified instead of y,yrep,lw", { @@ -75,11 +78,16 @@ test_that("ppc_loo_pit functions work when pit specified instead of y,yrep,lw", skip_if_not_installed("loo") expect_gg(ppc_loo_pit_qq(pit = pits)) expect_message( - ppc_loo_pit_qq(y = y, yrep = yrep, lw = lw, pit = pits), + p1 <- ppc_loo_pit_qq(y = y, yrep = yrep, lw = lw, pit = pits), "'pit' specified so ignoring 'y','yrep','lw' if specified" ) + expect_message( + p2 <- ppc_loo_pit_qq(pit = pits) + ) + expect_equal(p1$data, p2$data) - expect_gg(ppc_loo_pit_overlay(pit = pits)) + + expect_gg(p1 <- ppc_loo_pit_overlay(pit = pits)) expect_message( ppc_loo_pit_overlay(y = y, yrep = yrep, lw = lw, pit = pits), "'pit' specified so ignoring 'y','yrep','lw' if specified" @@ -87,7 +95,6 @@ test_that("ppc_loo_pit functions work when pit specified instead of y,yrep,lw", }) - test_that("ppc_loo_intervals returns ggplot object", { skip_if_not_installed("rstanarm") skip_if_not_installed("loo") From 2072a235de7de35255bfbec4c1a15e092a276789 Mon Sep 17 00:00:00 2001 From: jgabry Date: Wed, 17 Jan 2024 21:34:45 -0700 Subject: [PATCH 07/12] Update NEWS.md --- NEWS.md | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/NEWS.md b/NEWS.md index edad40e4..1d83708c 100644 --- a/NEWS.md +++ b/NEWS.md @@ -2,11 +2,9 @@ # bayesplot 1.11.0 -* Add 'bins' argument to many histogram plots by @paul-buerkner in #300 -* Update for new ggplot2 release by @teunbrand in #309 -* Follow ggplot2 updates on facet_grid() and facet_wrap() by @heavywatal in #305 -* Better loo_pit_qq plots by @avehtari in #307 -* Check `prob` is numeric for intervals plots by @tony-stone in #299 +ADD ANYTHING COMMITTED DIRECTLY TO PR FOR RELEASE (e.g. psis_object argument) + +ADD AUTO-GENERATED RELEASE NOTES # bayesplot 1.10.0 From 4ec0743118857dc1cf3c4189ac249b31b2a5b682 Mon Sep 17 00:00:00 2001 From: jgabry Date: Mon, 22 Jan 2024 09:41:24 -0700 Subject: [PATCH 08/12] fix extra space --- R/ppc-loo.R | 2 +- man/PPC-loo.Rd | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/R/ppc-loo.R b/R/ppc-loo.R index 146c5d9a..b81d4ec3 100644 --- a/R/ppc-loo.R +++ b/R/ppc-loo.R @@ -388,7 +388,7 @@ ppc_loo_pit <- #' @template args-prob-prob_outer #' @param intervals For `ppc_loo_intervals()` and `ppc_loo_ribbon()`, optionally #' a matrix of pre-computed LOO predictive intervals that can be specified -#' instead of `yrep` ( ignored if `intervals` is specified). If not specified +#' instead of `yrep` (ignored if `intervals` is specified). If not specified #' the intervals are computed internally before plotting. If specified, #' `intervals` must be a matrix with number of rows equal to the number of #' data points and five columns in the following order: lower outer interval, diff --git a/man/PPC-loo.Rd b/man/PPC-loo.Rd index 288beb49..58e6a7fd 100644 --- a/man/PPC-loo.Rd +++ b/man/PPC-loo.Rd @@ -171,7 +171,7 @@ section for a demonstration.} \item{intervals}{For \code{ppc_loo_intervals()} and \code{ppc_loo_ribbon()}, optionally a matrix of pre-computed LOO predictive intervals that can be specified -instead of \code{yrep} ( ignored if \code{intervals} is specified). If not specified +instead of \code{yrep} (ignored if \code{intervals} is specified). If not specified the intervals are computed internally before plotting. If specified, \code{intervals} must be a matrix with number of rows equal to the number of data points and five columns in the following order: lower outer interval, From bc95195a7a513389b4e15bb3334b0eb23a75847b Mon Sep 17 00:00:00 2001 From: jgabry Date: Mon, 22 Jan 2024 10:02:00 -0700 Subject: [PATCH 09/12] Update NEWS.md --- NEWS.md | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/NEWS.md b/NEWS.md index bd52a85a..55275753 100644 --- a/NEWS.md +++ b/NEWS.md @@ -2,12 +2,15 @@ # bayesplot 1.11.0 -ADD ANYTHING COMMITTED DIRECTLY TO PR FOR RELEASE (e.g. psis_object argument) - -ADD AUTO-GENERATED RELEASE NOTES - -* `ppc_pit_ecdf()` and `ppc_pit_ecdf_grouped()` now support discrete variables, and their default method for selecting the number of ECDF evaluation points has been updated. -* Items for next release here +* Update for new ggplot2 release by @teunbrand in #309 +* Add `bins` argument to many histogram plots by @paul-buerkner in #300 +* Follow ggplot2 updates on `facet_grid()` and `facet_wrap()` by @heavywatal in #305 +* Better `ppc_loo_pit_qq` plots by @avehtari in #307 +* Check `prob` is numeric for intervals plots by @tony-stone in #299 +* Add `bins` and `breaks` arguments to more histogram and hex plots by @heavywatal in #313 +* Replace `size` argument with `linewidth` for `geom_line` and `geom_ridgeline` by @heavywatal in #314 +* All LOO plots now accept `psis_object` argument by @jgabry in #311 +* `ppc_pit_ecdf()` and `ppc_pit_ecdf_grouped()` now support discrete variables, and their default method for selecting the number of ECDF evaluation points has been updated. by @TeemuSailynoja in #316 # bayesplot 1.10.0 From e4908c23287d3952ef4b0dba204d5cff1d8e48ff Mon Sep 17 00:00:00 2001 From: jgabry Date: Mon, 22 Jan 2024 10:03:02 -0700 Subject: [PATCH 10/12] Update DESCRIPTION --- DESCRIPTION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DESCRIPTION b/DESCRIPTION index 2d1c4ab3..d1a40d6a 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -2,7 +2,7 @@ Package: bayesplot Type: Package Title: Plotting for Bayesian Models Version: 1.11.0 -Date: 2024-01-17 +Date: 2024-01-22 Authors@R: c(person("Jonah", "Gabry", role = c("aut", "cre"), email = "jsg2201@columbia.edu"), person("Tristan", "Mahr", role = "aut"), person("Paul-Christian", "Bürkner", role = "ctb"), From 3a2516719bd1c766e32876428170f4179eabb06e Mon Sep 17 00:00:00 2001 From: jgabry Date: Mon, 22 Jan 2024 10:34:37 -0700 Subject: [PATCH 11/12] register internal s3 methods (doesn't actually export them) see https://github.com/r-lib/roxygen2/issues/1175 --- NAMESPACE | 15 +++++++++++++++ R/helpers-mcmc.R | 17 +++++++++++++++++ R/mcmc-diagnostics.R | 2 ++ R/ppc-discrete.R | 2 +- 4 files changed, 35 insertions(+), 1 deletion(-) diff --git a/NAMESPACE b/NAMESPACE index 6efe6d01..7fe559c6 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -2,16 +2,31 @@ S3method("[",neff_ratio) S3method("[",rhat) +S3method(apply_transformations,array) +S3method(apply_transformations,matrix) +S3method(diagnostic_factor,neff_ratio) +S3method(diagnostic_factor,rhat) S3method(log_posterior,CmdStanMCMC) S3method(log_posterior,stanfit) S3method(log_posterior,stanreg) +S3method(melt_mcmc,matrix) +S3method(melt_mcmc,mcmc_array) S3method(neff_ratio,CmdStanMCMC) S3method(neff_ratio,stanfit) S3method(neff_ratio,stanreg) +S3method(num_chains,data.frame) +S3method(num_chains,mcmc_array) +S3method(num_iters,data.frame) +S3method(num_iters,mcmc_array) +S3method(num_params,data.frame) +S3method(num_params,mcmc_array) S3method(nuts_params,CmdStanMCMC) S3method(nuts_params,list) S3method(nuts_params,stanfit) S3method(nuts_params,stanreg) +S3method(parameter_names,array) +S3method(parameter_names,default) +S3method(parameter_names,matrix) S3method(plot,bayesplot_grid) S3method(plot,bayesplot_scheme) S3method(pp_check,default) diff --git a/R/helpers-mcmc.R b/R/helpers-mcmc.R index 0111c2f5..41e2c4ee 100644 --- a/R/helpers-mcmc.R +++ b/R/helpers-mcmc.R @@ -124,6 +124,8 @@ select_parameters <- #' @return A molten data frame. #' melt_mcmc <- function(x, ...) UseMethod("melt_mcmc") + +#' @export melt_mcmc.mcmc_array <- function(x, varnames = c("Iteration", "Chain", "Parameter"), @@ -144,6 +146,7 @@ melt_mcmc.mcmc_array <- function(x, } # If all chains are already merged +#' @export melt_mcmc.matrix <- function(x, varnames = c("Draw", "Parameter"), value.name = "Value", @@ -305,13 +308,17 @@ chain_list2array <- function(x) { # Get parameter names from a 3-D array parameter_names <- function(x) UseMethod("parameter_names") + +#' @export parameter_names.array <- function(x) { stopifnot(is_3d_array(x)) dimnames(x)[[3]] %||% abort("No parameter names found.") } +#' @export parameter_names.default <- function(x) { colnames(x) %||% abort("No parameter names found.") } +#' @export parameter_names.matrix <- function(x) { colnames(x) %||% abort("No parameter names found.") } @@ -391,6 +398,8 @@ validate_transformations <- apply_transformations <- function(x, ...) { UseMethod("apply_transformations") } + +#' @export apply_transformations.matrix <- function(x, ..., transformations = list()) { pars <- colnames(x) x_transforms <- validate_transformations(transformations, pars) @@ -400,6 +409,8 @@ apply_transformations.matrix <- function(x, ..., transformations = list()) { x } + +#' @export apply_transformations.array <- function(x, ..., transformations = list()) { stopifnot(length(dim(x)) == 3) pars <- dimnames(x)[[3]] @@ -437,17 +448,23 @@ num_chains <- function(x, ...) UseMethod("num_chains") num_iters <- function(x, ...) UseMethod("num_iters") num_params <- function(x, ...) UseMethod("num_params") +#' @export num_params.mcmc_array <- function(x, ...) dim(x)[3] +#' @export num_chains.mcmc_array <- function(x, ...) dim(x)[2] +#' @export num_iters.mcmc_array <- function(x, ...) dim(x)[1] +#' @export num_params.data.frame <- function(x, ...) { stopifnot("Parameter" %in% colnames(x)) length(unique(x$Parameter)) } +#' @export num_chains.data.frame <- function(x, ...) { stopifnot("Chain" %in% colnames(x)) length(unique(x$Chain)) } +#' @export num_iters.data.frame <- function(x, ...) { cols <- colnames(x) stopifnot("Iteration" %in% cols || "Draws" %in% cols) diff --git a/R/mcmc-diagnostics.R b/R/mcmc-diagnostics.R index 4e5ec767..a56be0bd 100644 --- a/R/mcmc-diagnostics.R +++ b/R/mcmc-diagnostics.R @@ -364,12 +364,14 @@ diagnostic_factor <- function(x, ...) { UseMethod("diagnostic_factor") } +#' @export diagnostic_factor.rhat <- function(x, ..., breaks = c(1.05, 1.1)) { cut(x, breaks = c(-Inf, breaks, Inf), labels = c("low", "ok", "high"), ordered_result = FALSE) } +#' @export diagnostic_factor.neff_ratio <- function(x, ..., breaks = c(0.1, 0.5)) { cut(x, breaks = c(-Inf, breaks, Inf), labels = c("low", "ok", "high"), diff --git a/R/ppc-discrete.R b/R/ppc-discrete.R index aff81251..89f6ee00 100644 --- a/R/ppc-discrete.R +++ b/R/ppc-discrete.R @@ -367,7 +367,7 @@ ppc_bars_data <- #' @param y,yrep,group User's already validated `y`, `yrep`, and (if applicable) #' `group` arguments. #' @param prob,freq User's `prob` and `freq` arguments. -#' @importFrom dplyr "%>%" ungroup count arrange mutate summarise across full_join rename all_of +#' @importFrom dplyr %>% ungroup count arrange mutate summarise across full_join rename all_of .ppc_bars_data <- function(y, yrep, group = NULL, prob = 0.9, freq = TRUE) { alpha <- (1 - prob) / 2 probs <- sort(c(alpha, 0.5, 1 - alpha)) From df741633b98dfb964d40569b647be75d770591dc Mon Sep 17 00:00:00 2001 From: jgabry Date: Tue, 30 Jan 2024 14:15:31 -0700 Subject: [PATCH 12/12] Update DESCRIPTION --- DESCRIPTION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DESCRIPTION b/DESCRIPTION index d1a40d6a..3d4bc6ff 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -2,7 +2,7 @@ Package: bayesplot Type: Package Title: Plotting for Bayesian Models Version: 1.11.0 -Date: 2024-01-22 +Date: 2024-01-30 Authors@R: c(person("Jonah", "Gabry", role = c("aut", "cre"), email = "jsg2201@columbia.edu"), person("Tristan", "Mahr", role = "aut"), person("Paul-Christian", "Bürkner", role = "ctb"),