Skip to content

Commit 0993aa3

Browse files
committed
merge changes from main tree
Merge remote-tracking branch 'origin/master' into fun-avg # Conflicts: # NEWS.md
2 parents 4293eb8 + 95a23b7 commit 0993aa3

35 files changed

+7328
-191
lines changed

.Rbuildignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,4 @@ book/*
1515
docs/*
1616
Rplots.pdf
1717
^\.github$
18+
^release-prep\.R$

.github/workflows/recheck.yaml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
on:
2+
workflow_dispatch:
3+
inputs:
4+
which:
5+
type: choice
6+
description: Which dependents to check
7+
options:
8+
- strong
9+
- most
10+
11+
name: Reverse dependency check
12+
13+
jobs:
14+
revdep_check:
15+
name: Reverse check ${{ inputs.which }} dependents
16+
uses: r-devel/recheck/.github/workflows/recheck.yml@v1
17+
with:
18+
which: ${{ inputs.which }}
19+
subdirectory: '' # set if your R package is in a subdir of the git repo
20+
repository: '' # set to recheck an R package from another git repo
21+
ref: '' # set to recheck a custom tag/branch from another repo

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,4 @@ cran-comments.md
1212
revdep/*
1313
CRAN-RELEASE
1414
CRAN-SUBMISSION
15+
release-prep.R

DESCRIPTION

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
Package: bayesplot
22
Type: Package
33
Title: Plotting for Bayesian Models
4-
Version: 1.12.0.9000
5-
Date: 2025-04-09
4+
Version: 1.13.0.9000
5+
Date: 2025-06-18
66
Authors@R: c(person("Jonah", "Gabry", role = c("aut", "cre"), email = "jsg2201@columbia.edu"),
77
person("Tristan", "Mahr", role = "aut", comment = c(ORCID = "0000-0002-8890-5116")),
88
person("Paul-Christian", "Bürkner", role = "ctb"),
@@ -41,6 +41,7 @@ Imports:
4141
tidyselect,
4242
utils
4343
Suggests:
44+
ggdist,
4445
ggfortify,
4546
gridExtra (>= 2.2.1),
4647
hexbin,

NAMESPACE

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ export(ppc_data)
123123
export(ppc_dens)
124124
export(ppc_dens_overlay)
125125
export(ppc_dens_overlay_grouped)
126+
export(ppc_dots)
126127
export(ppc_ecdf_overlay)
127128
export(ppc_ecdf_overlay_grouped)
128129
export(ppc_error_binned)
@@ -170,6 +171,7 @@ export(ppd_boxplot)
170171
export(ppd_data)
171172
export(ppd_dens)
172173
export(ppd_dens_overlay)
174+
export(ppd_dots)
173175
export(ppd_ecdf_overlay)
174176
export(ppd_freqpoly)
175177
export(ppd_freqpoly_grouped)

NEWS.md

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

3-
* Add possibility for left-truncation to `ppc_km_overlay()` and `ppc_km_overlay_grouped()` by @Sakuski
4-
* Added `ppc_loo_pit_ecdf()` by @TeemuSailynoja
53
* PPC "avg" functions (`ppc_scatter_avg()`, `ppc_error_scatter_avg()`, etc.) gain a `stat` argument to set the averaging function. (Suggestion of #348, @kruschke).
64
* `ppc_error_scatter_avg_vs_x(x = some_expression)` labels the *x* axis with `some_expression`.
75

6+
# bayesplot 1.13.0
7+
8+
* Add `ppc_loo_pit_ecdf()` by @TeemuSailynoja (#345)
9+
* Add possibility for left-truncation to `ppc_km_overlay()` and `ppc_km_overlay_grouped()` by @Sakuski (#347)
10+
* Give user control over extrapolation in `ppc_km_overlay()` and `ppc_km_overlay_grouped()` by @Sakuski (#353)
11+
* Allow passing `moment_match` via `...` for loo functions by @n-kall (#351)
12+
* Skip some tests when missing Suggests by @MichaelChirico (#344)
13+
* Remove a test that will fail with next ggplot2 release (#356)
14+
815
# bayesplot 1.12.0
916

1017
* Expand checking workflows to more platforms by @andrjohns (#324)

R/mcmc-distributions.R

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -472,7 +472,7 @@ mcmc_violin <- function(
472472
}
473473
}
474474

475-
geom_args <- list(size = 0.5, na.rm = TRUE, alpha = alpha)
475+
geom_args <- list(linewidth = 0.5, na.rm = TRUE, alpha = alpha)
476476
if (violin) {
477477
geom_args[["draw_quantiles"]] <- probs
478478
} else {

R/ppc-censoring.R

Lines changed: 50 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,12 @@
2424
#' @section Plot Descriptions:
2525
#' \describe{
2626
#' \item{`ppc_km_overlay()`}{
27-
#' Empirical CCDF estimates of each dataset (row) in `yrep` are overlaid,
28-
#' with the Kaplan-Meier estimate (Kaplan and Meier, 1958) for `y` itself on
29-
#' top (and in a darker shade). This is a PPC suitable for right-censored
30-
#' `y`. Note that the replicated data from `yrep` is assumed to be
31-
#' uncensored.
27+
#' Empirical CCDF estimates of each dataset (row) in `yrep` are overlaid, with
28+
#' the Kaplan-Meier estimate (Kaplan and Meier, 1958) for `y` itself on top
29+
#' (and in a darker shade). This is a PPC suitable for right-censored `y`.
30+
#' Note that the replicated data from `yrep` is assumed to be uncensored. Left
31+
#' truncation (delayed entry) times for `y` can be specified using
32+
#' `left_truncation_y`.
3233
#' }
3334
#' \item{`ppc_km_overlay_grouped()`}{
3435
#' The same as `ppc_km_overlay()`, but with separate facets by `group`.
@@ -40,24 +41,33 @@
4041
#' @template reference-km
4142
#'
4243
#' @examples
44+
#' \donttest{
4345
#' color_scheme_set("brightblue")
44-
#' y <- example_y_data()
46+
#'
4547
#' # For illustrative purposes, (right-)censor values y > 110:
48+
#' y <- example_y_data()
4649
#' status_y <- as.numeric(y <= 110)
4750
#' y <- pmin(y, 110)
51+
#'
4852
#' # In reality, the replicated data (yrep) would be obtained from a
4953
#' # model which takes the censoring of y properly into account. Here,
5054
#' # for illustrative purposes, we simply use example_yrep_draws():
5155
#' yrep <- example_yrep_draws()
5256
#' dim(yrep)
53-
#' \donttest{
57+
#'
58+
#' # Overlay 25 curves
5459
#' ppc_km_overlay(y, yrep[1:25, ], status_y = status_y)
55-
#' }
60+
#'
61+
#' # With extrapolation_factor = 1 (no extrapolation)
62+
#' ppc_km_overlay(y, yrep[1:25, ], status_y = status_y, extrapolation_factor = 1)
63+
#'
64+
#' # With extrapolation_factor = Inf (show all posterior predictive draws)
65+
#' ppc_km_overlay(y, yrep[1:25, ], status_y = status_y, extrapolation_factor = Inf)
66+
#'
5667
#' # With separate facets by group:
5768
#' group <- example_group_data()
58-
#' \donttest{
5969
#' ppc_km_overlay_grouped(y, yrep[1:25, ], group = group, status_y = status_y)
60-
#' }
70+
#'
6171
#' # With left-truncation (delayed entry) times:
6272
#' min_vals <- pmin(y, apply(yrep, 2, min))
6373
#' left_truncation_y <- rep(0, length(y))
@@ -66,7 +76,6 @@
6676
#' runif(sum(condition), min = 0.6, max = 0.99) * y[condition],
6777
#' min_vals[condition] - 0.001
6878
#' )
69-
#' \donttest{
7079
#' ppc_km_overlay(y, yrep[1:25, ], status_y = status_y,
7180
#' left_truncation_y = left_truncation_y)
7281
#' }
@@ -78,15 +87,23 @@ NULL
7887
#' be a numeric vector of the same length as `y` with values in \{0, 1\} (0 =
7988
#' right censored, 1 = event).
8089
#' @param left_truncation_y Optional parameter that specifies left-truncation
81-
#' (delayed entry) times for the observations from `y`. This must
82-
#' be a numeric vector of the same length as `y`. If `NULL` (default),
83-
#' no left-truncation is assumed.
90+
#' (delayed entry) times for the observations from `y`. This must be a numeric
91+
#' vector of the same length as `y`. If `NULL` (default), no left-truncation
92+
#' is assumed.
93+
#' @param extrapolation_factor A numeric value (>=1) that controls how far the
94+
#' plot is extended beyond the largest observed value in `y`. The default
95+
#' value is 1.2, which corresponds to 20 % extrapolation. Note that all
96+
#' posterior predictive draws may not be shown by default because of the
97+
#' controlled extrapolation. To display all posterior predictive draws, set
98+
#' `extrapolation_factor = Inf`.
99+
#'
84100
ppc_km_overlay <- function(
85101
y,
86102
yrep,
87103
...,
88104
status_y,
89105
left_truncation_y = NULL,
106+
extrapolation_factor = 1.2,
90107
size = 0.25,
91108
alpha = 0.7
92109
) {
@@ -97,15 +114,25 @@ ppc_km_overlay <- function(
97114
suggested_package("ggfortify")
98115

99116
if (!is.numeric(status_y) || length(status_y) != length(y) || !all(status_y %in% c(0, 1))) {
100-
stop("`status_y` must be a numeric vector of 0s and 1s the same length as `y`.")
117+
stop("`status_y` must be a numeric vector of 0s and 1s the same length as `y`.", call. = FALSE)
101118
}
102119

103120
if (!is.null(left_truncation_y)) {
104121
if (!is.numeric(left_truncation_y) || length(left_truncation_y) != length(y)) {
105-
stop("`left_truncation_y` must be a numeric vector of the same length as `y`.")
122+
stop("`left_truncation_y` must be a numeric vector of the same length as `y`.", call. = FALSE)
106123
}
107124
}
108125

126+
if (extrapolation_factor < 1) {
127+
stop("`extrapolation_factor` must be greater than or equal to 1.", call. = FALSE)
128+
}
129+
if (extrapolation_factor == 1.2) {
130+
message(
131+
"Note: `extrapolation_factor` now defaults to 1.2 (20%).\n",
132+
"To display all posterior predictive draws, set `extrapolation_factor = Inf`."
133+
)
134+
}
135+
109136
data <- ppc_data(y, yrep, group = status_y)
110137

111138
# Modify the status indicator:
@@ -149,6 +176,10 @@ ppc_km_overlay <- function(
149176
fsf$is_y_size <- ifelse(fsf$is_y_color == "yrep", size, 1)
150177
fsf$is_y_alpha <- ifelse(fsf$is_y_color == "yrep", alpha, 1)
151178

179+
max_time_y <- max(y, na.rm = TRUE)
180+
fsf <- fsf %>%
181+
dplyr::filter(.data$is_y_color != "yrep" | .data$time <= max_time_y * extrapolation_factor)
182+
152183
# Ensure that the observed data gets plotted last by reordering the
153184
# levels of the factor "strata"
154185
fsf$strata <- factor(fsf$strata, levels = rev(levels(fsf$strata)))
@@ -194,6 +225,7 @@ ppc_km_overlay_grouped <- function(
194225
...,
195226
status_y,
196227
left_truncation_y = NULL,
228+
extrapolation_factor = 1.2,
197229
size = 0.25,
198230
alpha = 0.7
199231
) {
@@ -207,7 +239,8 @@ ppc_km_overlay_grouped <- function(
207239
status_y = status_y,
208240
left_truncation_y = left_truncation_y,
209241
size = size,
210-
alpha = alpha
242+
alpha = alpha,
243+
extrapolation_factor = extrapolation_factor
211244
)
212245

213246
p_overlay +

R/ppc-distributions.R

Lines changed: 51 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
#' @template args-pit-ecdf
1616
#' @param size,alpha Passed to the appropriate geom to control the appearance of
1717
#' the predictive distributions.
18-
#' @param ... Currently unused.
18+
#' @param ... For dot plots, optional additional arguments to pass to [ggdist::stat_dots()].
1919
#'
2020
#' @template details-binomial
2121
#' @template return-ggplot-or-data
@@ -28,14 +28,19 @@
2828
#' dataset (row) in `yrep`. For these plots `yrep` should therefore
2929
#' contain only a small number of rows. See the **Examples** section.
3030
#' }
31+
#' \item{`ppc_dots()`}{
32+
#' A dot plot plot is displayed for `y` and each dataset (row) in `yrep`.
33+
#' For these plots `yrep` should therefore contain only a small number of rows.
34+
#' See the **Examples** section. This function requires [ggdist::stat_dots] to be installed.
35+
#' }
3136
#' \item{`ppc_freqpoly_grouped()`}{
3237
#' A separate frequency polygon is plotted for each level of a grouping
3338
#' variable for `y` and each dataset (row) in `yrep`. For this plot
3439
#' `yrep` should therefore contain only a small number of rows. See the
3540
#' **Examples** section.
3641
#' }
37-
#' \item{`ppc_ecdf_overlay(), ppc_dens_overlay(),
38-
#' ppc_ecdf_overlay_grouped(), ppc_dens_overlay_grouped()`}{
42+
#' \item{`ppc_ecdf_overlay()`, `ppc_dens_overlay()`,
43+
#' `ppc_ecdf_overlay_grouped()`, `ppc_dens_overlay_grouped()`}{
3944
#' Kernel density or empirical CDF estimates of each dataset (row) in
4045
#' `yrep` are overlaid, with the distribution of `y` itself on top
4146
#' (and in a darker shade). When using `ppc_ecdf_overlay()` with discrete
@@ -80,7 +85,7 @@
8085
#' ppc_pit_ecdf(y, yrep, prob = 0.99, plot_diff = TRUE)
8186
#' }
8287
#'
83-
#' # for ppc_hist,dens,freqpoly,boxplot definitely use a subset yrep rows so
88+
#' # for ppc_hist,dens,freqpoly,boxplot,dots definitely use a subset yrep rows so
8489
#' # only a few (instead of nrow(yrep)) histograms are plotted
8590
#' ppc_hist(y, yrep[1:8, ])
8691
#' \donttest{
@@ -90,6 +95,9 @@
9095
#' # wizard hat plot
9196
#' color_scheme_set("blue")
9297
#' ppc_dens(y, yrep[200:202, ])
98+
#'
99+
#' # dot plot
100+
#' ppc_dots(y, yrep[1:8, ])
93101
#' }
94102
#'
95103
#' \donttest{
@@ -507,6 +515,45 @@ ppc_boxplot <-
507515
xaxis_title(FALSE)
508516
}
509517

518+
#' @rdname PPC-distributions
519+
#' @export
520+
#' @template args-dots
521+
ppc_dots <-
522+
function(y,
523+
yrep,
524+
...,
525+
binwidth = NA,
526+
quantiles = NA,
527+
freq = TRUE) {
528+
check_ignored_arguments(..., ok_args = c("dotsize", "layout", "stackratio", "overflow"))
529+
530+
suggested_package("ggdist")
531+
532+
data <- ppc_data(y, yrep)
533+
534+
ggplot(data, mapping = set_hist_aes(
535+
freq = freq,
536+
fill = .data$is_y_label,
537+
color = .data$is_y_label
538+
)) +
539+
ggdist::stat_dots(
540+
binwidth = binwidth,
541+
quantiles = quantiles,
542+
...
543+
) +
544+
scale_fill_ppc() +
545+
scale_color_ppc() +
546+
facet_wrap_parsed("rep_label") +
547+
force_axes_in_facets() +
548+
bayesplot_theme_get() +
549+
space_legend_keys() +
550+
yaxis_text(FALSE) +
551+
yaxis_title(FALSE) +
552+
yaxis_ticks(FALSE) +
553+
xaxis_title(FALSE) +
554+
facet_text(FALSE) +
555+
facet_bg(FALSE)
556+
}
510557

511558
#' @rdname PPC-distributions
512559
#' @export

R/ppc-loo.R

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ ppc_loo_pit_overlay <- function(y,
174174
adjust = 1,
175175
kernel = "gaussian",
176176
n_dens = 1024) {
177-
check_ignored_arguments(...)
177+
check_ignored_arguments(..., ok_args = list("moment_match"))
178178

179179
data <-
180180
ppc_loo_pit_data(
@@ -333,7 +333,7 @@ ppc_loo_pit_qq <- function(y,
333333
compare = c("uniform", "normal"),
334334
size = 2,
335335
alpha = 1) {
336-
check_ignored_arguments(...)
336+
check_ignored_arguments(..., ok_args = list("moment_match"))
337337

338338
compare <- match.arg(compare)
339339
if (!is.null(pit)) {
@@ -409,7 +409,7 @@ ppc_loo_pit_ecdf <- function(y,
409409
prob = .99,
410410
plot_diff = FALSE,
411411
interpolate_adj = NULL) {
412-
check_ignored_arguments(...)
412+
check_ignored_arguments(..., ok_args = list("moment_match"))
413413

414414
if (!is.null(pit)) {
415415
inform("'pit' specified so ignoring 'y','yrep','lw' if specified.")
@@ -534,7 +534,7 @@ ppc_loo_intervals <-
534534
fatten = 2.5,
535535
linewidth = 1,
536536
order = c("index", "median")) {
537-
check_ignored_arguments(...)
537+
check_ignored_arguments(..., ok_args = list("moment_match"))
538538
y <- validate_y(y)
539539
order_by_median <- match.arg(order) == "median"
540540
if (!is.null(intervals)) {
@@ -626,7 +626,7 @@ ppc_loo_ribbon <-
626626
prob_outer = 0.9,
627627
alpha = 0.33,
628628
size = 0.25) {
629-
check_ignored_arguments(...)
629+
check_ignored_arguments(..., ok_args = list("moment_match"))
630630
y <- validate_y(y)
631631
if (!is.null(intervals)) {
632632
stopifnot(is.matrix(intervals), ncol(intervals) %in% c(3, 5))

0 commit comments

Comments
 (0)