Skip to content

Commit 9561cf8

Browse files
authored
Merge pull request #260 from fweber144/ppc_censoring_grouped
New function ppc_km_overlay_grouped()
2 parents c6919eb + b9f7819 commit 9561cf8

18 files changed

+479
-99
lines changed

NAMESPACE

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ export(ppc_intervals)
120120
export(ppc_intervals_data)
121121
export(ppc_intervals_grouped)
122122
export(ppc_km_overlay)
123+
export(ppc_km_overlay_grouped)
123124
export(ppc_loo_intervals)
124125
export(ppc_loo_pit)
125126
export(ppc_loo_pit_data)

NEWS.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@
1212
* `mcmc_areas()` and `mcmc_areas_ridges()` gain an argument `border_size` for
1313
controlling the thickness of the ridgelines. (#224)
1414

15+
* New plotting function `ppc_km_overlay_grouped()`, the grouped variant of
16+
`ppc_km_overlay()`. (#260, @fweber144)
17+
1518
# bayesplot 1.8.1
1619

1720
* Fix R cmd check error on linux for CRAN

R/ppc-censoring.R

Lines changed: 123 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
#' @template args-y-yrep
1818
#' @param size,alpha Passed to the appropriate geom to control the appearance of
1919
#' the `yrep` distributions.
20-
#' @param ... Currently unused.
20+
#' @param ... Currently only used internally.
2121
#'
2222
#' @template return-ggplot
2323
#'
@@ -30,6 +30,9 @@
3030
#' `y`. Note that the replicated data from `yrep` is assumed to be
3131
#' uncensored.
3232
#' }
33+
#' \item{`ppc_km_overlay_grouped()`}{
34+
#' The same as `ppc_km_overlay()`, but with separate facets by `group`.
35+
#' }
3336
#' }
3437
#'
3538
#' @templateVar bdaRef (Ch. 6)
@@ -50,81 +53,137 @@
5053
#' \donttest{
5154
#' ppc_km_overlay(y, yrep[1:25, ], status_y = status_y)
5255
#' }
56+
#' # With separate facets by group:
57+
#' group <- example_group_data()
58+
#' \donttest{
59+
#' ppc_km_overlay_grouped(y, yrep[1:25, ], group = group, status_y = status_y)
60+
#' }
5361
NULL
5462

5563
#' @export
5664
#' @rdname PPC-censoring
5765
#' @param status_y The status indicator for the observations from `y`. This must
5866
#' be a numeric vector of the same length as `y` with values in \{0, 1\} (0 =
5967
#' right censored, 1 = event).
60-
ppc_km_overlay <-
61-
function(y,
62-
yrep,
63-
...,
64-
status_y,
65-
size = 0.25,
66-
alpha = 0.7) {
67-
check_ignored_arguments(...)
68+
ppc_km_overlay <- function(
69+
y,
70+
yrep,
71+
...,
72+
status_y,
73+
size = 0.25,
74+
alpha = 0.7
75+
) {
76+
check_ignored_arguments(..., ok_args = "add_group")
77+
add_group <- list(...)$add_group
6878

69-
if(!requireNamespace("survival", quietly = TRUE)){
70-
abort("Package 'survival' required.")
71-
}
72-
if(!requireNamespace("ggfortify", quietly = TRUE)){
73-
abort("Package 'ggfortify' required.")
74-
}
79+
if(!requireNamespace("survival", quietly = TRUE)){
80+
abort("Package 'survival' required.")
81+
}
82+
if(!requireNamespace("ggfortify", quietly = TRUE)){
83+
abort("Package 'ggfortify' required.")
84+
}
7585

76-
stopifnot(is.numeric(status_y))
77-
stopifnot(all(status_y %in% c(0, 1)))
86+
stopifnot(is.numeric(status_y))
87+
stopifnot(all(status_y %in% c(0, 1)))
7888

79-
data <- ppc_data(y, yrep, group = status_y)
89+
data <- ppc_data(y, yrep, group = status_y)
8090

81-
# Modify the status indicator:
82-
# * For the observed data ("y"), convert the status indicator back to
83-
# a numeric.
84-
# * For the replicated data ("yrep"), set the status indicator
85-
# to 1 ("event"). This way, the Kaplan-Meier estimator reduces
86-
# to "1 - ECDF" with ECDF denoting the ordinary empirical cumulative
87-
# distribution function.
88-
data <- data %>%
89-
dplyr::mutate(group = ifelse(.data$is_y,
90-
as.numeric(as.character(.data$group)),
91-
1))
91+
# Modify the status indicator:
92+
# * For the observed data ("y"), convert the status indicator back to
93+
# a numeric.
94+
# * For the replicated data ("yrep"), set the status indicator
95+
# to 1 ("event"). This way, the Kaplan-Meier estimator reduces
96+
# to "1 - ECDF" with ECDF denoting the ordinary empirical cumulative
97+
# distribution function.
98+
data <- data %>%
99+
dplyr::mutate(group = ifelse(.data$is_y,
100+
as.numeric(as.character(.data$group)),
101+
1))
92102

93-
sf <- survival::survfit(
94-
survival::Surv(value, group) ~ rep_label,
95-
data = data
96-
)
97-
fsf <- fortify(sf)
103+
sf_form <- survival::Surv(value, group) ~ rep_label
104+
if(!is.null(add_group)){
105+
data <- dplyr::inner_join(data,
106+
tibble::tibble(y_id = seq_along(y),
107+
add_group = add_group),
108+
by = "y_id")
109+
sf_form <- update(sf_form, . ~ . + add_group)
110+
}
111+
sf <- survival::survfit(
112+
sf_form,
113+
data = data
114+
)
115+
names(sf$strata) <- sub("add_group=", "add_group:", names(sf$strata)) # Needed to split the strata names in ggfortify:::fortify.survfit() properly.
116+
fsf <- fortify(sf)
117+
if(any(grepl("add_group", levels(fsf$strata)))){
118+
strata_split <- strsplit(as.character(fsf$strata), split = ", add_group:")
119+
fsf$strata <- as.factor(sapply(strata_split, "[[", 1))
120+
fsf$group <- as.factor(sapply(strata_split, "[[", 2))
121+
}
98122

99-
fsf$is_y_color <- as.factor(sub("\\[rep\\] \\(.*$", "rep", sub("^italic\\(y\\)", "y", fsf$strata)))
100-
fsf$is_y_size <- ifelse(fsf$is_y_color == "yrep", size, 1)
101-
fsf$is_y_alpha <- ifelse(fsf$is_y_color == "yrep", alpha, 1)
123+
fsf$is_y_color <- as.factor(sub("\\[rep\\] \\(.*$", "rep", sub("^italic\\(y\\)", "y", fsf$strata)))
124+
fsf$is_y_size <- ifelse(fsf$is_y_color == "yrep", size, 1)
125+
fsf$is_y_alpha <- ifelse(fsf$is_y_color == "yrep", alpha, 1)
102126

103-
# Ensure that the observed data gets plotted last by reordering the
104-
# levels of the factor "strata"
105-
fsf$strata <- factor(fsf$strata, levels = rev(levels(fsf$strata)))
127+
# Ensure that the observed data gets plotted last by reordering the
128+
# levels of the factor "strata"
129+
fsf$strata <- factor(fsf$strata, levels = rev(levels(fsf$strata)))
106130

107-
ggplot(data = fsf,
108-
mapping = aes_(x = ~ time,
109-
y = ~ surv,
110-
color = ~ is_y_color,
111-
group = ~ strata,
112-
size = ~ is_y_size,
113-
alpha = ~ is_y_alpha)) +
114-
geom_step() +
115-
hline_at(
116-
c(0, 0.5, 1),
117-
size = c(0.2, 0.1, 0.2),
118-
linetype = 2,
119-
color = get_color("dh")
120-
) +
121-
scale_size_identity() +
122-
scale_alpha_identity() +
123-
scale_color_ppc_dist() +
124-
scale_y_continuous(breaks = c(0, 0.5, 1)) +
125-
xlab(y_label()) +
126-
yaxis_title(FALSE) +
127-
xaxis_title(FALSE) +
128-
yaxis_ticks(FALSE) +
129-
bayesplot_theme_get()
130-
}
131+
ggplot(data = fsf,
132+
mapping = aes_(x = ~ time,
133+
y = ~ surv,
134+
color = ~ is_y_color,
135+
group = ~ strata,
136+
size = ~ is_y_size,
137+
alpha = ~ is_y_alpha)) +
138+
geom_step() +
139+
hline_at(
140+
0.5,
141+
size = 0.1,
142+
linetype = 2,
143+
color = get_color("dh")
144+
) +
145+
hline_at(
146+
c(0, 1),
147+
size = 0.2,
148+
linetype = 2,
149+
color = get_color("dh")
150+
) +
151+
scale_size_identity() +
152+
scale_alpha_identity() +
153+
scale_color_ppc_dist() +
154+
scale_y_continuous(breaks = c(0, 0.5, 1)) +
155+
xlab(y_label()) +
156+
yaxis_title(FALSE) +
157+
xaxis_title(FALSE) +
158+
yaxis_ticks(FALSE) +
159+
bayesplot_theme_get()
160+
}
161+
162+
#' @export
163+
#' @rdname PPC-censoring
164+
#' @template args-group
165+
ppc_km_overlay_grouped <- function(
166+
y,
167+
yrep,
168+
group,
169+
...,
170+
status_y,
171+
size = 0.25,
172+
alpha = 0.7
173+
) {
174+
check_ignored_arguments(...)
175+
176+
p_overlay <- ppc_km_overlay(
177+
y = y,
178+
yrep = yrep,
179+
add_group = group,
180+
...,
181+
status_y = status_y,
182+
size = size,
183+
alpha = alpha
184+
)
185+
186+
p_overlay +
187+
facet_wrap("group") +
188+
force_axes_in_facets()
189+
}

man-roxygen/args-group.R

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
#' @param group A grouping variable (a vector or factor) the same length as
1+
#' @param group A grouping variable (a vector or factor) of the same length as
22
#' `y`. Each value in `group` is interpreted as the group level
33
#' pertaining to the corresponding value of `y`.

man/PPC-censoring.Rd

Lines changed: 16 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

man/PPC-discrete.Rd

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

man/PPC-distributions.Rd

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

man/PPC-errors.Rd

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

man/PPC-intervals.Rd

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

man/PPC-scatterplots.Rd

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)