| Type: | Package |
| Title: | Improved Parametric Empirical Bayes for Longitudinal Biomarker Analysis |
| Version: | 0.1.1 |
| Description: | Extends parametric empirical Bayes (PEB) for longitudinal biomarker screening with a time-gap-aware standardization layer, covariate adjustment, and objective-driven multi-marker weighting. The layer models each subject's biomarker history with a random intercept (and an optional random slope) and autocorrelated, gap-scaled residuals, so that prediction uncertainty grows with the time between visits and per-visit specificity is preserved under irregular sampling. Marker weights are learned to optimize a user-selected clinical objective – maximizing sensitivity at a fixed specificity, extending detection lead time, or a combined objective – with optional feature selection and a choice of scalar or multivariate combiner. Functions for fitting, prediction, and evaluation (sensitivity, lead time, and specificity at chosen operating points) are provided. A manuscript describing the method is in preparation. |
| License: | MIT + file LICENSE |
| Encoding: | UTF-8 |
| LazyData: | true |
| Depends: | R (≥ 4.0.0) |
| Imports: | nlme, stats, graphics, utils |
| Suggests: | testthat (≥ 3.0.0), knitr, rmarkdown, shiny |
| VignetteBuilder: | knitr |
| URL: | https://github.com/bitansa/iPEB |
| BugReports: | https://github.com/bitansa/iPEB/issues |
| Config/testthat/edition: | 3 |
| Config/roxygen2/version: | 8.1.0 |
| NeedsCompilation: | no |
| Packaged: | 2026-09-09 18:47:02 UTC; bitansarkar |
| Author: | Bitan Sarkar |
| Maintainer: | Bitan Sarkar <bitansarkar010899@gmail.com> |
| Repository: | CRAN |
| Date/Publication: | 2026-09-17 13:20:08 UTC |
iPEB: Improved Parametric Empirical Bayes for Longitudinal Biomarker Analysis
Description
The iPEB package fits the improved Parametric Empirical Bayes model, which extends parametric empirical Bayes with a time-gap-aware standardization layer, covariate adjustment, and objective-driven multi-marker weighting.
Details
The main entry point is ipeb, which fits the model on training
data. Fitted objects have predict.ipeb and
evaluate methods for scoring and evaluating new subjects, and
ipeb_run provides a one-call fit-and-evaluate wrapper.
Data format
Functions expect a long-format data.frame with one row per
(subject, visit): a subject identifier column, a case/control indicator
(1 = case, 0 = control), one column per biomarker, a visit-time column, and a
column giving each visit's time before diagnosis (used to score lead time).
Column names are supplied through the fitting arguments.
Author(s)
Maintainer: Bitan Sarkar bitansarkar010899@gmail.com (ORCID) [copyright holder]
Authors:
Bitan Sarkar bitansarkar010899@gmail.com (ORCID) [copyright holder]
Ana Maria Kenney
James P. Long
Johannes F. Fahrmann
Samir Hanash
Kim-Anh Do
Ehsan Irajizad
See Also
Useful links:
Evaluate a fitted iPEB model
Description
Computes per-patient sensitivity and median lead time with per-visit
specificity at one or more operating points. Operating thresholds are
calibrated on the training control visits stored in the fitted object and
applied unchanged to newdata, so every reported number is
out-of-sample when newdata are held-out subjects.
Usage
evaluate(object, ...)
## S3 method for class 'ipeb'
evaluate(object, newdata, specificities = NULL, window = NULL, ...)
Arguments
object |
A fitted |
... |
Passed to methods. |
newdata |
A data frame with the fitting schema, including the case indicator (needed to score sensitivity and lead time). |
specificities |
Numeric vector of target specificities. Defaults to the specificity the model was optimized at. |
window |
Optional evaluation detection window in months. If |
Value
A data frame with one row per requested specificity and columns
specificity (target), sensitivity, lead_time (median,
years), realized_specificity (achieved on newdata), and
auc (subject-level, specificity-independent).
Examples
data(ipeb_example)
train <- subset(ipeb_example, split == "train")
test <- subset(ipeb_example, split == "test")
fit <- ipeb(train, markers = c("m1", "m2", "m3"),
innovation = "iid", slope = "off")
evaluate(fit, test, specificities = c(0.90, 0.95, 0.99))
Fit an improved Parametric Empirical Bayes (iPEB) model
Description
Fits the iPEB model on longitudinal biomarker data: a time-gap-aware
standardization layer, optional covariate adjustment, objective-driven
multi-marker weighting, optional feature selection, and an automatically
chosen scalar or multivariate combiner. The returned object can score and
evaluate new subjects with predict.ipeb and
evaluate.
Usage
ipeb(
data,
markers,
id = "id",
case = "case",
time = "time",
time_to_dx = "time_to_dx",
covariates = character(0),
objective = c("sensitivity", "leadtime", "combined"),
alpha = 0.95,
window = Inf,
slope = c("auto", "on", "off"),
innovation = c("auto", "ar1", "iid"),
select = c("none", "backward"),
n_markers = NULL,
validation_frac = 0.25,
seed = NULL
)
Arguments
data |
A long-format data frame with one row per subject-visit. |
markers |
Character vector of biomarker column names. |
id, case, time, time_to_dx |
Column names for the subject identifier, the case indicator (1 = case, 0 = control), the visit time, and each visit's time before diagnosis (in days; used to measure lead time). |
covariates |
Character vector of covariate column names to adjust for (default none). |
objective |
Clinical objective: |
alpha |
Operating specificity at which the combiner is optimized
(default |
window |
Optional detection window in months restricting the objective
to a fixed pre-diagnostic horizon. The default, |
slope |
Random-slope layer: |
innovation |
Residual model: |
select |
Feature selection by objective-driven backward elimination:
|
n_markers |
Optional target panel size when |
validation_frac |
Fraction of training subjects held out as an internal
validation slice to choose the combiner variant and drive selection
(default |
seed |
Optional single number. 'ipeb()' draws an internal validation split of the training subjects (and, when 'select' is not '"none"', uses it for feature selection), so repeated calls on identical data can return slightly different weights. Supplying 'seed' fixes that draw and makes a fit exactly reproducible; the default 'NULL' leaves the RNG untouched. |
Value
An object of class "ipeb": a list with the fitted weights,
selected markers, chosen variant, layer parameters, and the training
control scores used to calibrate operating thresholds.
See Also
predict.ipeb, evaluate, ipeb_run
Examples
data(ipeb_example)
train <- subset(ipeb_example, split == "train")
fit <- ipeb(train, markers = c("m1", "m2", "m3"),
id = "id", case = "case", time = "time",
time_to_dx = "time_to_dx", objective = "sensitivity",
innovation = "iid", slope = "off")
fit
Synthetic longitudinal biomarker example
Description
A small, entirely simulated longitudinal cohort used to illustrate the
package. Each subject contributes several irregularly spaced visits with
three biomarkers. In cases, marker m1 rises from roughly two years
before diagnosis and m2 rises late (a few months before), while
m3 is uninformative; controls have no pre-diagnostic rise. No real
patient data are used.
Usage
ipeb_example
Format
A data frame with one row per subject-visit and columns:
- id
Subject identifier.
- case
Case indicator (1 = case, 0 = control).
- time
Visit time in years since the subject's first visit.
- time_to_dx
Days from the visit to diagnosis (positive).
- m1, m2, m3
Biomarker measurements.
- split
Suggested
"train"/"test"split by subject.
Source
Simulated by data-raw/make_example.R.
Time-gap-aware standardized innovations
Description
Returns the innovation-standardized residuals from the iPEB layer: for each marker, a random intercept (and optional slope) model with autocorrelated, gap-scaled residuals is estimated on the healthy reference subjects, and every visit is scored by sequential one-step prediction (history to innovation, divided by its prediction standard deviation). The prediction variance grows with the gap since the previous visit, so the innovations are comparable across irregular schedules.
Usage
ipeb_innovations(
data,
markers,
reference_ids = NULL,
id = "id",
case = "case",
time = "time",
covariates = character(0),
slope = c("off", "on"),
innovation = c("iid", "ar1")
)
Arguments
data |
A long-format data frame, one row per subject-visit. |
markers |
Character vector of biomarker column names to standardize. |
reference_ids |
Optional vector of subject ids whose healthy (control)
visits define the reference for estimating the layer. Defaults to all
subjects in |
id, case, time |
Column names for the subject id, the case indicator (1 = case, 0 = control), and the visit time. |
covariates |
Character vector of covariate columns to adjust for. |
slope |
Random slope: |
innovation |
Residual model: |
Details
This is the layer that underlies ipeb. It is exposed so that
history-adjusted baselines (for example, a fixed-panel PEB score, a
single-marker PEB score, or a principal component of the innovations) can be
built directly from the same layer.
Value
A numeric matrix with one row per row of data and one column
per marker (named by marker), containing the standardized innovations.
See Also
Examples
data(ipeb_example)
train <- subset(ipeb_example, split == "train")
R <- ipeb_innovations(train, markers = c("m1", "m2", "m3"))
head(R)
Fit and evaluate iPEB in one call
Description
Convenience wrapper that fits ipeb on train and
evaluates the fitted model on test.
Usage
ipeb_run(
train,
test,
markers,
id = "id",
case = "case",
time = "time",
time_to_dx = "time_to_dx",
covariates = character(0),
objective = c("sensitivity", "leadtime", "combined"),
alpha = 0.95,
window = Inf,
slope = c("auto", "on", "off"),
innovation = c("auto", "ar1", "iid"),
select = c("none", "backward"),
n_markers = NULL,
validation_frac = 0.25,
specificities = NULL,
eval_window = NULL,
seed = NULL
)
Arguments
train |
Training data frame. |
test |
Test data frame (same schema as |
markers |
Character vector of biomarker column names. |
id, case, time, time_to_dx |
Column names for the subject identifier, the case indicator (1 = case, 0 = control), the visit time, and each visit's time before diagnosis (in days; used to measure lead time). |
covariates |
Character vector of covariate column names to adjust for (default none). |
objective |
Clinical objective: |
alpha |
Operating specificity at which the combiner is optimized
(default |
window |
Optional detection window in months restricting the objective
to a fixed pre-diagnostic horizon. The default, |
slope |
Random-slope layer: |
innovation |
Residual model: |
select |
Feature selection by objective-driven backward elimination:
|
n_markers |
Optional target panel size when |
validation_frac |
Fraction of training subjects held out as an internal
validation slice to choose the combiner variant and drive selection
(default |
specificities |
Numeric vector of target specificities for evaluation.
Defaults to |
eval_window |
Optional evaluation detection window in months (passed to
|
seed |
Optional single number passed to |
Value
A list with two elements: fit (the fitted "ipeb"
object) and evaluation (the data frame returned by
evaluate on test).
See Also
Examples
data(ipeb_example)
train <- subset(ipeb_example, split == "train")
test <- subset(ipeb_example, split == "test")
res <- ipeb_run(train, test, markers = c("m1", "m2", "m3"),
objective = "sensitivity", innovation = "iid", slope = "off",
specificities = c(0.90, 0.95, 0.99))
res$evaluation
Plot the fitted iPEB marker weights
Description
Plot the fitted iPEB marker weights
Usage
## S3 method for class 'ipeb'
plot(x, ...)
Arguments
x |
A fitted |
... |
Passed to |
Value
The fitted object, invisibly.
Score new subjects with a fitted iPEB model
Description
Computes the iPEB composite score for each visit in newdata using the
layer parameters and combiner weights stored in a fitted model. A subject is
scored from its own trajectory against the training healthy reference; higher
scores indicate stronger evidence of disease.
Usage
## S3 method for class 'ipeb'
predict(object, newdata, ...)
Arguments
object |
A fitted |
newdata |
A data frame with the same columns used at fitting (the selected markers, covariates, id, time, and time-to-diagnosis; the case column is optional here). |
... |
Unused. |
Value
A numeric vector of iPEB scores, one per row of newdata.
See Also
Examples
data(ipeb_example)
train <- subset(ipeb_example, split == "train")
test <- subset(ipeb_example, split == "test")
fit <- ipeb(train, markers = c("m1", "m2", "m3"),
innovation = "iid", slope = "off")
scores <- predict(fit, test)
Launch the iPEB Shiny explorer
Description
Opens the companion Shiny application bundled with the package. The app lets
you load the built-in synthetic example (or upload a long-format CSV), choose
the objective, operating specificity, windowing, layer options and feature
selection, then fit ipeb and view the marker weights and the
held-out evaluation interactively.
Usage
run_app(...)
Arguments
... |
Additional arguments passed to |
Details
The app requires the shiny package (a suggested dependency); install it
with install.packages("shiny") if needed. A hosted, browser-based
version for users without R will be linked from the package README once deployed.
Value
Invisibly NULL; called for the side effect of launching the app.
See Also
Examples
if (interactive()) {
run_app()
}