Skip to content

Commit b9fe9e0

Browse files
committed
Add pp_check functionality for stanjm objects
1 parent 49ab027 commit b9fe9e0

14 files changed

+165
-67
lines changed

R/datasets.R

+32-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
#' Small datasets for use in \pkg{rstanarm} examples and vignettes.
2121
#'
2222
#' @name rstanarm-datasets
23-
#' @aliases kidiq roaches wells bball1970 bball2006 mortality tumors radon
23+
#' @aliases kidiq roaches wells bball1970 bball2006 mortality tumors radon pbcLong pbcSurv
2424
#' @format
2525
#' \describe{
2626
#' \item{\code{bball1970}}{
@@ -76,6 +76,34 @@
7676
#' \item \code{K} Number of surgeries
7777
#' }
7878
#' }
79+
#' \item{\code{pbcLong,pbcSurv}}{
80+
#' Longitudinal biomarker and time-to-event survival data for 40 patients
81+
#' with primary biliary cirrhosis who participated in a randomised
82+
#' placebo controlled trial of D-penicillamine conducted at the Mayo
83+
#' Clinic between 1974 and 1984.
84+
#'
85+
#' Source: Therneau and Grambsch (2000)
86+
#'
87+
#' 304 obs. of 8 variables (\code{pbcLong}) and 40 obs. of 7 variables (\code{pbcSurv})
88+
#' \itemize{
89+
#' \item \code{age} {in years}
90+
#' \item \code{albumin} {serum albumin (g/dl)}
91+
#' \item \code{logBili} {logarithm of serum bilirubin}
92+
#' \item \code{death} {indicator of death at endpoint}
93+
#' \item \code{futimeYears} {time (in years) between baseline and
94+
#' the earliest of death, transplantion or censoring}
95+
#' \item \code{id} {numeric ID unique to each individual}
96+
#' \item \code{platelet} {platelet count}
97+
#' \item \code{sex} {gender (m = male, f = female)}
98+
#' \item \code{status} {status at endpoint (0 = censored,
99+
#' 1 = transplant, 2 = dead)}
100+
#' \item \code{trt} {binary treatment code (0 = placebo, 1 =
101+
#' D-penicillamine)}
102+
#' \item \code{year} {time (in years) of the longitudinal measurements,
103+
#' taken as time since baseline)}
104+
#' }
105+
#' }
106+
#'
79107
#' \item{\code{radon}}{
80108
#' Data on radon levels in houses in the state of Minnesota.
81109
#'
@@ -159,6 +187,9 @@
159187
#' Tarone, R. E. (1982) The use of historical control information in testing for
160188
#' a trend in proportions. \emph{Biometrics} \strong{38}(1):215--220.
161189
#'
190+
#' Therneau, T. and Grambsch, P. (2000) \emph{Modeling Survival Data: Extending
191+
#' the Cox Model}. Springer-Verlag, New York, US.
192+
#'
162193
#' @examples
163194
#' # Using 'kidiq' dataset
164195
#' fit <- stan_lm(kid_score ~ mom_hs * mom_iq, data = kidiq,

R/example_jm.R

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# Part of the rstanarm package for estimating model parameters
2+
# Copyright (C) 2015, 2016 Trustees of Columbia University
3+
# Copyright (C) 2016 Sam Brilleman
4+
#
5+
# This program is free software; you can redistribute it and/or
6+
# modify it under the terms of the GNU General Public License
7+
# as published by the Free Software Foundation; either version 3
8+
# of the License, or (at your option) any later version.
9+
#
10+
# This program is distributed in the hope that it will be useful,
11+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
# GNU General Public License for more details.
14+
#
15+
# You should have received a copy of the GNU General Public License
16+
# along with this program; if not, write to the Free Software
17+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18+
19+
#' Example joint longitudinal and time-to-event model
20+
#'
21+
#' A model for use in the \pkg{rstanarm} examples related to \code{\link{stan_jm}}.
22+
#'
23+
#' @name example_jm
24+
#' @format Calling \code{example("example_jm")} will run the model in the
25+
#' Examples section, below, and the resulting stanjm object will then be
26+
#' available in the global environment. The \code{chains} and \code{iter}
27+
#' arguments are specified to make this example be small in size. In practice,
28+
#' we recommend that they be left unspecified in order to use the default
29+
#' values or increased if there are convergence problems. The \code{cores}
30+
#' argument is optional and on a multicore system, the user may well want
31+
#' to set that equal to the number of chains being executed.
32+
#'
33+
#' @examples
34+
#' set.seed(123)
35+
#' example_jm <-
36+
#' stan_jm(formulaLong = logBili ~ year + (1 | id),
37+
#' dataLong = pbcLong,
38+
#' formulaEvent = Surv(futimeYears, death) ~ sex + trt,
39+
#' dataEvent = pbcSurv,
40+
#' time_var = "year",
41+
#' # this next line is only to keep the example small in size!
42+
#' chains = 1, cores = 1, seed = 12345, iter = 1000)
43+
#'
44+
#'
45+
NULL

