Skip to content

Commit c3c841f

Browse files
authored
Merge pull request #173 from stan-dev/bugfix-issue-172
allow negative integer input to ppc_bars, ppc_bars_grouped
2 parents a05ee8a + 3476f65 commit c3c841f

File tree

5 files changed

+81
-56
lines changed

5 files changed

+81
-56
lines changed

NEWS.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141
[`?ppc_loo_pit_overlay()`](http://mc-stan.org/bayesplot/reference/PPC-loo.html)
4242
now work as expected. (#166, #167)
4343

44-
44+
* `ppc_bars()` and `ppc_bars_grouped()` now allow negative integers as input. (#172)
4545

4646

4747
# bayesplot 1.6.0

R/helpers-ppc.R

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,8 @@ ppc_group_data <- function(y, yrep, group, stat = NULL) {
234234
# grouping vars. It summarising path, it has one grouping var.
235235
}
236236

237-
# check if x consists of whole numbers (very close to integers)
237+
# Check if x consists of whole numbers (very close to integers)
238+
# Implementation here follows example ?integer
238239
is_whole_number <- function(x, tol = .Machine$double.eps) {
239240
if (!is.numeric(x)) {
240241
FALSE
@@ -243,9 +244,13 @@ is_whole_number <- function(x, tol = .Machine$double.eps) {
243244
}
244245
}
245246

246-
# check if all values in x are counts (non-negative whole numbers)
247+
# Check if all values in x are whole numbers or counts (non-negative whole
248+
# numbers)
249+
all_whole_number <- function(x, ...) {
250+
all(is_whole_number(x, ...))
251+
}
247252
all_counts <- function(x, ...) {
248-
all(is_whole_number(x, ...)) && min(x) >= 0
253+
all_whole_number(x, ...) && min(x) >= 0
249254
}
250255

251256
# labels ----------------------------------------------------------------

R/ppc-discrete.R

Lines changed: 58 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,10 @@
3030
#'
3131
#' @template return-ggplot
3232
#'
33-
#' @details For all of these plots \code{y} and \code{yrep} must be non-negative
34-
#' integers, although they need not be integers in the strict sense of \R's
35-
#' \code{\link{integer}} type.
33+
#' @details For all of these plots \code{y} and \code{yrep} must be
34+
#' integers, although they need not be integers in the strict sense
35+
#' of \R's \code{\link{integer}} type. For rootogram plots \code{y}
36+
#' and \code{yrep} must also be non-negative.
3637
#'
3738
#' @section Plot Descriptions:
3839
#' \describe{
@@ -100,28 +101,37 @@ ppc_bars <-
100101
fatten = 3,
101102
freq = TRUE) {
102103

103-
check_ignored_arguments(...)
104-
y <- validate_y(y)
105-
yrep <- validate_yrep(yrep, y)
106-
if (!all_counts(y))
107-
stop("ppc_bars expects only non-negative integers in 'y'.")
108-
if (!all_counts(yrep))
109-
stop("ppc_bars expects only non-negative integers in 'yrep'.")
110-
111-
alpha <- (1 - prob) / 2
112-
probs <- sort(c(alpha, 0.5, 1 - alpha))
113-
yrep_data <- ppc_bars_yrep_data(y, yrep, probs = probs, freq = freq, group = NULL)
114-
.ppc_bars(
115-
y_data = data.frame(y = y),
116-
yrep_data,
117-
grouped = FALSE,
118-
facet_args = list(),
119-
width = width,
120-
size = size,
121-
fatten = fatten,
122-
freq = freq
123-
)
104+
check_ignored_arguments(...)
105+
y <- validate_y(y)
106+
yrep <- validate_yrep(yrep, y)
107+
if (!all_whole_number(y)) {
108+
stop("ppc_bars expects 'y' to be discrete.")
124109
}
110+
if (!all_whole_number(yrep)) {
111+
stop("ppc_bars expects 'yrep' to be discrete.")
112+
}
113+
114+
alpha <- (1 - prob) / 2
115+
probs <- sort(c(alpha, 0.5, 1 - alpha))
116+
yrep_data <- ppc_bars_yrep_data(
117+
y,
118+
yrep,
119+
probs = probs,
120+
freq = freq,
121+
group = NULL
122+
)
123+
124+
.ppc_bars(
125+
y_data = data.frame(y = y),
126+
yrep_data,
127+
grouped = FALSE,
128+
facet_args = list(),
129+
width = width,
130+
size = size,
131+
fatten = fatten,
132+
freq = freq
133+
)
134+
}
125135

126136

127137
#' @rdname PPC-discrete
@@ -141,29 +151,31 @@ ppc_bars_grouped <-
141151
fatten = 3,
142152
freq = TRUE) {
143153

144-
check_ignored_arguments(...)
145-
y <- validate_y(y)
146-
yrep <- validate_yrep(yrep, y)
147-
group <- validate_group(group, y)
148-
if (!all_counts(y))
149-
stop("ppc_bars expects only non-negative integers in 'y'.")
150-
if (!all_counts(yrep))
151-
stop("ppc_bars expects only non-negative integers in 'yrep'.")
152-
153-
alpha <- (1 - prob) / 2
154-
probs <- sort(c(alpha, 0.5, 1 - alpha))
155-
yrep_data <- ppc_bars_yrep_data(y, yrep, probs, freq = freq, group = group)
156-
.ppc_bars(
157-
y_data = data.frame(y, group),
158-
yrep_data,
159-
grouped = TRUE,
160-
facet_args = facet_args,
161-
width = width,
162-
size = size,
163-
fatten = fatten,
164-
freq = freq
165-
)
154+
check_ignored_arguments(...)
155+
y <- validate_y(y)
156+
yrep <- validate_yrep(yrep, y)
157+
group <- validate_group(group, y)
158+
if (!all_whole_number(y)) {
159+
stop("ppc_bars_grouped expects 'y' to be discrete.")
166160
}
161+
if (!all_whole_number(yrep)) {
162+
stop("ppc_bars_grouped expects 'yrep' to be discrete.")
163+
}
164+
165+
alpha <- (1 - prob) / 2
166+
probs <- sort(c(alpha, 0.5, 1 - alpha))
167+
yrep_data <- ppc_bars_yrep_data(y, yrep, probs, freq = freq, group = group)
168+
.ppc_bars(
169+
y_data = data.frame(y, group),
170+
yrep_data,
171+
grouped = TRUE,
172+
facet_args = facet_args,
173+
width = width,
174+
size = size,
175+
fatten = fatten,
176+
freq = freq
177+
)
178+
}
167179

168180

169181
#' @rdname PPC-discrete

tests/testthat/test-extractors.R

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,8 @@ context("Extractors")
44

55
ITER <- 1000
66
CHAINS <- 3
7-
capture.output(
8-
fit <- stan_glm(mpg ~ wt + am, data = mtcars,
7+
fit <- stan_glm(mpg ~ wt + am, data = mtcars,
98
iter = ITER, chains = CHAINS, refresh = 0)
10-
)
119

1210
x <- list(cbind(a = 1:3, b = rnorm(3)), cbind(a = 1:3, b = rnorm(3)))
1311

tests/testthat/test-ppc-discrete.R

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,21 @@ test_that("freq argument to ppc_bars works", {
3030
expect_true(all(y_prop < 1) && all(y_prop > 0))
3131
})
3232

33-
test_that("ppc_bars errors if y/yrep not natural numbers", {
33+
test_that("ppc_bars works with negative integers", {
34+
y <- round(rnorm(100, -10, 1))
35+
yrep <- round(matrix(rnorm(100 * 500, -10, 1), 500, 100))
36+
expect_gg(ppc_bars(y, yrep))
37+
})
38+
39+
test_that("ppc_bars(_grouped) errors if y/yrep not discrete", {
3440
expect_error(ppc_bars(y + 0.5, yrep),
35-
"ppc_bars expects only non-negative integers in 'y'")
41+
"ppc_bars expects 'y' to be discrete")
3642
expect_error(ppc_bars(y, yrep + 0.5),
37-
"ppc_bars expects only non-negative integers in 'yrep'")
43+
"ppc_bars expects 'yrep' to be discrete")
44+
expect_error(ppc_bars_grouped(y + 0.5, yrep, group = esoph$agegp),
45+
"ppc_bars_grouped expects 'y' to be discrete")
46+
expect_error(ppc_bars_grouped(y, yrep + 0.5, group = esoph$agegp),
47+
"ppc_bars_grouped expects 'yrep' to be discrete")
3848
})
3949

4050

0 commit comments

Comments
 (0)