From 17d32233e62177666cbcb69220df93b4c95c28e4 Mon Sep 17 00:00:00 2001 From: Utkarsh Date: Thu, 16 Apr 2026 22:45:16 +0530 Subject: [PATCH 1/3] Deprecate rhat() and neff_ratio() in favor of extract_rhat() and extract_neff_ratio() --- NAMESPACE | 14 +++--- NEWS.md | 1 + R/bayesplot-extractors.R | 70 +++++++++++++++++++++------ R/mcmc-diagnostics.R | 10 ++-- R/mcmc-intervals.R | 4 +- man/MCMC-diagnostics.Rd | 10 ++-- man/MCMC-intervals.Rd | 4 +- man/bayesplot-extractors.Rd | 39 ++++++++++----- tests/testthat/test-extractors.R | 44 +++++++++++------ vignettes/visual-mcmc-diagnostics.Rmd | 32 ++++++------ 10 files changed, 152 insertions(+), 76 deletions(-) diff --git a/NAMESPACE b/NAMESPACE index 99acd2974..eace1c691 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -6,14 +6,17 @@ S3method(apply_transformations,array) S3method(apply_transformations,matrix) S3method(diagnostic_factor,neff_ratio) S3method(diagnostic_factor,rhat) +S3method(extract_neff_ratio,CmdStanMCMC) +S3method(extract_neff_ratio,stanfit) +S3method(extract_neff_ratio,stanreg) +S3method(extract_rhat,CmdStanMCMC) +S3method(extract_rhat,stanfit) +S3method(extract_rhat,stanreg) 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) @@ -33,9 +36,6 @@ S3method(pp_check,default) S3method(print,bayesplot_function_list) S3method(print,bayesplot_grid) S3method(print,bayesplot_scheme) -S3method(rhat,CmdStanMCMC) -S3method(rhat,stanfit) -S3method(rhat,stanreg) export(abline_01) export(available_mcmc) export(available_ppc) @@ -53,6 +53,8 @@ export(example_mcmc_draws) export(example_x_data) export(example_y_data) export(example_yrep_draws) +export(extract_neff_ratio) +export(extract_rhat) export(facet_bg) export(facet_text) export(grid_lines) diff --git a/NEWS.md b/NEWS.md index 75d62cd8a..1f674aac4 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,5 +1,6 @@ # bayesplot (development version) +* Deprecated `rhat()` and `neff_ratio()` in favor of `extract_rhat()` and `extract_neff_ratio()` to avoid masking the same-named (but different) functions in the **posterior** package. The old names still work but emit a deprecation warning. (#295) * Fixed `validate_chain_list()` colnames check to compare all chains, not just the first two. * Added test verifying `legend_move("none")` behaves equivalently to `legend_none()`. * Added singleton-dimension edge-case tests for exported `_data()` functions. diff --git a/R/bayesplot-extractors.R b/R/bayesplot-extractors.R index fcaead662..40dc6e2f1 100644 --- a/R/bayesplot-extractors.R +++ b/R/bayesplot-extractors.R @@ -24,9 +24,16 @@ #' The data frame should have columns `"Parameter"` (factor), `"Iteration"` #' (integer), `"Chain"` (integer), and `"Value"` (numeric). See **Examples**, below. #' } -#' \item{`rhat()`, `neff_ratio()`}{ +#' \item{`extract_rhat()`, `extract_neff_ratio()`}{ #' Methods return (named) vectors. #' } +#' \item{`rhat()`, `neff_ratio()`}{ +#' `r lifecycle::badge("deprecated")` Use `extract_rhat()` and +#' `extract_neff_ratio()` instead. These names clashed with +#' [posterior::rhat()] and [posterior::ess_basic()] (and other ESS +#' functions), which caused confusion because the bayesplot versions +#' *extract* already-computed values rather than compute them. +#' } #' } #' #' @seealso [MCMC-nuts], [MCMC-diagnostics] @@ -60,17 +67,50 @@ log_posterior <- function(object, ...) { nuts_params <- function(object, ...) { UseMethod("nuts_params") } +# extract_rhat ------------------------------------------------------------- +#' @rdname bayesplot-extractors +#' @export +extract_rhat <- function(object, ...) { + UseMethod("extract_rhat") +} +# extract_neff_ratio ------------------------------------------------------- +#' @rdname bayesplot-extractors +#' @export +extract_neff_ratio <- function(object, ...) { + UseMethod("extract_neff_ratio") +} + # rhat ------------------------------------------------------------- #' @rdname bayesplot-extractors #' @export rhat <- function(object, ...) { - UseMethod("rhat") + lifecycle::deprecate_warn( + when = "1.16.0", + what = "rhat()", + with = "extract_rhat()", + details = paste( + "bayesplot's rhat() was renamed to extract_rhat() to make clear", + "it only extracts already-computed R-hat values (and to avoid", + "masking posterior::rhat(), which computes R-hat)." + ) + ) + extract_rhat(object, ...) } # neff_ratio ------------------------------------------------------------- #' @rdname bayesplot-extractors #' @export neff_ratio <- function(object, ...) { - UseMethod("neff_ratio") + lifecycle::deprecate_warn( + when = "1.16.0", + what = "neff_ratio()", + with = "extract_neff_ratio()", + details = paste( + "bayesplot's neff_ratio() was renamed to extract_neff_ratio() to", + "make clear it only extracts already-computed effective sample", + "size ratios (and to avoid masking posterior's ESS functions)." + ) + ) + extract_neff_ratio(object, ...) } @@ -195,9 +235,9 @@ nuts_params.CmdStanMCMC <- function(object, pars = NULL, ...) { #' @rdname bayesplot-extractors #' @export -#' @method rhat stanfit +#' @method extract_rhat stanfit #' -rhat.stanfit <- function(object, pars = NULL, ...) { +extract_rhat.stanfit <- function(object, pars = NULL, ...) { suggested_package("rstan") s <- if (!is.null(pars)) { rstan::summary(object, pars = pars, ...) @@ -210,10 +250,10 @@ rhat.stanfit <- function(object, pars = NULL, ...) { #' @rdname bayesplot-extractors #' @export -#' @method rhat stanreg +#' @method extract_rhat stanreg #' @template args-regex_pars #' -rhat.stanreg <- function(object, pars = NULL, regex_pars = NULL, ...) { +extract_rhat.stanreg <- function(object, pars = NULL, regex_pars = NULL, ...) { suggested_package("rstanarm") r <- summary(object, pars = pars, regex_pars = regex_pars, ...)[, "Rhat"] r <- validate_rhat(r) @@ -226,8 +266,8 @@ rhat.stanreg <- function(object, pars = NULL, regex_pars = NULL, ...) { #' @rdname bayesplot-extractors #' @export -#' @method rhat CmdStanMCMC -rhat.CmdStanMCMC <- function(object, pars = NULL, ...) { +#' @method extract_rhat CmdStanMCMC +extract_rhat.CmdStanMCMC <- function(object, pars = NULL, ...) { .rhat <- utils::getFromNamespace("rhat", "posterior") s <- object$summary(pars, rhat = .rhat)[, c("variable", "rhat")] r <- setNames(s$rhat, s$variable) @@ -238,9 +278,9 @@ rhat.CmdStanMCMC <- function(object, pars = NULL, ...) { #' @rdname bayesplot-extractors #' @export -#' @method neff_ratio stanfit +#' @method extract_neff_ratio stanfit #' -neff_ratio.stanfit <- function(object, pars = NULL, ...) { +extract_neff_ratio.stanfit <- function(object, pars = NULL, ...) { suggested_package("rstan") s <- if (!is.null(pars)) { rstan::summary(object, pars = pars, ...) @@ -254,9 +294,9 @@ neff_ratio.stanfit <- function(object, pars = NULL, ...) { #' @rdname bayesplot-extractors #' @export -#' @method neff_ratio stanreg +#' @method extract_neff_ratio stanreg #' -neff_ratio.stanreg <- function(object, pars = NULL, regex_pars = NULL, ...) { +extract_neff_ratio.stanreg <- function(object, pars = NULL, regex_pars = NULL, ...) { suggested_package("rstanarm") s <- summary(object, pars = pars, regex_pars = regex_pars, ...) ess <- s[, "n_eff"] @@ -272,8 +312,8 @@ neff_ratio.stanreg <- function(object, pars = NULL, regex_pars = NULL, ...) { #' @rdname bayesplot-extractors #' @export -#' @method neff_ratio CmdStanMCMC -neff_ratio.CmdStanMCMC <- function(object, pars = NULL, ...) { +#' @method extract_neff_ratio CmdStanMCMC +extract_neff_ratio.CmdStanMCMC <- function(object, pars = NULL, ...) { s <- object$summary(pars, "n_eff" = "ess_basic")[, c("variable", "n_eff")] ess <- setNames(s$n_eff, s$variable) tss <- prod(dim(object$draws())[1:2]) diff --git a/R/mcmc-diagnostics.R b/R/mcmc-diagnostics.R index 87e716da4..dd2f4035a 100644 --- a/R/mcmc-diagnostics.R +++ b/R/mcmc-diagnostics.R @@ -105,8 +105,8 @@ #' # intentionally use small 'iter' so there are some #' # problems with rhat and neff for demonstration #' fit <- stan_glm(mpg ~ ., data = mtcars, iter = 50, refresh = 0) -#' rhats <- rhat(fit) -#' ratios <- neff_ratio(fit) +#' rhats <- extract_rhat(fit) +#' ratios <- extract_neff_ratio(fit) #' mcmc_rhat(rhats) #' mcmc_neff(ratios, size = 3) #' @@ -120,8 +120,8 @@ #' #' # increase number of iterations and plots look much better #' fit2 <- update(fit, iter = 500) -#' mcmc_rhat(rhat(fit2)) -#' mcmc_neff(neff_ratio(fit2)) +#' mcmc_rhat(extract_rhat(fit2)) +#' mcmc_neff(extract_neff_ratio(fit2)) #' mcmc_acf(as.array(fit2), pars = c("wt", "cyl"), lags = 10) #' } #' @@ -220,7 +220,7 @@ mcmc_rhat_data <- function(rhat, ...) { #' @rdname MCMC-diagnostics #' @export #' @param ratio A vector of *ratios* of effective sample size estimates to -#' total sample size. See [neff_ratio()]. +#' total sample size. See [extract_neff_ratio()]. #' mcmc_neff <- function(ratio, ..., size = NULL) { check_ignored_arguments(...) diff --git a/R/mcmc-intervals.R b/R/mcmc-intervals.R index 2dd4fd72f..86e3e1720 100644 --- a/R/mcmc-intervals.R +++ b/R/mcmc-intervals.R @@ -31,7 +31,7 @@ #' @param rhat An optional numeric vector of R-hat estimates, with one element #' per parameter included in `x`. If `rhat` is provided, the intervals/areas #' and point estimates in the resulting plot are colored based on R-hat value. -#' See [rhat()] for methods for extracting R-hat estimates. +#' See [extract_rhat()] for methods for extracting R-hat estimates. #' @template args-density-controls #' #' @template return-ggplot-or-data @@ -180,7 +180,7 @@ #' color_scheme_set("teal") #' mcmc_intervals(x, point_est = "mean", prob = 0.8, prob_outer = 0.95) #' mcmc_areas(x, regex_pars = "cyl", bw = "SJ", -#' rhat = rhat(fit, regex_pars = "cyl")) +#' rhat = extract_rhat(fit, regex_pars = "cyl")) #' } #' #' \dontrun{ diff --git a/man/MCMC-diagnostics.Rd b/man/MCMC-diagnostics.Rd index f6dbad816..c862479e4 100644 --- a/man/MCMC-diagnostics.Rd +++ b/man/MCMC-diagnostics.Rd @@ -62,7 +62,7 @@ to override the default binning.} \code{binwidth}.} \item{ratio}{A vector of \emph{ratios} of effective sample size estimates to -total sample size. See \code{\link[=neff_ratio]{neff_ratio()}}.} +total sample size. See \code{\link[=extract_neff_ratio]{extract_neff_ratio()}}.} \item{x}{An object containing MCMC draws: \itemize{ @@ -191,8 +191,8 @@ library(rstanarm) # intentionally use small 'iter' so there are some # problems with rhat and neff for demonstration fit <- stan_glm(mpg ~ ., data = mtcars, iter = 50, refresh = 0) -rhats <- rhat(fit) -ratios <- neff_ratio(fit) +rhats <- extract_rhat(fit) +ratios <- extract_neff_ratio(fit) mcmc_rhat(rhats) mcmc_neff(ratios, size = 3) @@ -206,8 +206,8 @@ mcmc_acf(draws, pars = c("wt", "cyl"), lags = 10) # increase number of iterations and plots look much better fit2 <- update(fit, iter = 500) -mcmc_rhat(rhat(fit2)) -mcmc_neff(neff_ratio(fit2)) +mcmc_rhat(extract_rhat(fit2)) +mcmc_neff(extract_neff_ratio(fit2)) mcmc_acf(as.array(fit2), pars = c("wt", "cyl"), lags = 10) } diff --git a/man/MCMC-intervals.Rd b/man/MCMC-intervals.Rd index b98f835ea..de7f23335 100644 --- a/man/MCMC-intervals.Rd +++ b/man/MCMC-intervals.Rd @@ -172,7 +172,7 @@ the inner and interval segments, respectively.} \item{rhat}{An optional numeric vector of R-hat estimates, with one element per parameter included in \code{x}. If \code{rhat} is provided, the intervals/areas and point estimates in the resulting plot are colored based on R-hat value. -See \code{\link[=rhat]{rhat()}} for methods for extracting R-hat estimates.} +See \code{\link[=extract_rhat]{extract_rhat()}} for methods for extracting R-hat estimates.} \item{area_method}{How to constrain the areas in \code{mcmc_areas()}. The default is \code{"equal area"}, setting the density curves to have the same @@ -344,7 +344,7 @@ x <- as.matrix(fit) color_scheme_set("teal") mcmc_intervals(x, point_est = "mean", prob = 0.8, prob_outer = 0.95) mcmc_areas(x, regex_pars = "cyl", bw = "SJ", - rhat = rhat(fit, regex_pars = "cyl")) + rhat = extract_rhat(fit, regex_pars = "cyl")) } \dontrun{ diff --git a/man/bayesplot-extractors.Rd b/man/bayesplot-extractors.Rd index 593a2b0e1..034e7c2f3 100644 --- a/man/bayesplot-extractors.Rd +++ b/man/bayesplot-extractors.Rd @@ -4,6 +4,8 @@ \alias{bayesplot-extractors} \alias{log_posterior} \alias{nuts_params} +\alias{extract_rhat} +\alias{extract_neff_ratio} \alias{rhat} \alias{neff_ratio} \alias{log_posterior.stanfit} @@ -13,18 +15,22 @@ \alias{nuts_params.stanreg} \alias{nuts_params.list} \alias{nuts_params.CmdStanMCMC} -\alias{rhat.stanfit} -\alias{rhat.stanreg} -\alias{rhat.CmdStanMCMC} -\alias{neff_ratio.stanfit} -\alias{neff_ratio.stanreg} -\alias{neff_ratio.CmdStanMCMC} +\alias{extract_rhat.stanfit} +\alias{extract_rhat.stanreg} +\alias{extract_rhat.CmdStanMCMC} +\alias{extract_neff_ratio.stanfit} +\alias{extract_neff_ratio.stanreg} +\alias{extract_neff_ratio.CmdStanMCMC} \title{Extract quantities needed for plotting from model objects} \usage{ log_posterior(object, ...) nuts_params(object, ...) +extract_rhat(object, ...) + +extract_neff_ratio(object, ...) + rhat(object, ...) neff_ratio(object, ...) @@ -43,17 +49,17 @@ neff_ratio(object, ...) \method{nuts_params}{CmdStanMCMC}(object, pars = NULL, ...) -\method{rhat}{stanfit}(object, pars = NULL, ...) +\method{extract_rhat}{stanfit}(object, pars = NULL, ...) -\method{rhat}{stanreg}(object, pars = NULL, regex_pars = NULL, ...) +\method{extract_rhat}{stanreg}(object, pars = NULL, regex_pars = NULL, ...) -\method{rhat}{CmdStanMCMC}(object, pars = NULL, ...) +\method{extract_rhat}{CmdStanMCMC}(object, pars = NULL, ...) -\method{neff_ratio}{stanfit}(object, pars = NULL, ...) +\method{extract_neff_ratio}{stanfit}(object, pars = NULL, ...) -\method{neff_ratio}{stanreg}(object, pars = NULL, regex_pars = NULL, ...) +\method{extract_neff_ratio}{stanreg}(object, pars = NULL, regex_pars = NULL, ...) -\method{neff_ratio}{CmdStanMCMC}(object, pars = NULL, ...) +\method{extract_neff_ratio}{CmdStanMCMC}(object, pars = NULL, ...) } \arguments{ \item{object}{The object to use.} @@ -85,9 +91,16 @@ The data frame should have columns \code{"Iteration"} (integer), \code{"Chain"} The data frame should have columns \code{"Parameter"} (factor), \code{"Iteration"} (integer), \code{"Chain"} (integer), and \code{"Value"} (numeric). See \strong{Examples}, below. } -\item{\code{rhat()}, \code{neff_ratio()}}{ +\item{\code{extract_rhat()}, \code{extract_neff_ratio()}}{ Methods return (named) vectors. } +\item{\code{rhat()}, \code{neff_ratio()}}{ +\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} Use \code{extract_rhat()} and +\code{extract_neff_ratio()} instead. These names clashed with +\code{\link[posterior:rhat]{posterior::rhat()}} and \code{\link[posterior:ess_basic]{posterior::ess_basic()}} (and other ESS +functions), which caused confusion because the bayesplot versions +\emph{extract} already-computed values rather than compute them. +} } } \description{ diff --git a/tests/testthat/test-extractors.R b/tests/testthat/test-extractors.R index 1116be673..58fa93765 100644 --- a/tests/testthat/test-extractors.R +++ b/tests/testthat/test-extractors.R @@ -78,56 +78,72 @@ test_that("log_posterior.stanreg returns correct structure", { expect_equal(length(unique(lp$Chain)), CHAINS) }) -test_that("rhat.stanreg returns correct structure", { +test_that("extract_rhat.stanreg returns correct structure", { skip_if_not_installed("rstanarm") - r <- rhat(fit) + r <- extract_rhat(fit) expect_named(r) expect_equal(r, summary(fit)[1:length(r), "Rhat"]) - expect_identical(names(rhat(fit, regex_pars = c("wt", "am"))), + expect_identical(names(extract_rhat(fit, regex_pars = c("wt", "am"))), c("wt", "am")) }) -test_that("neff_ratio.stanreg returns correct structure", { +test_that("extract_neff_ratio.stanreg returns correct structure", { skip_if_not_installed("rstanarm") - expect_named(neff_ratio(fit, pars = c("wt", "am")), c("wt", "am")) + expect_named(extract_neff_ratio(fit, pars = c("wt", "am")), c("wt", "am")) - ratio <- neff_ratio(fit) + ratio <- extract_neff_ratio(fit) expect_named(ratio) ans <- summary(fit)[1:length(ratio), "n_eff"] / (floor(ITER / 2) * CHAINS) expect_equal(ratio, ans, tolerance = 0.001) }) -test_that("rhat.stanfit returns correct structure", { +test_that("extract_rhat.stanfit returns correct structure", { skip_if_not_installed("rstanarm") - r <- rhat(fit$stanfit) + r <- extract_rhat(fit$stanfit) expect_named(r) expect_equal(r, summary(fit)[, "Rhat"]) - r2 <- rhat(fit$stanfit, pars = c("wt", "sigma")) + r2 <- extract_rhat(fit$stanfit, pars = c("wt", "sigma")) expect_named(r2) expect_equal(r2, summary(fit, pars = c("wt", "sigma"))[, "Rhat"]) }) -test_that("neff_ratio.stanreg returns correct structure", { +test_that("extract_neff_ratio.stanfit returns correct structure", { skip_if_not_installed("rstanarm") denom <- floor(ITER / 2) * CHAINS - ratio <- neff_ratio(fit$stanfit) + ratio <- extract_neff_ratio(fit$stanfit) expect_named(ratio) ans <- summary(fit)[, "n_eff"] / denom expect_equal(ratio, ans, tolerance = 0.001) - ratio2 <- neff_ratio(fit$stanfit, pars = c("wt", "sigma")) + ratio2 <- extract_neff_ratio(fit$stanfit, pars = c("wt", "sigma")) expect_named(ratio2) ans2 <- summary(fit, pars = c("wt", "sigma"))[, "n_eff"] / denom expect_equal(ratio2, ans2, tolerance = 0.001) }) +test_that("rhat() and neff_ratio() are deprecated but still work", { + skip_if_not_installed("rstanarm") + + expect_warning( + r <- rhat(fit), + class = "lifecycle_warning_deprecated" + ) + expect_equal(r, suppressWarnings(extract_rhat(fit))) + + expect_warning( + ratio <- neff_ratio(fit), + class = "lifecycle_warning_deprecated" + ) + expect_equal(ratio, suppressWarnings(extract_neff_ratio(fit))) +}) + test_that("cmdstanr methods work", { skip_on_cran() skip_if_not_installed("cmdstanr") @@ -145,11 +161,11 @@ test_that("cmdstanr methods work", { expect_equal(range(np$Chain), c(1, 2)) expect_equal(range(np$Iteration), c(1, 500)) - r <- rhat(fit) + r <- extract_rhat(fit) expect_named(head(r, 4), c("alpha", "beta[1]", "beta[2]", "beta[3]")) expect_true(all(round(r) == 1)) - ratio <- neff_ratio(fit) + ratio <- extract_neff_ratio(fit) expect_named(head(ratio, 4), c("alpha", "beta[1]", "beta[2]", "beta[3]")) expect_true(all(ratio > 0)) diff --git a/vignettes/visual-mcmc-diagnostics.Rmd b/vignettes/visual-mcmc-diagnostics.Rmd index 1b6ee6a6d..c54fd4b65 100644 --- a/vignettes/visual-mcmc-diagnostics.Rmd +++ b/vignettes/visual-mcmc-diagnostics.Rmd @@ -625,13 +625,15 @@ fit_cp_bad_rhat <- sampling(schools_mod_cp, data = schools_dat, iter = 50, init_r = 10, seed = 671254821) ``` -**bayesplot** provides a generic `rhat` extractor function, currently with -methods defined for models fit using the **rstan**, **rstanarm** and **brms** -packages. But regardless of how you fit your model, all **bayesplot** needs is a -vector of $\hat{R}$ values. +**bayesplot** provides a generic `extract_rhat` extractor function, currently +with methods defined for models fit using the **rstan**, **rstanarm** and +**brms** packages. But regardless of how you fit your model, all **bayesplot** +needs is a vector of $\hat{R}$ values. (The older name `rhat()` is deprecated +because it conflicted with `posterior::rhat()`, which actually *computes* +$\hat{R}$; `extract_rhat()` only *extracts* already-computed values.) ```{r print-rhats} -rhats <- rhat(fit_cp_bad_rhat) +rhats <- extract_rhat(fit_cp_bad_rhat) print(rhats) ``` @@ -670,7 +672,7 @@ If we look at the same model fit using longer Markov chains we should see all $\hat{R} < 1.1$, and all points in the plot the same (light) color: ```{r mcmc_rhat-3} -mcmc_rhat(rhat = rhat(fit_cp)) + yaxis_text(hjust = 0) +mcmc_rhat(rhat = extract_rhat(fit_cp)) + yaxis_text(hjust = 0) ``` We can see the same information shown by `mcmc_rhat` but in histogram form using @@ -700,16 +702,18 @@ may not necessarily approach the true posterior faster. Google "antithetic sampl visit [the relevant forum thread](https://discourse.mc-stan.org/t/n-eff-bda3-vs-stan/2608/19) for some further explanation. -The **bayesplot** package provides a generic `neff_ratio` extractor function, -currently with methods defined for models fit using the **rstan**, -**rstanarm** and **brms** packages. But regardless of how you fit your model, all -**bayesplot** needs is a vector of $n_{eff}/N$ values. The `mcmc_neff` and -`mcmc_neff_hist` can then be used to plot the ratios. +The **bayesplot** package provides a generic `extract_neff_ratio` extractor +function, currently with methods defined for models fit using the **rstan**, +**rstanarm** and **brms** packages. But regardless of how you fit your model, +all **bayesplot** needs is a vector of $n_{eff}/N$ values. The `mcmc_neff` and +`mcmc_neff_hist` can then be used to plot the ratios. (The older name +`neff_ratio()` is deprecated to avoid masking the ESS functions in the +**posterior** package.) #### mcmc_neff, mcmc_neff_hist ```{r print-neff-ratios} -ratios_cp <- neff_ratio(fit_cp) +ratios_cp <- extract_neff_ratio(fit_cp) print(ratios_cp) mcmc_neff(ratios_cp, size = 2) ``` @@ -732,8 +736,8 @@ difference. Here are the $n_{eff}/N$ plots for `fit_cp` and `fit_ncp` side by side. ```{r mcmc_neff-compare} -neff_cp <- neff_ratio(fit_cp, pars = c("theta", "mu", "tau")) -neff_ncp <- neff_ratio(fit_ncp, pars = c("theta", "mu", "tau")) +neff_cp <- extract_neff_ratio(fit_cp, pars = c("theta", "mu", "tau")) +neff_ncp <- extract_neff_ratio(fit_ncp, pars = c("theta", "mu", "tau")) compare_cp_ncp(mcmc_neff(neff_cp), mcmc_neff(neff_ncp), ncol = 1) ``` From ce4593821878f4263881d4db32af02dc710b7171 Mon Sep 17 00:00:00 2001 From: Utkarsh Date: Thu, 16 Apr 2026 22:52:46 +0530 Subject: [PATCH 2/3] update news.md --- NEWS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NEWS.md b/NEWS.md index 1f674aac4..3662fed94 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,6 +1,6 @@ # bayesplot (development version) -* Deprecated `rhat()` and `neff_ratio()` in favor of `extract_rhat()` and `extract_neff_ratio()` to avoid masking the same-named (but different) functions in the **posterior** package. The old names still work but emit a deprecation warning. (#295) +* Deprecated `rhat()` and `neff_ratio()` in favor of `extract_rhat()` and `extract_neff_ratio()`. * Fixed `validate_chain_list()` colnames check to compare all chains, not just the first two. * Added test verifying `legend_move("none")` behaves equivalently to `legend_none()`. * Added singleton-dimension edge-case tests for exported `_data()` functions. From ff85ef17b74a1935f0e91c39492776ac0dd3e606 Mon Sep 17 00:00:00 2001 From: Utkarsh Date: Thu, 16 Apr 2026 23:00:44 +0530 Subject: [PATCH 3/3] Preserve S3 dispatch on deprecated rhat()/neff_ratio() --- NAMESPACE | 2 ++ R/bayesplot-extractors.R | 18 ++++++++++++++++++ man/bayesplot-extractors.Rd | 6 ++++++ 3 files changed, 26 insertions(+) diff --git a/NAMESPACE b/NAMESPACE index eace1c691..a4d5ff98a 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -17,6 +17,7 @@ S3method(log_posterior,stanfit) S3method(log_posterior,stanreg) S3method(melt_mcmc,matrix) S3method(melt_mcmc,mcmc_array) +S3method(neff_ratio,default) S3method(num_chains,data.frame) S3method(num_chains,mcmc_array) S3method(num_iters,data.frame) @@ -36,6 +37,7 @@ S3method(pp_check,default) S3method(print,bayesplot_function_list) S3method(print,bayesplot_grid) S3method(print,bayesplot_scheme) +S3method(rhat,default) export(abline_01) export(available_mcmc) export(available_ppc) diff --git a/R/bayesplot-extractors.R b/R/bayesplot-extractors.R index 40dc6e2f1..424dd36a0 100644 --- a/R/bayesplot-extractors.R +++ b/R/bayesplot-extractors.R @@ -81,6 +81,9 @@ extract_neff_ratio <- function(object, ...) { } # rhat ------------------------------------------------------------- +# Kept as an S3 generic (not just a wrapper) so third-party methods +# registered against rhat (e.g. brms::rhat.brmsfit) still dispatch +# during the deprecation window. #' @rdname bayesplot-extractors #' @export rhat <- function(object, ...) { @@ -94,8 +97,16 @@ rhat <- function(object, ...) { "masking posterior::rhat(), which computes R-hat)." ) ) + UseMethod("rhat") +} + +#' @rdname bayesplot-extractors +#' @export +#' @method rhat default +rhat.default <- function(object, ...) { extract_rhat(object, ...) } + # neff_ratio ------------------------------------------------------------- #' @rdname bayesplot-extractors #' @export @@ -110,6 +121,13 @@ neff_ratio <- function(object, ...) { "size ratios (and to avoid masking posterior's ESS functions)." ) ) + UseMethod("neff_ratio") +} + +#' @rdname bayesplot-extractors +#' @export +#' @method neff_ratio default +neff_ratio.default <- function(object, ...) { extract_neff_ratio(object, ...) } diff --git a/man/bayesplot-extractors.Rd b/man/bayesplot-extractors.Rd index 034e7c2f3..111c03539 100644 --- a/man/bayesplot-extractors.Rd +++ b/man/bayesplot-extractors.Rd @@ -7,7 +7,9 @@ \alias{extract_rhat} \alias{extract_neff_ratio} \alias{rhat} +\alias{rhat.default} \alias{neff_ratio} +\alias{neff_ratio.default} \alias{log_posterior.stanfit} \alias{log_posterior.stanreg} \alias{log_posterior.CmdStanMCMC} @@ -33,8 +35,12 @@ extract_neff_ratio(object, ...) rhat(object, ...) +\method{rhat}{default}(object, ...) + neff_ratio(object, ...) +\method{neff_ratio}{default}(object, ...) + \method{log_posterior}{stanfit}(object, inc_warmup = FALSE, ...) \method{log_posterior}{stanreg}(object, inc_warmup = FALSE, ...)