| run.all.gof | R Documentation |
Runs several goodness-of-fit tests for a binary logistic regression in one
call and returns one tidy data.frame, one row per test. Pass a fitted
glm to run the whole battery; pass (y, predicted_probs) to run
the tests that need only predictions. Each test is wrapped so that a failure of
one test never aborts the whole run.
run.all.gof(
object,
predicted_probs = NULL,
X = NULL,
tests = "all",
G = 10,
include_slow = TRUE,
parallel = FALSE,
ncores = NULL,
calibration_plot = FALSE,
install = c("ask", "no", "yes"),
control = list()
)
object |
A fitted binary logistic |
predicted_probs |
Numeric predicted probabilities; required when
|
X |
Optional design matrix; lets the directed (DEF) and covariate-space tests
run from the |
tests |
Either |
G |
Integer number of groups passed to the grouping tests (default 10), or
|
include_slow |
Logical; when |
parallel |
Logical; when |
ncores |
Integer; the number of worker processes used when
|
calibration_plot |
Logical; when |
install |
One of |
control |
Optional named list of per-test options. Recognized entries:
|
How to read the battery. Every test here answers the same question – does the fitted model describe the data it was fitted to – but they differ in the departure each is built to notice. That is why the panel is more informative than any single p-value: agreement across families is evidence of fit, and disagreement tells you what kind of misfit is present. A test that rejects points at the departure its own construction is sensitive to.
The one thing the panel cannot do is rescue an invalid reference distribution. Under sparse data – almost every covariate pattern unique – the classical chi-square references fail, which is the situation this package was written for.
Every row the battery returns carries a Family label, and the sections below are
those labels: find the label in the output, then the section of the same name here.
Global and Standardized statistics (Family "Global", "Standardized"). These compare observed and
fitted responses over the whole sample without grouping.
Pearson – the sum of squared Pearson residuals. Its
chi-square reference assumes many observations per covariate pattern. On
sparse data that assumption fails and the test is unreliable in both
directions; it is reported for completeness and comparison, not for use.
It is printed without a significance flag and is not counted among the
rejections of the header or of summary(); the Pearson (grouped)
row, shown when covariate patterns repeat, is the one to read.
Deviance – the likelihood-ratio statistic against the
saturated model. On ungrouped binary data its expectation depends on the
fitted risks alone and not on whether they agree with the responses, so it
sits above n - p when the fitted risks are near one half and far below
it when they are extreme; the direction of the error is set by the risk
profile rather than by the fit. On a correctly specified model with
mid-range risks it therefore rejects almost always. It is reported for
completeness and comparison, not for use, and like Pearson it is not
counted among the rejections.
Osius-Rojek – rescues the Pearson statistic by standardizing
it with its asymptotic mean and variance computed under increasing sample
size rather than increasing cell counts, giving a normal reference that
stays valid when patterns are unique; the deviate is referred two-sided.
Fast, parameter-free, and a
sensible default. It can be anti-conservative at small samples and
conservative under a strongly skewed covariate.
McCullagh – standardizes the Pearson statistic by its
exact conditional moments rather than asymptotic ones (computed by
the Kuss 2002 algorithm). Typically the most powerful of the global
statistics. The deviate is referred to the upper tail of the normal, as
in the GOFLOGIT macro, so a Pearson statistic below its conditional mean
is not counted as misfit. The moments are computed from the p x p
information matrix, so the cost is linear in the sample size.
Copas-RSS – the unweighted sum of squares of the raw
residuals, standardized by its own moments and referred two-sided to the
normal (df is NA, as for the other normal deviates).
Weighting each residual equally rather than by its variance makes it
comparatively sensitive to misfit in the middle of the risk range.
Information-Matrix – the White/Orme test. It compares two
estimators of the information matrix that agree only if the model is
correctly specified, so it is an omnibus check on the whole
specification rather than on calibration alone.
Partition tests (Family "Partition"). These sort observations by fitted risk, group them,
and compare observed with expected counts group by group.
HL – the Hosmer-Lemeshow test, the field's default: G groups
cut at percentiles of fitted risk (the "deciles of risk" when
G = 10), referred to chi-square on G - 2 degrees of freedom.
Note that this reference was established by simulation, not derivation.
Familiar and cheap, but modest in power, and its result depends on the
grouping.
HL-equalwidth – the same statistic with groups cut at fixed
probability intervals instead of percentiles. When fitted risks are
concentrated in a narrow range, intervals can come out empty and the test
may not be computable at all, which is why percentile grouping is usually
preferred.
Pigeon-Heyse – a variance-corrected Hosmer-Lemeshow statistic
that accounts for the variability of fitted probabilities within each
group. The correction is conservative in sparse designs, so a
non-rejection carries less weight than the nominal level suggests.
F-test – deviance residuals compared across the risk groups by
a one-way analysis of variance. It is markedly liberal under sparsity and
grows more so with sample size; it is included for comparison, printed
without a significance flag and not counted among the rejections.
EF, EF-normal – the Ebrahim-Farrington test,
Farrington's correction on the Hosmer-Lemeshow risk groups. EF uses
the chi-square reference on G - 2 degrees of freedom at the battery's
G; EF-normal uses the plug-in normal reference, which is the
reference for many groups, at G = "auto" (groups of about 25 records)
unless control = list("EF-normal" = list(G = ...)) sets another
number; it needs the model or X. See ef.gof. Tied fitted
risks are put in random order.
Lai-Liu-HL – Lai and Liu's procedure for using the
Hosmer-Lemeshow test in large samples, where any test eventually rejects.
It standardizes power to a reference sample size n0 and so returns
no p-value: the statistic is the standardized power and the accept/reject
decision appears in the Note column. Tune with
control = list("Lai-Liu-HL" = list(n0 = ..., k = ...)).
HL-largeN – Nattino, Pennell and Lemeshow's (2020) large-sample
Hosmer-Lemeshow test. Instead of perfect fit it tests whether the misfit,
measured by \epsilon = \sqrt{\lambda/n}, exceeds a tolerance \epsilon_0:
the ordinary statistic is referred to a noncentral \chi^2_{G-2} with
noncentrality \epsilon_0^2 n. By their convention \epsilon_0 is the
misfit that would be just significant at n0 = 1e6; change it with
control = list("HL-largeN" = list(n0 = ...)). The Note gives
\epsilon_0 and the estimate \hat\epsilon. Meant for samples in the tens of
thousands and above; in small samples it is conservative.
Directed tests (Family "Directed"). Rather than asking whether anything is wrong, these
ask whether a particular shape of departure is present, which buys
power when the guess is right.
EDGE, EDGE.G10 – the EDGE test (the cubic basis of
edge.gof) at its default partition, G = "auto", and at
ten groups, whatever the battery's G. When the default partition has
ten groups (n \le 250) the two are one test and only EDGE is
shown. The statistic S is a weighted sum of chi-squares: the note
says when its p-value comes from S/c \sim \chi^2_{df}
(Satterthwaite), so Statistic and df alone do not give it.
DEF.poly2, DEF.poly3, DEF.stukel, DEF.sym –
the directed forms, each aiming the test at a smooth departure in the shape
of the calibration curve: a quadratic or cubic drift in the linear
predictor, Stukel's asymmetry-and-tail family, or Stukel's symmetric
direction, tails too heavy or too light on both sides. Powerful when the
misfit resembles the chosen basis, weaker when it does not. Each row takes
weights and G through control, for example
control = list(DEF.sym = list(weights = "score", G = "auto")); see
def.gof. In the full battery DEF.poly3 is left out
when it would repeat EDGE.G10 (the battery's G is 10 and
control does not move either row); name it in tests to get it. On a sample with no event, or no non-event, there is
no fitted model; these rows and the Stukel row are then NA, and
Note says why.
Stukel – a score test against Stukel's generalized logistic
link, which nests the logit and lets the two tails bend independently. It
is aimed squarely at link misspecification. The two tail directions are
tested jointly on 2 degrees of freedom (1 when every fitted risk lies on
one side of one half, which Note then says). Testing them jointly
gives up a little power against one-sided (cloglog-type) departures. Up to
2.7.0 this row summed two marginal statistics and was liberal; see NEWS.
control = list(Stukel = list(form = "lr")) gives the likelihood-ratio
test for the same two directions, and form = "marginal" the old sum,
for reproducing earlier results only. The likelihood-ratio refit can fail
to converge under separation; the row is then NA, with a note. The
joint form leaves out a direction whose information after the fit is below
10^{-10} times its information before the fit, as when the fitted logit
is constant; when no direction is left the row is NA, with a note.
Covariate-space tests (Family "Covariate-space"). These partition the covariates themselves
rather than the fitted risk, so they can see structure that risk-ordering
averages away – an omitted interaction, for instance, need not disturb the
marginal calibration at all.
Tsiatis – a score test that adds indicator variables for
regions of the covariate space and asks whether they improve the fit.
Xie – clusters the covariate space and compares observed with
expected counts per cluster, using the corrected degrees of freedom
G - k/2 - 1 with k the number of predictors.
Pulkstenis-Robinson – crosses a categorical covariate with
risk groups, so it needs at least one categorical predictor. The package
auto-detects one (any factor, character or logical, or a numeric with few
distinct values, controlled by
getOption("ebrahim.gof.pr.maxlev", 6)) and returns NA with a
note when there is none.
Smoothing and GAM tests (Family "Smoothing", "GAM"). These replace grouping with a smoother, so nothing
is lost to an arbitrary choice of bin edges.
le-Cessie – the le Cessie-van Houwelingen score test, which
smooths the residuals over the covariate space with a kernel and asks
whether the smoothed surface is further from zero than chance allows.
Sensitive to local structure that omnibus statistics average away, and one
of the most expensive tests here, with cost growing sharply in the sample
size.
HL-GAM, PR-GAM, Xie-GAM – variants that fit a
deliberately overfitted generalized additive model and use it to define
the grouping, letting the data rather than the analyst choose where the
boundaries fall. These need mgcv.
Resampling tests (Family "Bootstrap"). When a statistic has no usable closed-form
reference, these build one by simulation.
Stute-Zhu – a cumulative-residual test: residuals are
accumulated along the fitted linear predictor and the largest excursion of
that path is compared with a parametric bootstrap. It needs no binning and
no bandwidth, and in practice it is the best-behaved test in the battery
on size. The p-value is (1 + k)/(1 + B), with k the number of
bootstrap statistics at least as large as the observed one, so it is never
0. Set the number of resamples with
control = list("Stute-Zhu" = list(B = ...)).
BAGofT – the binary adaptive test, which splits the data, uses
one part to learn a partition that separates fitted from observed, and
tests on the other. Its behaviour depends strongly on how many splits and
resamples it is given; set them with
control = list(BAGofT = list(nsim = ...)) and be aware that the
published default is far more expensive than a single split. By default
the row is computed by bagoft.fast, which returns the same
p-value as the BAGofT package for the same seed and needs only
randomForest (and dcov above five covariates);
control = list(BAGofT = list(engine = "package")) calls
BAGofT itself. When no simulated statistic is as extreme as the
observed one, BAGofT returns 0; the row then reports
1/(nsim + 1), the smallest Monte Carlo p-value, and says so.
Projection – the projection test of Escanciano (2006) as
defined for logistic regression by Liu et al. (2024): the cumulative
residual process is taken along every direction of the covariate space,
not only along the fitted linear predictor as in Stute-Zhu, so it
also sees departures such as an omitted interaction. Model-based
bootstrap with B = 1000 refits by default; see
projection.gof. Its weight matrix costs O(n^3) time and
O(n^2) memory, so the row is skipped above n = 3000. Set
control = list(Projection = list(B = ..., max_n = ...)).
Calibration tests (Family "Calibration"). These come from clinical prediction, and ask
directly whether predicted risks match observed frequencies.
GiViTI, GiViTI-external – the GiViTI polynomial
calibration test, which fits a polynomial of the fitted risk and tests
whether it departs from the identity, under the internal and external
development assumptions respectively. The two are not
interchangeable: on data used to fit the model the internal form is the
appropriate one, so the full battery runs GiViTI only, and
GiViTI-external runs when it is named in tests. For frozen
predictions on new data use run.all.external. It also produces the calibration belt, which shows
where on the risk scale a model drifts; see
calibration_plot. Wraps givitiR in an isolated callr
subprocess, so a failure inside its compiled dependencies returns
NA instead of ending your session. Select with
control = list(GiViTI = list(devel = "internal")).
eHL – an e-value form of the Hosmer-Lemeshow test, reported as
p = \min(1, 1/e). E-values are safe under optional stopping, which
conventional p-values are not, but the conversion shown here is
conservative.
Cubic-LR – the cubic calibration likelihood-ratio test: the
square and cube of the logit of the fitted risk are added to a logistic
regression of the outcome on it, and the drop in deviance is referred to
chi-squared on 2 degrees of freedom. It is the goodness-of-link idea of
Pregibon (1980) with the cubic logistic model of Morgan (1985), and a
fixed-degree relative of the GiViTI polynomial; fast, and needs only the
predictions. See cubic.calib.gof, which documents its origin.
Combinations (Family "Ensemble"). Rather than choosing one test, these pool several.
Ensemble.Vote(3DEF) and Ensemble.Univ(3DEF+EF) – Cauchy
combinations of the directed tests, and of those plus the omnibus EF. The
Cauchy combination is valid without knowing how the members correlate,
which is what makes pooling dependent tests possible at all. The point is
to avoid having to guess the departure in advance, at the cost of being
slightly less powerful than the single best member would have been. Both
rows always combine the unit form of DEF.poly2, DEF.poly3 and
DEF.stukel at the battery's G. When control gives those
rows other weights or another G, the ensemble rows do not
follow, and their Note says "unit form".
See also legoft, a pretrained combination whose weights
are fixed offline and ship frozen, so two analysts running it on the same
data obtain the same p-value.
Implementation notes. Tsiatis and Xie cluster the
covariate space with k-means using a fixed internal seed, so results are
reproducible and your own random stream is left untouched. The equal-frequency
groups of HL, F-test, EF and the DEF rows split tied
fitted risks by row order, so with many ties (grouped data, or a model on
discrete covariates) their results can depend on the order of the rows;
randomising the row order is advised. Every bundled test
reproduces the implementation used in the original simulation study:
Osius-Rojek follows LogisticDx's gof.glm,
Copas-RSS follows the rms gof residual, and
HL follows ResourceSelection::hoslem.test. The exception is
Stukel: its default joint score statistic agrees with
anova(..., test = "Rao") for the augmented model, up to glm's
convergence tolerance, and only
form = "marginal" reproduces LogisticDx (through
statmod::glm.scoretest when statmod is installed).
Procedures the battery does not select. Some of the package's own methods are
not part of the panel and are called directly on the fitted model, their p-values read
beside it: deepgof1 and legoft are of that kind. Naming
them in tests does not reach them.
For goodness of fit after penalized fitting, where none of the above references
are valid because the coefficients are shrunk, use calm.gof or
shrink.gof. These take the design, the response and the penalty rather
than a fitted glm, so they are called separately from the battery.
A data.frame (of class gof_battery) with columns
Test, Family, Statistic, df, p_value,
and Note, one row per test. A dedicated print method shows the
rows grouped by family with formatted p-values and significance flags; the
underlying columns remain available for programmatic use.
Grouped vs sparse forms. Pearson, Deviance and
McCullagh are reported in two forms: the default (sparse / one-trial)
form and a "(grouped)" form computed on the distinct covariate
patterns (each a Binomial(m_g, P_g)). The two are identical when every
covariate pattern is unique (fully sparse data, as in the simulation) and
differ only when patterns repeat (m_g > 1). To avoid clutter, the
"(grouped)" row is shown only when it actually differs from the
sparse form (i.e., when some pattern repeats); on fully sparse data it is a
duplicate and is omitted. Osius-Rojek is always computed on covariate
patterns, matching its classical (LogisticDx) definition.
Farrington vs EF. The original Farrington (1996) test is a
grouped (covariate-pattern) test. The Ebrahim-Farrington (EF) test is
its sparse-data counterpart: it does not group by covariate pattern
but forms G data-dependent bins of the predicted risk, so it applies
directly to fully sparse data. Use EF for sparse binary data; the
grouped Farrington form is appropriate only when covariate patterns repeat.
Reproducibility of the parallel path. With parallel = TRUE
the cluster's random-number streams are initialized with
clusterSetRNGStream, seeded deterministically from
the session's current RNG state. Two runs from the same
set.seed state (and the same ncores) therefore give
identical bootstrap p-values. Note that the parallel L'Ecuyer-CMRG streams
necessarily differ from the serial RNG stream, so parallel = TRUE
results differ (within Monte-Carlo error) from parallel = FALSE
results at the same seed; this is standard and both are valid. Results also
depend on ncores, because the replicates are split across workers.
Ebrahim Khaled Ebrahim ebrahimkhaled@alexu.edu.eg
The aggregated tests are due to their original authors; they are provided here for comparison and credited as follows.
Farrington CP (1996). "On Assessing Goodness of Fit of Generalized Linear Models to Sparse Data." Journal of the Royal Statistical Society B, 58(2), 349–360. \Sexpr[results=rd]{tools:::Rd_expr_doi("10.1111/j.2517-6161.1996.tb02086.x")}
Hosmer DW, Lemeshow S (1980). "Goodness of Fit Tests for the Multiple Logistic Regression Model." Communications in Statistics – Theory and Methods, 9(10), 1043–1069. \Sexpr[results=rd]{tools:::Rd_expr_doi("10.1080/03610928008827941")}
McCullagh P (1985). "On the Asymptotic Distribution of Pearson's Statistic in Linear Exponential Family Models." International Statistical Review, 53(1), 61–67. \Sexpr[results=rd]{tools:::Rd_expr_doi("10.2307/1402880")}
Osius G, Rojek D (1992). "Normal Goodness-of-Fit Tests for Multinomial Models with Large Degrees of Freedom." Journal of the American Statistical Association, 87(420), 1145–1152. \Sexpr[results=rd]{tools:::Rd_expr_doi("10.1080/01621459.1992.10476271")}
le Cessie S, van Houwelingen JC (1991). "A Goodness-of-Fit Test for Binary Regression Models, Based on Smoothing Methods." Biometrics, 47(4), 1267–1282. \Sexpr[results=rd]{tools:::Rd_expr_doi("10.2307/2532385")}
Stukel TA (1988). "Generalized Logistic Models." Journal of the American Statistical Association, 83(402), 426–431. \Sexpr[results=rd]{tools:::Rd_expr_doi("10.1080/01621459.1988.10478613")}
Stute W, Zhu LX (2002). "Model Checks for Generalized Linear Models." Scandinavian Journal of Statistics, 29(3), 535–545. \Sexpr[results=rd]{tools:::Rd_expr_doi("10.1111/1467-9469.00304")}
Escanciano JC (2006). "A Consistent Diagnostic Test for Regression Models Using Projections." Econometric Theory, 22(6), 1030–1051. \Sexpr[results=rd]{tools:::Rd_expr_doi("10.1017/S0266466606060506")}
Liu H, Li X, Chen F, Haerdle W, Liang H (2024). "A Comprehensive Comparison of Goodness-of-Fit Tests for Logistic Regression Models." Statistics and Computing, 34, 175. \Sexpr[results=rd]{tools:::Rd_expr_doi("10.1007/s11222-024-10487-5")}
Tsiatis AA (1980). "A Note on a Goodness-of-Fit Test for the Logistic Regression Model." Biometrika, 67(1), 250–251. \Sexpr[results=rd]{tools:::Rd_expr_doi("10.1093/biomet/67.1.250")}
Xie XJ, Pendergast J, Clarke W (2008). "Increasing the Power: A Practical Approach to Goodness-of-Fit Test for Logistic Regression Models with Continuous Predictors." Computational Statistics & Data Analysis, 52(5), 2703–2713. \Sexpr[results=rd]{tools:::Rd_expr_doi("10.1016/j.csda.2007.09.027")}
Pulkstenis E, Robinson TJ (2002). "Two Goodness-of-Fit Tests for Logistic Regression Models with Continuous Covariates." Statistics in Medicine, 21(1), 79–93. \Sexpr[results=rd]{tools:::Rd_expr_doi("10.1002/sim.943")}
Nattino G, Finazzi S, Bertolini G (2014). "A New Calibration Test and a Reappraisal of the Calibration Belt for the Assessment of Prediction Models Based on Dichotomous Outcomes." Statistics in Medicine, 33(14), 2390–2407. \Sexpr[results=rd]{tools:::Rd_expr_doi("10.1002/sim.6100")}
Pigeon JG, Heyse JF (1999). "An Improved Goodness of Fit Statistic for Probability Prediction Models." Biometrical Journal, 41(1), 71–82. \Sexpr[results=rd]{tools:::Rd_expr_doi("10.1002/(SICI)1521-4036(199903)41:1<71::AID-BIMJ71>3.0.CO;2-O")}
Copas JB (1989). "Unweighted Sum of Squares Test for Proportions." Journal of the Royal Statistical Society C, 38(1), 71–80. \Sexpr[results=rd]{tools:::Rd_expr_doi("10.2307/2347682")}
White H (1982). "Maximum Likelihood Estimation of Misspecified Models." Econometrica, 50(1), 1–25. \Sexpr[results=rd]{tools:::Rd_expr_doi("10.2307/1912526")}
Orme C (1988). "The Calculation of the Information Matrix Test for Binary Data Models." The Manchester School, 56(4), 370–376. \Sexpr[results=rd]{tools:::Rd_expr_doi("10.1111/j.1467-9957.1988.tb01339.x")}
Kuss O (2002). "Global Goodness-of-Fit Tests in Logistic Regression with Sparse Data." Statistics in Medicine, 21(24), 3789–3801. \Sexpr[results=rd]{tools:::Rd_expr_doi("10.1002/sim.1421")}
Lai X, Liu L (2018). "A Simple Test Procedure in Standardizing the Power of Hosmer-Lemeshow Test in Large Data Sets." Journal of Statistical Computation and Simulation, 88(13), 2463–2472. \Sexpr[results=rd]{tools:::Rd_expr_doi("10.1080/00949655.2018.1467912")}
Nattino G, Finazzi S, Bertolini G (2014). "A New Calibration Test and a Reappraisal of the Calibration Belt for the Assessment of Prediction Models Based on Dichotomous Outcomes." Statistics in Medicine, 33(14), 2390–2407. \Sexpr[results=rd]{tools:::Rd_expr_doi("10.1002/sim.6100")}
Zhang J, Ding J, Yang Y (2023). "Is a Classification Procedure Good Enough? A Goodness-of-Fit Assessment Tool for Classification Learning." Journal of the American Statistical Association, 118(542), 1115–1125. \Sexpr[results=rd]{tools:::Rd_expr_doi("10.1080/01621459.2021.1979010")}
Liu Y, 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")}
Hosmer DW, Hosmer T, le Cessie S, Lemeshow S (1997). "A Comparison of Goodness-of-Fit Tests for the Logistic Regression Model." Statistics in Medicine, 16(9), 965–980. \Sexpr[results=rd]{tools:::Rd_expr_doi("10.1002/(sici)1097-0258(19970515)16:9<965::aid-sim509>3.0.co;2-o")}
The methods introduced by this package, and the studies that evaluate them, are reported in the following. Reproduction materials for each are archived and citable.
Ebrahim EK, Khattab IG, El-Kotory A (2026). "A Modified Hosmer-Lemeshow Goodness-of-Fit Test for Asymmetric Links: Second-Order Power and Robustness." arXiv:2607.15454 [stat.ME]. \Sexpr[results=rd]{tools:::Rd_expr_doi("10.48550/arXiv.2607.15454")}
Ebrahim EK, El-Kotory A (2026). "Benchmarking Goodness-of-Fit and Calibration Algorithms for Logistic Regression Classifiers: A Large-Scale Simulation Study under Sparse Data." Journal of Intelligent Computing and Data Science, 2(2), 97-128. \Sexpr[results=rd]{tools:::Rd_expr_doi("10.21608/jicds.2026.505341.1048")} Reproduction materials: \Sexpr[results=rd]{tools:::Rd_expr_doi("10.5281/zenodo.21286171")}
Ebrahim EK (2026). "Goodness-of-Fit Tests and Calibration Machine-Learning Algorithms for Logistic Regression with Sparse Data." M.Sc. thesis, Alexandria University. arXiv:2608.11140 [stat.ME]. \Sexpr[results=rd]{tools:::Rd_expr_doi("10.48550/arXiv.2608.11140")}
Ebrahim EK, Hussein OAE-A, El-Kotory A (2026). "A Grouped Calibration Test for Logistic Regression That Tolerates a Few Corrupted Records." arXiv:2608.20511 [stat.ME]. \Sexpr[results=rd]{tools:::Rd_expr_doi("10.48550/arXiv.2608.20511")} Reproduction materials (first version): \Sexpr[results=rd]{tools:::Rd_expr_doi("10.5281/zenodo.21247541")}
Ebrahim EK (2026). "EDGES: A Selection-Free Ensemble Goodness-of-Fit Test." Reproduction materials. \Sexpr[results=rd]{tools:::Rd_expr_doi("10.5281/zenodo.21320865")}
Ebrahim EK (2026). "Detection Subspaces: A Theory of Goodness-of-Fit Tests." Reproduction materials. \Sexpr[results=rd]{tools:::Rd_expr_doi("10.5281/zenodo.21687498")}
Ebrahim EK (2026). "Shrinkage Invalidates the Hosmer-Lemeshow Test: Goodness of Fit
for Penalized Logistic Regression, with an Application to Glaucoma Diagnosis."
arXiv:2609.06413 [stat.ME]. \Sexpr[results=rd]{tools:::Rd_expr_doi("10.48550/arXiv.2609.06413")} Reproduction materials
for shrink.gof: \Sexpr[results=rd]{tools:::Rd_expr_doi("10.5281/zenodo.21900114")}
ef.gof, def.gof, def.ensemble.gof,
gof_install_suggests.
set.seed(1)
n <- 500
x <- runif(n, -3, 3)
y <- rbinom(n, 1, 1 / (1 + exp(-(0.6 * x))))
fit <- glm(y ~ x, family = binomial())
## The fast tests. Every covariate pattern here is unique, so this is the
## sparse case the package is written for.
res <- run.all.gof(fit, include_slow = FALSE)
res
## The return value is a plain data.frame, so the panel can be read
## programmatically as well as printed.
res[res$p_value < 0.05, c("Test", "Family", "p_value")] # what rejected
table(res$Family) # coverage by family
## A correctly specified model: the panel should mostly agree, and any
## isolated rejection is the false positive you expect at the 5 percent level.
mean(res$p_value < 0.05, na.rm = TRUE)
## Now a model that is genuinely wrong -- the quadratic term is omitted.
y2 <- rbinom(n, 1, 1 / (1 + exp(-(0.6 * x + 0.5 * x^2))))
bad <- glm(y2 ~ x, family = binomial())
run.all.gof(bad, include_slow = FALSE)
## Pick specific tests, for instance one per family, which is the pairing the
## package recommends over relying on any single statistic.
run.all.gof(fit, tests = c("McCullagh", "HL", "Stukel", "Tsiatis"))
## Grouping tests take the number of groups; the choice is a convention
## rather than a derived optimum, so it is worth varying.
for (g in c(5, 10, 20))
print(run.all.gof(fit, tests = "HL", G = g))
## The full battery (include_slow = TRUE by default). The slow tests need the
## suggested packages mgcv, randomForest, givitiR and callr; in an interactive
## session run.all.gof() offers to install any that are missing
## (install = "ask"). See also gof_install_suggests().
## The control= list forwards options to the individual tests; the reductions
## here keep the example quick without changing what it demonstrates.
run.all.gof(fit, install = "no",
control = list("Stute-Zhu" = list(B = 50),
BAGofT = list(nsim = 20),
Projection = list(B = 99)))
## The GiViTI calibration belt shows WHERE on the risk scale a model drifts,
## which a single p-value cannot.
res2 <- run.all.gof(fit, tests = c("McCullagh", "GiViTI"),
calibration_plot = TRUE)
plot(res2) # redraw the stored belt
## Run the bootstrap loops on a PSOCK cluster. Seeds are handled internally,
## so a parallel run reproduces a serial one.
set.seed(1)
run.all.gof(fit, tests = "Stute-Zhu", parallel = TRUE, ncores = 2,
control = list("Stute-Zhu" = list(B = 50)))
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.