R/posterior_linpred.R

+3-2
Original file line numberDiff line numberDiff line change
@@ -78,14 +78,15 @@ posterior_linpred.stanreg <-
7878
dat <- pp_data(object,
7979
newdata = newdata,
8080
re.form = re.form,
81-
offset = offset)
81+
offset = offset,
82+
...)
8283
if (XZ) {
8384
XZ <- dat[["x"]]
8485
if (is.mer(object))
8586
XZ <- cbind(XZ, t(dat[["Zt"]]))
8687
return(XZ)
8788
}
88-
eta <- pp_eta(object, data = dat, draws = NULL)[["eta"]]
89+
eta <- pp_eta(object, data = dat, draws = NULL, ...)[["eta"]]
8990
if (!transform)
9091
return(eta)
9192

R/posterior_predict.R

+6-2
Original file line numberDiff line numberDiff line change
@@ -143,15 +143,19 @@ posterior_predict.stanreg <- function(object, newdata = NULL, draws = NULL,
143143
fun <- match.fun(fun)
144144

145145
dots <- list(...)
146-
m <- if (is.stanjm(object) && is.null(dots$m)) 1 else dots$m
146+
if (is.stanjm(object)) {
147+
dots <- list(...)
148+
m <- dots[["m"]]
149+
if (is.null(m))
150+
stop("Argument 'm' must be provided for stanjm objects.")
151+
} else m <- NULL
147152

148153
newdata <- validate_newdata(newdata)
149154
dat <-
150155
pp_data(object,
151156
newdata = newdata,
152157
re.form = re.form,
153158
offset = offset,
154-
m = m,
155159
...)
156160
if (is_scobit(object)) {
157161
data <- pp_eta(object, dat, NULL)

R/posterior_survfit.R

+17-18
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@
9292
#' percentiles will be provided.
9393
#' @param times A numeric vector of length 1 or a character string. Specifies the
9494
#' times at which to obtain the estimated survival probabilities.
95-
#' If \code{newdata} is not provided, then the
95+
#' If \code{newdata} is \code{NULL}, then the
9696
#' \code{times} argument is optional; if it is not provided then \code{times}
9797
#' will default to the last known event or censoring time for each individual,
9898
#' whereas if it is provided then it must be a numeric vector of length 1, and
@@ -161,13 +161,13 @@
161161
#'
162162
#' @seealso \code{\link{plot.survfit.stanjm}} for plotting the estimated survival
163163
#' probabilities, \code{\link{ps_check}} for for graphical checks of the estimated
164-
#' survival function, and \code{\link{posterior_predict}} for estimating the
164+
#' survival function, and \code{\link{posterior_traj}} for estimating the
165165
#' marginal or subject-specific longitudinal trajectories.
166166
#'
167167
#' @examples
168168
#'
169169
#' # Run example model if not already loaded
170-
#' if (!exists("examplejm")) example(examplejm)
170+
#' if (!exists("example_jm")) example(example_jm)
171171
#'
172172
#' # Obtain subject-specific survival probabilities for a few
173173
#' # selected individuals in the estimation dataset who were
@@ -176,8 +176,8 @@
176176
#' # survival probabilities, that is, conditional on having survived
177177
#' # until the event or censoring time, and then by default will
178178
#' # extrapolate the survival predictions forward from there.
179-
#' head(pbcSurv_subset[pbcSurv_subset$status == 0,])
180-
#' ps1 <- posterior_survfit(examplejm, ids = c(7,13,16))
179+
#' head(pbcSurv[pbcSurv$status == 0,])
180+
#' ps1 <- posterior_survfit(example_jm, ids = c(7,13,16))
181181
#' head(ps1)
182182
#' # We can plot the estimated survival probabilities using the
183183
#' # associated plot function
@@ -193,8 +193,8 @@
193193
#' # is to specify that we want the survival time estimated at time 0
194194
#' # and then extrapolated forward 5 years. We also specify that we
195195
#' # do not want to condition on their last known survival time.
196-
#' ps2 <- posterior_survfit(examplejm, ids = c(7,13,16), times == 0,
197-
#' extrapolate = TRUE, control = list(ext_distance = 5, condition = FALSE))
196+
#' ps2 <- posterior_survfit(example_jm, ids = c(7,13,16), times == 0,
197+
#' extrapolate = TRUE, control = list(edist = 5, condition = FALSE))
198198
#' ps2
199199
#'
200200
#' # Instead of estimating survival probabilities for a specific individual
@@ -215,8 +215,8 @@
215215
#' nd <- data.frame(id = c("new1", "new2"),
216216
#' sex = c("f", "f"),
217217
#' trt = c(1, 0))
218-
#' ps3 <- posterior_survfit(examplejm, newdata = nd, times = 0,
219-
#' extrapolate = TRUE, control = list(ext_distance = 5, condition = FALSE))
218+
#' ps3 <- posterior_survfit(example_jm, newdata = nd, times = 0,
219+
#' extrapolate = TRUE, control = list(edist = 5, condition = FALSE))
220220
#' ps3
221221
#'
222222
#' # We can then plot the estimated survival functions to compare
@@ -229,7 +229,7 @@
229229
#' # for individuals in our estimation sample) then we can specify
230230
#' # 'standardise = TRUE'. We can then plot the resulting standardised
231231
#' # survival curve.
232-
#' ps4 <- posterior_survfit(examplejm, standardise = TRUE,
232+
#' ps4 <- posterior_survfit(example_jm, standardise = TRUE,
233233
#' times = 0, extrapolate = TRUE)
234234
#' plot(ps4)
235235
#'
@@ -482,16 +482,16 @@ posterior_survfit <- function(object, newdata = NULL, extrapolate = TRUE,
482482
#' It can also be passed to the function \code{\link{plot_stack}}.
483483
#'
484484
#' @seealso \code{\link{posterior_survfit}}, \code{\link{plot_stack}},
485-
#' \code{\link{posterior_predict}}, \code{\link{plot.predict.stanjm}}
485+
#' \code{\link{posterior_traj}}, \code{\link{plot.predict.stanjm}}
486486
#'
487487
#' @examples
488488
#'
489489
#' # Run example model if not already loaded
490-
#' if (!exists("examplejm")) example(examplejm)
490+
#' if (!exists("example_jm")) example(example_jm)
491491
#'
492492
#' # Obtain subject-specific conditional survival probabilities
493493
#' # for all individuals in the estimation dataset.
494-
#' ps1 <- posterior_survfit(examplejm, extrapolate = TRUE)
494+
#' ps1 <- posterior_survfit(example_jm, extrapolate = TRUE)
495495
#'
496496
#' # We then plot the conditional survival probabilities for
497497
#' # a subset of individuals
@@ -516,17 +516,16 @@ posterior_survfit <- function(object, newdata = NULL, extrapolate = TRUE,
516516
#' # subject-specific survival functions, with plot(s)
517517
#' # of the estimated longitudinal trajectories for the
518518
#' # same individuals
519-
#' ps1 <- posterior_survfit(examplejm, ids = c(7,13,16))
520-
#' pt1 <- posterior_predict(examplejm, , ids = c(7,13,16),
521-
#' interpolate = TRUE, extrapolate = TRUE)
519+
#' ps1 <- posterior_survfit(example_jm, ids = c(7,13,16))
520+
#' pt1 <- posterior_traj(example_jm, , ids = c(7,13,16))
522521
#' plot_surv <- plot(ps1)
523522
#' plot_traj <- plot(pt1, vline = TRUE, plot_observed = TRUE)
524523
#' plot_stack(plot_traj, plot_surv)
525524
#'
526525
#' # Lastly, let us plot the standardised survival function
527526
#' # based on all individuals in our estimation dataset
528-
#' ps2 <- posterior_survfit(examplejm, standardise = TRUE, times = 0,
529-
#' control = list(ext_points = 20))
527+
#' ps2 <- posterior_survfit(example_jm, standardise = TRUE, times = 0,
528+
#' control = list(epoints = 20))
530529
#' plot(ps2)
531530
#'
532531
#'

R/posterior_traj.R

+10-10
Original file line numberDiff line numberDiff line change
@@ -118,30 +118,30 @@
118118
#' @examples
119119
#' \donttest{
120120
#' # Run example model if not already loaded
121-
#' if (!exists("examplejm")) example(examplejm)
121+
#' if (!exists("example_jm")) example(example_jm)
122122
#'
123123
#' # Obtain subject-specific predictions for all individuals
124124
#' # in the estimation dataset
125-
#' pt1 <- posterior_traj(examplejm, interpolate = FALSE, extrapolate = FALSE)
125+
#' pt1 <- posterior_traj(example_jm, interpolate = FALSE, extrapolate = FALSE)
126126
#' head(pt1)
127127
#'
128128
#' # Obtain subject-specific predictions only for a few selected individuals
129-
#' pt2 <- posterior_traj(examplejm, ids = c(1,3,8))
129+
#' pt2 <- posterior_traj(example_jm, ids = c(1,3,8))
130130
#'
131131
#' # If we wanted to obtain subject-specific predictions in order to plot the
132132
#' # longitudinal trajectories, then we might want to ensure a full trajectory
133133
#' # is obtained by interpolating and extrapolating time. We can then use the
134134
#' # generic plot function to plot the subject-specific predicted trajectories
135135
#' # for the first three individuals. Interpolation and extrapolation is
136136
#' # carried out by default.
137-
#' pt3 <- posterior_traj(examplejm)
137+
#' pt3 <- posterior_traj(example_jm)
138138
#' head(pt3) # predictions at additional time points compared with pt1
139139
#' plot(pt3, ids = 1:3)
140140
#'
141141
#' # If we wanted to extrapolate further in time, but decrease the number of
142142
#' # discrete time points at which we obtain predictions for each individual,
143143
#' # then we could specify a named list in the 'control' argument
144-
#' pt4 <- posterior_traj(examplejm, control = list(ipoints = 10, epoints = 10, eprop = 0.5))
144+
#' pt4 <- posterior_traj(example_jm, control = list(ipoints = 10, epoints = 10, eprop = 0.5))
145145
#'
146146
#' # Alternatively we may want to estimate the marginal longitudinal
147147
#' # trajectory for a given set of covariates. To do this, we can pass
@@ -155,7 +155,7 @@
155155
#' # Our marginal prediction will therefore capture the between-individual
156156
#' # variation associated with the random effects.)
157157
#' nd <- data.frame(id = rep("new1", 11), year = (0:10 / 2))
158-
#' pt5 <- posterior_traj(examplejm, newdata = nd)
158+
#' pt5 <- posterior_traj(example_jm, newdata = nd)
159159
#' head(pt5) # note the greater width of the uncertainty interval compared
160160
#' # with the subject-specific predictions in pt1, pt2, etc
161161
#'
@@ -176,7 +176,7 @@
176176
#' # the fixed effect component of the model, we simply specify 're.form = NA'.
177177
#' # (We will use the same covariate values as used in the prediction for
178178
#' # example for pt5).
179-
#' pt6 <- posterior_traj(examplejm, newdata = nd, re.form = NA)
179+
#' pt6 <- posterior_traj(example_jm, newdata = nd, re.form = NA)
180180
#' head(pt6) # note the much narrower ci, compared with pt5
181181
#' }
182182
#'
@@ -339,18 +339,18 @@ posterior_traj <- function(object, m = 1, newdata = NULL,
339339
#' @examples
340340
#'
341341
#' # Run example model if not already loaded
342-
#' if (!exists("examplejm")) example(examplejm)
342+
#' if (!exists("example_jm")) example(example_jm)
343343
#'
344344
#' # For a subset of individuals in the estimation dataset we will
345345
#' # obtain subject-specific predictions for the longitudinal submodel
346346
#' # at evenly spaced times between 0 and their event or censoring time.
347-
#' pt1 <- posterior_traj(examplejm, ids = c(7,13,16), interpolate = TRUE)
347+
#' pt1 <- posterior_traj(example_jm, ids = c(7,13,16), interpolate = TRUE)
348348
#' plot(pt1) # credible interval for mean response
349349
#' plot(pt1, limits = "pi") # prediction interval for raw response
350350
#' plot(pt1, limits = "none") # no uncertainty interval
351351
#'
352352
#' # We can also extrapolate the longitudinal trajectories.
353-
#' pt2 <- posterior_traj(examplejm, ids = c(7,13,16), interpolate = TRUE,
353+
#' pt2 <- posterior_traj(example_jm, ids = c(7,13,16), interpolate = TRUE,
354354
#' extrapolate = TRUE)
355355
#' plot(pt2)
356356
#' plot(pt2, vline = TRUE) # add line indicating event or censoring time

0 commit comments

Comments
 (0)