Skip to contents

Superseded by rem(), the unified front-end for fitting relational event models on preprocessed case-control data. compare_models() remains fully supported.

Convenience wrapper that runs the canonical case-control / no-intercept binomial-GLM recipe on every specification in models and returns a tidy AIC comparison table. One case-control sample is drawn from event_log and shared across every specification so that the AIC values are directly comparable.

Each specification is a character vector of stat names accepted by endogenous_features(). The function computes the union of all stats once, builds case-minus-control differences, and fits one binomial GLM per specification with the appropriate subset of columns. The fitted models are equivalent to the partial-likelihood parametrisation used in case-control REM inference (Vu et al. 2017; Juozaitienė & Wit 2024).

For n_controls = 1 the helper fits a no-intercept binomial GLM on case-minus-control differences. For n_controls > 1 it falls back to survival::clogit() — a true conditional-logistic fit that correctly handles multiple controls per stratum. The survival package is in Suggests and is required only when n_controls > 1.

Usage

compare_models(
  event_log,
  models,
  n_controls = 1,
  scope = c("all", "appearance", "citation"),
  mode = c("one", "two"),
  random_effects = NULL,
  half_life = NULL,
  seed = NULL,
  keep_fits = FALSE
)

Arguments

event_log

Data frame with sender, receiver, and time columns.

models

Named list of character vectors. Each entry names one candidate specification; the vector contents are the endogenous statistics it includes. Stats must be valid names for endogenous_features().

n_controls

Number of controls per case in sample_non_events(). 1 uses a binomial GLM on differences; > 1 uses survival::clogit() on the stratified case-control table.

scope, mode

Passed through to sample_non_events(); see that help page for semantics.

random_effects

Optional character vector. May be any of NULL (no random effects), "sender", "receiver", or c("sender", "receiver"). When supplied, requires n_controls > 1. With one axis, the stratified coxph fit adds a Gamma survival::frailty() term on the requested actor. With both axes, the fit dispatches to coxme::coxme() with two normal ~ 1 | actor random effects, which avoids survival::coxph's one-sparse-term cap and the dense-penalty segfault on stratified case-control designs. The two-axis path requires the coxme package (Suggests). This is the actor-heterogeneity correction used by Juozaitienė & Wit (2024) and changes which specification AIC selects on real-world data (timing variants typically win over count baselines once actor effects are absorbed). Defaults to NULL (no random effects).

half_life

Required when any specification contains an exp-decay stat. Shared across all specs that use one.

seed

Optional integer seed for the case-control sample.

keep_fits

Logical; when TRUE, the returned table carries the fitted model objects (one per spec, named by model, NULL for specs that failed) as attr(result, "fits"), e.g. for plotting estimated effects. Defaults to FALSE.

Value

A data frame with one row per specification and columns model, n_terms, n_obs, log_lik, AIC, delta_AIC. Sorted ascending by AIC. The model with the lowest AIC has delta_AIC = 0.

References

Juozaitienė R, Wit EC (2024). It's about time: revisiting reciprocity and triadicity in relational event analysis. Journal of the Royal Statistical Society Series A 188(4), 1246-1262. doi:10.1093/jrsssa/qnae132 .

Examples

# \donttest{
data(classroom_events)
compare_models(
  classroom_events,
  models = list(
    count       = c("reciprocity_count", "transitivity_count"),
    continuous  = c("reciprocity_time_recent",
                    "transitivity_time_recent"),
    interrupted = c("reciprocity_time_recent_interrupted",
                    "transitivity_time_recent_interrupted")),
  seed = 11)
#>         model n_terms n_obs   log_lik      AIC delta_AIC
#> 1       count       2   691 -305.5233 615.0466    0.0000
#> 2  continuous       2   691 -421.1231 846.2462  231.1996
#> 3 interrupted       2   691 -439.6904 883.3809  268.3343
# }