Skip to content

Commit 8b07034

Browse files
authored
Merge pull request #353 from Sakuski/ppc_km_overlay-extrapolation_factor
Add possibility to control extrapolation in ppc_km_overlay() and ppc_km_overlay_grouped()
2 parents e4df4b6 + a5d4829 commit 8b07034

12 files changed

+684
-159
lines changed

NEWS.md

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

3+
* Add extrapolation_factor parameter to `ppc_km_overlay()` and `ppc_km_overlay_grouped()` by @Sakuski
34
* Add possibility for left-truncation to `ppc_km_overlay()` and `ppc_km_overlay_grouped()` by @Sakuski
45
* Added `ppc_loo_pit_ecdf()` by @TeemuSailynoja
56

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(is_y_color != "yrep" | 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 +

man/PPC-censoring.Rd

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

0 commit comments

Comments
 (0)