er_model_interface: Model interface for exposure-response plots

er_model_interfaceR Documentation

Model interface for exposure-response plots

Description

erplots draws exposure-response plots from fitted models that implement this small interface, rather than assuming a particular model class:

  • Implement er_predict() for basic plotting support.

  • Implement er_simulate() for simulation-based visualisations.

  • Implement er_summary() for summary annotations.

  • Implement er_predict_survival() for a parametric survival-curve overlay in the er_tte() grammar (er_tte_add_model()).

Usage

er_predict(model, newdata, conf_level = 0.95, ...)

er_simulate(model, newdata, nsim = 100, seed = NULL, ...)

er_summary(model, ...)

er_predict_survival(model, newdata, time_grid, conf_level = 0.95, ...)

Arguments

model

A fitted exposure-response model object.

newdata

A data frame of covariate values at which to predict. For er_predict_survival(), one row per covariate profile (e.g. one per stratum level) – it does not include a time column; times come from time_grid instead (see "Details").

conf_level

Confidence level for the prediction interval.

...

Passed to methods.

nsim

Number of simulation replicates.

seed

Optional RNG seed.

time_grid

Numeric vector of times at which to predict S(t).

Details

er_plot_add_model() does not verify that model was fit on the same exposure/response variables as the plot; that compatibility is the caller's responsibility. When er_plot_add_model() builds newdata, it always includes the exposure and, if stratified, strata variables, plus reference values for any other covariates in the model's original fitting data.

Strata membership for er_predict_survival() is carried on newdata the same way: as an ordinary column (named after the er_tte() object's own stratify_by variable), never implicit in model itself. er_tte_add_model() builds one newdata row per stratum level (or a single row, unstratified), filling any other covariate the model references with a reference value exactly as er_plot_add_model() already does (see its "Details").

A method may rely on caller-supplied extra arguments being forwarded through ...: er_plot_add_model()'s predict_args, er_plot_add_summary()'s summary_args, and er_vpc_add_simulated()'s simulate_args are each spliced into the corresponding generic call (er_predict()/er_summary()/er_simulate() respectively), so a model-specific argument beyond the fixed contract below (e.g. a landmark time for a time-to-event model) has a documented path to reach the method. These are deliberately kept separate from each ⁠er_plot_add_*()⁠/⁠er_vpc_add_*()⁠ function's own ..., which is reserved for the style builder instead (see er_style()'s "Passing extra arguments to a builder" section) – a method should not assume it receives anything passed via that ....

Value

  • er_predict() returns newdata with three additional columns: fit_resp (point prediction), ci_lower, and ci_upper.

  • er_simulate() returns a data frame containing nsim replicates of newdata, with a sim_id column identifying each replicate, and a fit_resp column giving the simulated prediction for that replicate (reflecting parameter uncertainty). Models that cannot support simulation-based visualisation should not implement a method; the default method returns NULL; callers should treat a NULL result as "not available" rather than an error.

    A method may additionally return a sim_resp column: a full response-scale draw for that replicate/observation, reflecting both parameter uncertainty (as fit_resp already does) and observation-level sampling/residual noise (e.g. a 0/1 draw for a binary response, an integer draw for a count response, a draw including residual variance for a continuous response) – not just the fitted mean/probability. This is what er_vpc_add_simulated()'s model argument requires: a visual predictive check needs simulated observations comparable to the actually observed data, not points on the mean curve, which is a genuinely different question from the one fit_resp (used by er_style_model_spaghetti()) answers. sim_resp is independently optional – a method can supply fit_resp alone (as every implementation did before sim_resp existed, and as remains sufficient for spaghetti plots), or both columns from the same call. er_vpc_add_simulated() treats a sim_resp-less result the same way it treats an outright NULL: "predictive simulation not available for this model."

  • er_summary() returns NULL (nothing available – the default method's behaviour), or a named list with any of the following independently optional keys. Unrecognised keys are permitted and ignored by built-in builders, giving a model package room to stash extra fields for its own custom builders.

    • p_value: a single headline p-value (or NULL) for "the" exposure effect, when the model has one unambiguous candidate (e.g. a GLM's exposure coefficient). A model with no single privileged parameter (e.g. a multi-parameter nonlinear Emax model, with separate E0/ Emax/EC50/Hill terms and no obviously "the" effect) should return NULL here rather than picking an arbitrary term – er_style_summary_pvalue() already treats NULL as "nothing to show".

    • coefficients: a tibble/data frame with one row per model parameter, for builders (e.g. er_style_summary_coefficients()) that display more than a single p-value. Columns follow this package's snake_case convention rather than broom::tidy()'s dotted names: term (required), label (optional display name, falls back to term), estimate (required), and optional std_error, statistic, p_value, conf_low, conf_high (each NA if not computed/meaningful). NULL if not available.

    • glance: a single-row tibble/data frame of model-level goodness-of-fit, broom::glance()-style: optional n, df_residual, logLik, aic, bic, deviance, r_squared (NA where not meaningful, e.g. non-Gaussian models), converged. Reserved for future builders; no built-in builder currently consumes it. NULL if not available.

    This is purely additive: a method that only ever returns list(p_value = ...) (as above) continues to work unchanged.

  • er_predict_survival() returns newdata, cross-joined with time_grid (one row per newdata row x time_grid value), with three additional columns: time, fit_survival (the point estimate of ⁠S(time | newdata row)⁠), ci_lower, and ci_upper. Unlike er_predict(), newdata here never includes a time/exposure column itself – time_grid is a separate argument, so a method can build the full time grid in one call per covariate profile rather than being handed a pre-crossed data frame. There is no default method that returns NULL; a model with no survival-curve support should simply not implement this generic, and er_tte_add_model() errors informatively (via the default method above) if called with one.

Examples

# a bare-bones er_predict() method for a plain `lm` fit
toy_fit <- lm(biomarker_change ~ auc_ss, data = erplots_data)
class(toy_fit) <- c("toy_lm", class(toy_fit))

er_predict.toy_lm <- function(model, newdata, conf_level = 0.95, ...) {
  z <- -qnorm((1 - conf_level) / 2)
  pred <- predict(model, newdata = newdata, se.fit = TRUE)
  newdata$fit_resp <- pred$fit
  newdata$ci_lower <- pred$fit - z * pred$se.fit
  newdata$ci_upper <- pred$fit + z * pred$se.fit
  newdata
}

er_predict(toy_fit, newdata = data.frame(auc_ss = c(100, 500, 900)))


erplots documentation built on Oct. 4, 2026, 5:06 p.m.