Skip to content

Commit eb34be4

Browse files
authored
Merge branch 'master' into test/data-functions-edge-cases
2 parents 20f9685 + 8f45291 commit eb34be4

20 files changed

Lines changed: 244 additions & 89 deletions

NEWS.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
# bayesplot (development version)
22

33
* Added singleton-dimension edge-case tests for exported `_data()` functions.
4+
* Validate empty list and zero-row matrix inputs in `nuts_params.list()`.
5+
* Validate user-provided `pit` values in `ppc_loo_pit_data()` and `ppc_loo_pit_qq()`, rejecting non-numeric inputs, missing values, and values outside `[0, 1]`.
46
* New `show_marginal` argument to `ppd_*()` functions to show the PPD - the marginal predictive distribution by @mattansb (#425)
57
* `ppc_ecdf_overlay()`, `ppc_ecdf_overlay_grouped()`, and `ppd_ecdf_overlay()` now always use `geom_step()`. The `discrete` argument is deprecated.
68
* Fixed missing `drop = FALSE` in `nuts_params.CmdStanMCMC()`.

R/bayesplot-extractors.R

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,10 +145,18 @@ nuts_params.stanreg <-
145145
#' @export
146146
#' @method nuts_params list
147147
nuts_params.list <- function(object, pars = NULL, ...) {
148+
if (length(object) == 0) {
149+
abort("'object' must be a non-empty list.")
150+
}
151+
148152
if (!all(sapply(object, is.matrix))) {
149153
abort("All list elements should be matrices.")
150154
}
151155

156+
if (any(vapply(object, nrow, integer(1)) == 0)) {
157+
abort("All matrices in the list must have at least one row.")
158+
}
159+
152160
dd <- lapply(object, dim)
153161
if (length(unique(dd)) != 1) {
154162
abort("All matrices in the list must have the same dimensions.")

R/helpers-ppc.R

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,15 +58,20 @@ validate_y <- function(y) {
5858
#' Validate predictions (`yrep` or `ypred`)
5959
#'
6060
#' Checks that `predictions` is a numeric matrix, doesn't have any NAs, and has
61-
#' the correct number of columns.
61+
#' the correct number of columns. If `predictions` is a `posterior::draws`
62+
#' object it is first coerced to a matrix.
6263
#'
63-
#' @param predictions The user's `yrep` or `ypred` object (SxN matrix).
64+
#' @param predictions The user's `yrep` or `ypred` object (SxN matrix or a
65+
#' `posterior::draws` object).
6466
#' @param `n_obs` The number of observations (columns) that `predictions` should
6567
#' have, if applicable.
6668
#' @return Either throws an error or returns a numeric matrix.
6769
#' @noRd
6870
validate_predictions <- function(predictions, n_obs = NULL) {
69-
# sanity checks
71+
if (posterior::is_draws(predictions)) {
72+
predictions <- posterior::as_draws_matrix(predictions)
73+
predictions <- unclass(predictions)
74+
}
7075
stopifnot(is.matrix(predictions), is.numeric(predictions))
7176
if (!is.null(n_obs)) {
7277
stopifnot(length(n_obs) == 1, n_obs == as.integer(n_obs))

R/ppc-loo.R

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -302,7 +302,10 @@ ppc_loo_pit_data <-
302302
boundary_correction = TRUE,
303303
grid_len = 512) {
304304
if (!is.null(pit)) {
305-
stopifnot(is.numeric(pit), is_vector_or_1Darray(pit))
305+
pit <- validate_pit(pit)
306+
if (boundary_correction && length(pit) < 2L) {
307+
abort("At least 2 PIT values are required when 'boundary_correction' is TRUE.")
308+
}
306309
inform("'pit' specified so ignoring 'y','yrep','lw' if specified.")
307310
} else {
308311
suggested_package("rstantools")
@@ -348,7 +351,7 @@ ppc_loo_pit_qq <- function(y,
348351

349352
compare <- match.arg(compare)
350353
if (!is.null(pit)) {
351-
stopifnot(is.numeric(pit), is_vector_or_1Darray(pit))
354+
pit <- validate_pit(pit)
352355
inform("'pit' specified so ignoring 'y','yrep','lw' if specified.")
353356
} else {
354357
suggested_package("rstantools")
@@ -795,14 +798,6 @@ ppc_loo_ribbon <-
795798
# Generate boundary corrected values via a linear convolution using a
796799
# 1-D Gaussian window filter. This method uses the "reflection method"
797800
# to estimate these pvalues and helps speed up the code
798-
if (any(is.infinite(x))) {
799-
warn(paste(
800-
"Ignored", sum(is.infinite(x)),
801-
"Non-finite PIT values are invalid for KDE boundary correction method"
802-
))
803-
x <- x[is.finite(x)]
804-
}
805-
806801
if (grid_len < 100) {
807802
grid_len <- 100
808803
}
@@ -819,6 +814,10 @@ ppc_loo_ribbon <-
819814
# 1-D Convolution
820815
bc_pvals <- .linear_convolution(x, bw, grid_counts, grid_breaks, grid_len)
821816

817+
if (all(is.na(bc_pvals))) {
818+
abort("KDE boundary correction produced all NA values.")
819+
}
820+
822821
# Generate vector of x-axis values for plotting based on binned relative freqs
823822
n_breaks <- length(grid_breaks)
824823

man-roxygen/args-y-yrep.R

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
#' @param y A vector of observations. See **Details**.
22
#' @param yrep An `S` by `N` matrix of draws from the posterior (or prior)
3-
#' predictive distribution. The number of rows, `S`, is the size of the
4-
#' posterior (or prior) sample used to generate `yrep`. The number of columns,
5-
#' `N` is the number of predicted observations (`length(y)`). The columns of
6-
#' `yrep` should be in the same order as the data points in `y` for the plots
7-
#' to make sense. See the **Details** and **Plot Descriptions** sections for
8-
#' additional advice specific to particular plots.
3+
#' predictive distribution, or a [`posterior::draws`] object. The number of
4+
#' rows, `S`, is the size of the posterior (or prior) sample used to generate
5+
#' `yrep`. The number of columns, `N` is the number of predicted observations
6+
#' (`length(y)`). The columns of `yrep` should be in the same order as the
7+
#' data points in `y` for the plots to make sense. See the **Details** and
8+
#' **Plot Descriptions** sections for additional advice specific to particular
9+
#' plots.

man-roxygen/args-ypred.R

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#' @param ypred An `S` by `N` matrix of draws from the posterior (or prior)
2-
#' predictive distribution. The number of rows, `S`, is the size of the
3-
#' posterior (or prior) sample used to generate `ypred`. The number of
4-
#' columns, `N`, is the number of predicted observations.
2+
#' predictive distribution, or a [`posterior::draws`] object. The number of
3+
#' rows, `S`, is the size of the posterior (or prior) sample used to generate
4+
#' `ypred`. The number of columns, `N`, is the number of predicted
5+
#' observations.

man/PPC-censoring.Rd

Lines changed: 7 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

man/PPC-discrete.Rd

Lines changed: 7 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

man/PPC-distributions.Rd

Lines changed: 7 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

man/PPC-errors.Rd

Lines changed: 7 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)