edge.gof: EDGE: Directed Goodness-of-Fit Test for Binary Logistic...

View source: R/edge_gof.R

edge.gofR Documentation

EDGE: Directed Goodness-of-Fit Test for Binary Logistic Regression

Description

edge.gof() is the primary interface to the EDGE test (Efficient Directed Grouped Examination): a grouped, directed goodness-of-fit test for binary logistic regression under sparse data. EDGE projects the grouped standardized residuals onto a small pre-specified basis of calibration shapes (cubic "poly3" by default) and refers the resulting quadratic form to its closed-form weighted chi-squared null distribution – no refit, no resampling, no tuning.

edge.gof() computes exactly the same statistic as the legacy name def.gof (retained for backward compatibility); the returned Test label is "EDGE".

Usage

edge.gof(
  object,
  predicted_probs = NULL,
  X = NULL,
  G = c("auto", 10),
  basis = "poly3",
  method = "satterthwaite",
  weights = "unit",
  external = FALSE,
  y = NULL
)

Arguments

object

A fitted binary logistic glm, or a binary (0/1) response vector y (then supply predicted_probs).

predicted_probs

Numeric predicted probabilities; required when object is a y vector, ignored when it is a glm.

X

Optional design matrix, used only with the y/predicted_probs form: it enables the exact estimation-adjusted (\Omega) calibration (logit working weights assumed). Without it the conservative \chi^2_k reference is used and a warning is issued. Ignored when object is a glm, and ignored (with a warning) when external = TRUE.

G

Number of groups: "auto", a number, or a vector of them; the default c("auto", 10) reports both partitions.

basis

One of "poly3" (default), "poly2", "stukel", "sym", or "ensemble". "sym" is one column, \eta|\eta| at the logit \eta of each group's mean fitted risk: Stukel's (1988) symmetric direction, aimed at tails that are too heavy or too light on both sides, for example a probit or cauchit truth fitted by a logit.

method

One of "satterthwaite" (default) or "imhof". Ignored when weights = "score".

weights

"unit" (default) is the statistic as published, S = r'P_Z r referred to a weighted chi-squared law. "score" multiplies each column by the square root of its group's variance, which for a logit fit makes the statistic the score test for adding the grouped shape to the model (a score-type test for other links). It is referred to chi-squared on the rank of its information matrix, which is the number of columns unless one is redundant (see Details).

external

Logical, default FALSE. TRUE treats the predicted probabilities as frozen (external validation of a fixed model): \Omega = I, a constant column joins the basis, and the statistic is referred to \chi^2 on the number of basis columns (see Details of def.gof). Supply y and predicted_probs, or a glm whose fitted probabilities are then taken as frozen. Requires weights = "unit" and a basis other than "ensemble"; method is not used.

y

Optional alias for object when frozen predictions are tested: edge.gof(y = y, predicted_probs = p, external = TRUE).

Details

Two partitions, side by side. By default the test is reported at two partitions, as the EDGE paper recommends. The default partition, G = "auto" (\max(10, \lceil n/25 \rceil) groups), refines with the sample and has more power, above all against misfit at the extremes of risk. Ten groups, G = 10, keep many records in the extreme groups and so tolerate more corrupted records, at some cost in power. Choose which one decides in the analysis plan, from what is known about how the data were collected, not after seeing the results. The first row is marked Role = "verdict" and the second Role = "check": with the default G the default partition decides and ten groups are the robustness check; to let ten groups decide, give G = c(10, "auto"). If only the default partition rejects, the signal sits in the extreme groups: check those records. Give a single G to get one row.

The picture. plot() on the result draws the grouped residuals of one row with the shape the test looked for and the bands that say which groups are out of line; see plot.edge_gof.

Value

A data.frame of class c("edge_gof", "data.frame") with one row per partition and columns Test ("EDGE"), Partition, Role ("verdict" for the first row, "check" for the second), Basis, Test_Statistic, df, Method and p_value, as documented in def.gof. It is a data frame in every respect; the class only adds a plot method. The grouped pieces behind each row are kept in attr(, "details"), a list with one element per row holding r (the grouped residuals (O_g - E_g)/\sqrt{V_g}), Pz_r (their projection on the basis, whose sum of squares is the unit-form statistic), O, E, V, size, pbar (the mean predicted risk of each group), G, omega_diag (the null variance of each residual: below one in-sample, one for frozen predictions), external, adjusted, role, partition and statistic. A row without a p-value, or with basis = "ensemble", has NULL there. Rows selected or reordered with x[i, ] keep the attribute whole, and plot() finds the pieces of a row by its partition, role and statistic. subset() and merge() drop the attribute, and rows bound from another result have no pieces of their own; plot() then stops with a message.

Author(s)

Ebrahim Khaled Ebrahim ebrahimkhaled@alexu.edu.eg

References

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")}

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")}

See Also

plot.edge_gof, def.gof (legacy name), edge.belt, ef.gof, def.ensemble.gof, run.all.gof.

Examples

set.seed(1)
x <- runif(500, -3, 3)
y <- rbinom(500, 1, plogis(0.6 * x))
fit <- glm(y ~ x, family = binomial())
edge.gof(fit)                      # cubic basis, at the default partition and at ten groups
edge.gof(fit, G = 10)              # one partition only
edge.gof(fit, basis = "stukel")    # Stukel-shape basis
edge.gof(fit, basis = "sym")       # Stukel's symmetric direction, one column
edge.gof(fit, basis = "sym", weights = "score")   # its score form
edge.gof(fit, G = "auto")          # the default partition alone: max(10, ceiling(n / 25)) = 20 here
plot(edge.gof(fit))                # the verdict row, on the residual scale


ebrahim.gof documentation built on Oct. 11, 2026, 5:07 p.m.