Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# bayesplot (development version)

* Added dedicated edge-case tests for all exported `_data()` functions.
* Added unit tests for `mcmc_areas_ridges_data()`, `mcmc_parcoord_data()`, and `mcmc_trace_data()`.
* Added unit tests for `ppc_error_data()` and `ppc_loo_pit_data()` covering output structure, argument handling, and edge cases.
* Added vignette sections demonstrating `*_data()` companion functions for building custom ggplot2 visualizations (#435)
Expand Down
197 changes: 197 additions & 0 deletions tests/testthat/test-data-functions-edge-cases.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
source(test_path("data-for-ppc-tests.R"))
load(test_path("data-for-ordinal.rda"))

# ppc_bars_data ------------------------------------------------------------

test_that("ppc_bars_data handles single observation and single draw", {
y1 <- 2L
yrep1 <- matrix(c(1L, 2L, 3L, 2L, 2L), ncol = 1)
d <- ppc_bars_data(y1, yrep1)
expect_s3_class(d, "data.frame")
expect_equal(d$y_obs[d$x == 2], 1)

# single draw: interval collapses to a point
y_s <- c(1L, 2L, 3L, 2L)
yrep_s <- matrix(c(1L, 2L, 2L, 3L), nrow = 1)
d2 <- ppc_bars_data(y_s, yrep_s)
expect_equal(d2$l, d2$m, ignore_attr = TRUE)
expect_equal(d2$m, d2$h, ignore_attr = TRUE)
})

test_that("ppc_bars_data prob = 0 collapses interval to median", {
d <- ppc_bars_data(y_ord, yrep_ord, prob = 0)
expect_equal(d$l, d$m, ignore_attr = TRUE)
expect_equal(d$m, d$h, ignore_attr = TRUE)
})

test_that("ppc_bars_data errors on zero-length input", {
expect_error(ppc_bars_data(integer(0), matrix(integer(0), nrow = 5, ncol = 0)))
})


# ppc_error_data -----------------------------------------------------------

test_that("ppc_error_data handles single observation", {
skip_if_not_installed("rstantools")
y1 <- 5
yrep1 <- matrix(c(4, 6, 5), ncol = 1)
d <- ppc_error_data(y1, yrep1)
expect_equal(nrow(d), 3)
expect_equal(d$value, y1 - yrep1[, 1])
expect_true(all(d$y_obs == 5))
})

test_that("ppc_error_data returns zero-row data frame for zero-length input", {
skip_if_not_installed("rstantools")
d <- ppc_error_data(numeric(0), matrix(numeric(0), nrow = 1, ncol = 0))
expect_equal(nrow(d), 0)
expect_named(d, c("y_id", "y_name", "y_obs", "rep_id", "rep_label", "value"))
})


# ppc_scatter_data ---------------------------------------------------------

test_that("ppc_scatter_data handles single observation and single draw", {
y1 <- 5
yrep1 <- matrix(c(4, 6, 5), ncol = 1)
d <- ppc_scatter_data(y1, yrep1)
expect_equal(nrow(d), 3)
expect_true(all(d$y_obs == 5))
expect_equal(d$value, c(4, 6, 5))

# single draw
d2 <- ppc_scatter_data(y, yrep[1, , drop = FALSE])
expect_equal(nrow(d2), length(y))
expect_equal(d2$value, yrep[1, ])
expect_equal(d2$y_obs, y)
})

test_that("ppc_scatter_data returns zero-row data frame for zero-length input", {
d <- ppc_scatter_data(numeric(0), matrix(numeric(0), nrow = 1, ncol = 0))
expect_equal(nrow(d), 0)
})


# ppc_scatter_avg_data -----------------------------------------------------

test_that("ppc_scatter_avg_data handles single observation", {
y1 <- 5
yrep1 <- matrix(c(4, 6, 5), ncol = 1)
d <- ppc_scatter_avg_data(y1, yrep1)
expect_equal(nrow(d), 1)
expect_equal(d$value, mean(c(4, 6, 5)))
expect_equal(d$y_obs, 5)
})

test_that("ppc_scatter_avg_data returns zero-row data frame for zero-length input", {
d <- ppc_scatter_avg_data(numeric(0), matrix(numeric(0), nrow = 1, ncol = 0))
expect_equal(nrow(d), 0)
})


# ppc_loo_pit_data ---------------------------------------------------------

test_that("ppc_loo_pit_data handles single pit value", {
expect_message(
d <- ppc_loo_pit_data(pit = 0.5, boundary_correction = FALSE, samples = 3),
"pit"
)
y_rows <- d[d$is_y, ]
expect_equal(nrow(y_rows), 1)
expect_equal(y_rows$value, 0.5)
})

test_that("ppc_loo_pit_data works with custom bw parameter", {
set.seed(42)
pit_vals <- runif(50)
expect_message(
d <- ppc_loo_pit_data(
pit = pit_vals,
boundary_correction = TRUE,
bw = "SJ",
samples = 3,
grid_len = 128
),
"pit"
)
expect_true("x" %in% names(d))
})

test_that("ppc_loo_pit_data handles zero-length pit", {
expect_message(
d <- ppc_loo_pit_data(pit = numeric(0), boundary_correction = FALSE, samples = 2),
"pit"
)
expect_equal(nrow(d), 0)
})

test_that("ppc_loo_pit_data is_y and is_y_label columns are consistent", {
set.seed(42)
pit_vals <- runif(10)
expect_message(
d <- ppc_loo_pit_data(pit = pit_vals, boundary_correction = FALSE, samples = 2),
"pit"
)
expect_true(all(d$is_y_label[d$is_y] == levels(d$is_y_label)[1]))
expect_true(all(d$is_y_label[!d$is_y] == levels(d$is_y_label)[2]))
})


# ppd_data -----------------------------------------------------------------

test_that("ppd_data handles single observation (single column)", {
ypred <- matrix(c(1, 2, 3), ncol = 1)
d <- ppd_data(ypred)
expect_equal(nrow(d), 3)
expect_true(all(d$y_id == 1))
expect_equal(d$value, c(1, 2, 3))
})

test_that("ppd_data returns zero-row data frame for zero-length input", {
d <- ppd_data(matrix(numeric(0), nrow = 1, ncol = 0))
expect_equal(nrow(d), 0)
})


# ppd_stat_data ------------------------------------------------------------

test_that("ppd_stat_data handles single draw and single observation", {
yrep_single <- matrix(rnorm(10), nrow = 1)
d <- ppd_stat_data(yrep_single, stat = "mean")
expect_equal(nrow(d), 1)

yrep_1obs <- matrix(rnorm(5), ncol = 1)
d2 <- ppd_stat_data(yrep_1obs, stat = "mean")
expect_s3_class(d2, "data.frame")
})

test_that("ppd_stat_data errors on zero-length input", {
expect_error(ppd_stat_data(matrix(numeric(0), nrow = 1, ncol = 0), stat = "mean"))
})


# ppd_intervals_data -------------------------------------------------------

test_that("ppd_intervals_data handles single observation and single draw", {
yrep_1obs <- matrix(rnorm(25), ncol = 1)
d <- ppd_intervals_data(yrep_1obs)
expect_equal(nrow(d), 1)
expect_true(d$ll <= d$l && d$l <= d$m && d$m <= d$h && d$h <= d$hh)

# single draw: all quantiles collapse to the value
yrep_1draw <- matrix(rnorm(10), nrow = 1)
d2 <- ppd_intervals_data(yrep_1draw)
expect_equal(d2$ll, d2$m)
expect_equal(d2$hh, d2$m)
})

test_that("ppd_intervals_data uses custom x values", {
x_vals <- seq(10, 100, length.out = ncol(yrep))
d <- ppd_intervals_data(yrep, x = x_vals)
expect_equal(d$x, x_vals)
})

test_that("ppd_intervals_data returns zero-row data frame for zero-length input", {
d <- ppd_intervals_data(matrix(numeric(0), nrow = 1, ncol = 0))
expect_equal(nrow(d), 0)
})
Loading