| localize.external | R Documentation |
Says which part of the misfit is present when given probabilities are checked against
given 0/1 outcomes: a published risk model on new patients, or any model's predictions on a
validation set. Nothing is refitted. The misfit is split into four parts that follow the
calibration hierarchy (Van Calster et al. 2016), and each part is named or not with the
familywise error rate held at alpha:
INTERCEPTcalibration in the large: overall risk too high or too low.
SLOPEthe calibration slope: risks too extreme or too modest.
LINKbends of the map from the score \eta = \mathrm{logit}(p) to risk.
COVmisfit among patients who share a score: a missed interaction or curved covariate, which no recalibration can repair.
localize.external(
y,
p,
X,
M = 999L,
alpha = 0.05,
calibration = c("montecarlo", "multiplier"),
cov_df = 5,
naming = c("closure", "holm", "bonferroni"),
robust = FALSE,
seed = NULL,
plot = interactive()
)
y |
0/1 outcomes. |
p |
the predicted probabilities to be checked, one per outcome, in |
X |
a numeric matrix or data frame of covariates, one row per outcome, without missing
values or constant columns. At least one column; |
M |
number of reference draws; each p-value lies on a grid of |
alpha |
familywise level. |
calibration |
|
cov_df |
the degrees of freedom of the spline in |
naming |
how groups are named: |
robust |
if |
seed |
optional integer, passed to |
plot |
if |
Each group is a Cauchy combination (Liu and Xie 2020) of score tests whose bases are
confined to that group's part, weighted-orthogonal to the parts before it: 1;
\eta; \eta^2, \eta^3, Stukel's two terms and ns(eta, 4); and, for
COV, squares and cubes of the covariates, their pairwise products and
ns(x_j, 3), each made orthogonal to every function of \eta through
ns(eta, cov_df). A covariate with four or fewer distinct values enters the products
only. With a single covariate every function of it is a function of \eta, so
COV is dropped.
A group is named when every intersection of groups containing it rejects: closed testing
(Marcus et al. 1976), so the probability of naming any group whose part is absent is at most
alpha. Each intersection is tested by the mean Cauchy coordinate of its members'
p-values, referred to its rank among M reference draws.
With calibration = "montecarlo" (the default) the draws are y^* \sim
Bernoulli(p). Nothing is estimated, so under no misfit the p-values are exactly valid
at every sample size, and for a part that is absent the error control holds for local
departures in the other parts. calibration = "multiplier" uses a robust variance and
sign-flipped residuals, so that an absent part keeps its level for departures of any size in
the other parts; that guarantee is asymptotic, and in simulations at n \le 4000 this
reference was liberal. Use it for study, not yet for decisions.
naming = "holm" or "bonferroni" names the groups by Holm's or Bonferroni's
correction of their single-group p-values instead of by closure. Both are closed procedures
with Bonferroni intersections, so they keep the same familywise guarantee; every intersection
is still computed and returned.
robust = TRUE builds the bases on normal scores, qnorm(rank / (n + 1)), of the
score and of every covariate with more than four distinct values, so that a few extreme
covariate values cannot drive a verdict. The level is unaffected: the Monte Carlo reference is
exact for any fixed choice of bases.
An object of class "gof_localize": a list with named (the groups named,
in hierarchy order), highest (the highest of them, or NA), action (the
update the decision table gives for it), single (the p-value of each group tested
alone), adjusted (each group's adjusted p-value: under closure the largest p-value
of an intersection containing it, otherwise the Holm or Bonferroni adjustment of the
single-group p-values; a group is named when it is at most alpha),
intersection (the p-value of every intersection, named as in
"SLOPE+COV"), members (the chi-square p-value of each member score test),
groups (the members of each group), alpha, naming, robust,
setting,
calibration, draws (the number of reference draws, M), n,
method and data.name.
Act on the highest group named, in the order INTERCEPT < SLOPE < LINK < COV: it
points to the lightest update that repairs the model (Steyerberg et al. 2004).
INTERCEPT | update the intercept |
SLOPE | logistic recalibration a + b\eta |
LINK | flexible recalibration f(\eta) or another link |
COV | revise the model, even if other groups are named too |
When nothing is named, no misfit was detected; that verdict is limited by the sample size. When the miscalibration is gross, as after transport to another population, a large error on the logit scale also bends the probability curve, so the named rung can be too high. Then split the validation data at random, reach the verdict and update on one half, and test the updated (frozen) model on the other half with this function.
Ebrahim, E. K., El-Kotory, A. and Hussein, O. A. E.-A. (2026). One goodness-of-fit test is not enough: error-controlled localization of misfit in logistic risk models. Preprint. Reproduction materials: \Sexpr[results=rd]{tools:::Rd_expr_doi("10.5281/zenodo.23192535")}
Marcus, R., Peritz, E. and Gabriel, K. R. (1976). On closed testing procedures with special reference to ordered analysis of variance. Biometrika, 63(3), 655–660. \Sexpr[results=rd]{tools:::Rd_expr_doi("10.1093/biomet/63.3.655")}
Liu, Y. and Xie, J. (2020). Cauchy combination test: a powerful test with analytic p-value calculation under arbitrary dependency structures. Journal of the American Statistical Association, 115(529), 393–402. \Sexpr[results=rd]{tools:::Rd_expr_doi("10.1080/01621459.2018.1554485")}
Van Calster, B., Nieboer, D., Vergouwe, Y., De Cock, B., Pencina, M. J. and Steyerberg, E. W. (2016). A calibration hierarchy for risk models was defined: from utopia to empirical data. Journal of Clinical Epidemiology, 74, 167–176. \Sexpr[results=rd]{tools:::Rd_expr_doi("10.1016/j.jclinepi.2015.12.005")}
Steyerberg, E. W., Borsboom, G. J. J. M., van Houwelingen, H. C., Eijkemans, M. J. C. and Habbema, J. D. F. (2004). Validation and updating of predictive logistic regression models: a study on sample size and shrinkage. Statistics in Medicine, 23(16), 2567–2586. \Sexpr[results=rd]{tools:::Rd_expr_doi("10.1002/sim.1844")}
localize.gof for a fitted model checked on its own data;
deepgof1.external and run.all.external for one overall test.
set.seed(1)
n <- 500
X <- data.frame(x1 = rnorm(n), x2 = rnorm(n))
p <- plogis(-0.5 + 0.8 * X$x1 + 0.6 * X$x2) # the published model
y <- rbinom(n, 1, plogis(qlogis(p) + 0.8 * X$x1 * X$x2)) # new patients: a missed interaction
localize.external(y, p, X, M = 199, seed = 1) # M = 199 to keep the example fast
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.