diff --git a/R/mcmc-traces.R b/R/mcmc-traces.R index c01bc416..571a6ce2 100644 --- a/R/mcmc-traces.R +++ b/R/mcmc-traces.R @@ -304,17 +304,28 @@ mcmc_rank_overlay <- function(x, mutate(cut = cut(.data$value_rank, n_bins)) %>% group_by(.data$cut) %>% mutate(bin_start = min(.data$value_rank)) %>% - ungroup() %>% - select(-c("cut")) + ungroup() + # Count how many values fall into each bin per chain & parameter d_bin_counts <- data %>% left_join(histobins, by = "value_rank") %>% count(.data$parameter, .data$chain, .data$bin_start) + # Now ensure that all combinations of parameter, chain, and bin_start exist + # even if no counts are present (https://github.com/stan-dev/bayesplot/issues/331) + all_combos <- dplyr::as_tibble(expand.grid( + parameter = unique(data$parameter), + chain = unique(data$chain), + bin_start = unique(histobins$bin_start), + stringsAsFactors = FALSE + )) + d_bin_counts <- all_combos %>% + left_join(d_bin_counts, by = c("parameter", "chain", "bin_start")) %>% + mutate(n = dplyr::if_else(is.na(n), 0L, n)) + # Duplicate the final bin, setting the left edge to the greatest x value, so # that the entire x-axis is used, right_edge <- max(data$value_rank) - d_bin_counts <- d_bin_counts %>% dplyr::filter(.data$bin_start == max(.data$bin_start)) %>% mutate(bin_start = right_edge) %>% diff --git a/tests/testthat/_snaps/mcmc-traces/mcmc-rank-overlay-not-all-bins.svg b/tests/testthat/_snaps/mcmc-traces/mcmc-rank-overlay-not-all-bins.svg new file mode 100644 index 00000000..53f0d82a --- /dev/null +++ b/tests/testthat/_snaps/mcmc-traces/mcmc-rank-overlay-not-all-bins.svg @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + + + + + + + + + + + + +0 +25 +50 +75 +100 + + + + + + + + + + + +0 +500 +1000 +1500 +2000 +Rank +Chain + + +1 +2 +mcmc_rank_overlay (not all bins) + + diff --git a/tests/testthat/data-for-mcmc-tests.R b/tests/testthat/data-for-mcmc-tests.R index 0c7298c3..1136cefe 100644 --- a/tests/testthat/data-for-mcmc-tests.R +++ b/tests/testthat/data-for-mcmc-tests.R @@ -73,4 +73,11 @@ vdiff_dframe_chains_lp <- vdiff_dframe_chains_divergences vdiff_dframe_chains_lp$Parameter <- NULL vdiff_dframe_chains_lp$Value <- runif(2000, -100, -50) +vdiff_dframe_rank_overlay_bins_test <- posterior::as_draws_df( + list( + list(theta = -2 + 0.003 * 1:1000 + stats::arima.sim(list(ar = 0.7), n = 1000, sd = 0.5)), + list(theta = 1 + -0.01 * 1:1000 + stats::arima.sim(list(ar = 0.7), n = 1000, sd = 0.5)) + ) +) + set.seed(seed = NULL) diff --git a/tests/testthat/test-mcmc-traces.R b/tests/testthat/test-mcmc-traces.R index d7ba2b39..62d46c88 100644 --- a/tests/testthat/test-mcmc-traces.R +++ b/tests/testthat/test-mcmc-traces.R @@ -154,6 +154,9 @@ test_that("mcmc_rank_overlay renders correctly", { n_bins = 4 ) + # https://github.com/stan-dev/bayesplot/issues/331 + p_not_all_bins_exist <- mcmc_rank_overlay(vdiff_dframe_rank_overlay_bins_test) + vdiffr::expect_doppelganger("mcmc_rank_overlay (default)", p_base) vdiffr::expect_doppelganger( "mcmc_rank_overlay (reference line)", @@ -164,6 +167,9 @@ test_that("mcmc_rank_overlay renders correctly", { "mcmc_rank_overlay (wide bins)", p_one_param_wide_bins ) + + # https://github.com/stan-dev/bayesplot/issues/331 + vdiffr::expect_doppelganger("mcmc_rank_overlay (not all bins)", p_not_all_bins_exist) }) test_that("mcmc_rank_hist renders correctly", {