rem(method = "gam") warns when rows with missing
covariate values are left out of the fit, and records which rows it used
(fit$rows, with fit$n counting only those).
gof_rem() keeps the same rows when given the full data; it
stopped with “non-conformable arguments” before.
sample_non_events(scope = "citation") always draws
the citing paper and the cited papers from separate pools. Under the
mode = "one" default of 1.1.0 it pooled them, so most
controls had a sender other than the citing paper.
rem(method = "nn") and nn_uncertainty()
no longer change the caller’s random-number state when given a seed
(CRAN policy); fitted results are unchanged.
Partial-dependence curves of plot() on neural fits
and of nn_uncertainty() span the 1st to 99th percentile of
each feature instead of the mean ± 2 standard deviations, which reached
below the data for skewed, non-negative statistics.
Concordance of neural fits splits a tied top score evenly between the tied candidates; it gave the whole stratum to the event.
simulate_relational_events(method = "tau_leap")
stops with a message when a single step would draw more than ten million
events, which happens when an effect grows without bound; it could
exhaust memory.
gof_rem() tests a model fitted with
rem(method = "gam") with cumulative martingale residuals
(Boschi & Wit 2025): over event time (test = "time"),
over the quantiles of a covariate
(test = "functional_form", which detects a wrong shape of
the effect), or over the quantiles weighted by the term’s basis
(test = "functional_form_score"). It works on linear and
smooth terms of the fitted model, and its null distribution is a
multiplier bootstrap that subtracts the drift from estimating the
coefficients. It has print() and plot()
methods (plot() takes main and a
legend position). The existing
gof_univariate(), gof_multivariate(),
gof_global() and gof_auxiliary() are
unchanged.
rem() fits store the name of their time
column.
New alien_mammals: the risk table of the first
records of alien mammals with the covariates of Juozaitienė et
al. (2023) (distance to the nearest invaded region, trade, temperature
difference, colonial ties, land use), and the never-at-risk pairs and
species entry years as attributes; used in the species-invasion section
of the software paper.
New event logs, all under licences that allow redistribution:
copenhagen_calls, copenhagen_sms and
copenhagen_actors (Copenhagen Networks Study, MIT);
us_leader_visits (leader-to-leader visits to and from the
United States, 1945-2019, CC0); football_results (men’s
international football matches since 1872, CC0); ucdp_dyads
(UCDP armed-conflict dyads, 1946-2025, CC BY 4.0);
alien_invasions (first records of alien species by region,
1880-2005, CC0).
New hyperevent log: congress_bills_118, one sponsor
and the cosponsors of each bill of the 118th US Congress, with
congress_members_118 (public domain).
New global covariates: oni (Oceanic Nino Index since
1950), daily_weather (NOAA daily temperature and
precipitation for the cities of the bundled email and messaging logs)
and public_holidays.
radoslaw_email is rebuilt from the authors’ CC0
release (Nurek & Michalski 2020, doi:10.7910/DVN/6Z3CGX). It keeps
the original employee ids, which match the new
radoslaw_hierarchy (who reports to whom), and its
timestamps are read as Warsaw local time. The previous copy, from
Network Repository, read them as UTC, so it ignored daylight saving
time: events sent during Polish summer time are now one hour earlier
relative to the first event, and unix_origin is one hour
earlier. The number of events and each employee’s activity are
unchanged.
The pkgdown site has a data catalogue: licences, download code and structural profiles of 78 relational-event datasets and covariates, including the many whose licences do not allow amorem to redistribute them.
Endogenous statistics on case-control data no longer
count the sampled controls as events.
endogenous_features() on the output of
sample_non_events() (a 0/1 event column with
control rows) now builds the network history from the
event == 1 rows only; the controls read it but never enter
it. Before, every row updated the history, so each statistic also
counted hypothetical dyads. This was the default path inside
compare_models(), compare_models_smooth(),
gof(), martingale_residuals() and the
vignettes. On six simulated datasets with a reciprocity effect of 0.3,
the estimate moved from 0.20 to 0.31 on average. Results of those
functions change and should be re-run. Pass
history_log = event_log to treat every row as an
event.
rem() evaluates tv() and
tvnl() terms at each row’s own time. When
data has time_ev / time_nv
instead of a single time column (the wide form of
sample_non_events(shift = "exponential")),
tv(x) contributes beta(t) x_ev - beta(t*) x_nv
and tvnl() uses both times. Before, the event time was used
for both rows. Models with a single time column give the same formula
and fit as before.
compare_models_global() now uses the paper’s
time-shifted design. It drew one shift per control row, never
shifted the event, never checked the observation window (control times
could precede the data), evaluated the controls’ dyadic statistics at
the event time, and let sampled controls enter the network history. On
simulated data with a global effect of 1 it returned estimates of -1.74,
2.63 and -2.12 over three datasets. It now draws its sample with
sample_non_events(shift = "exponential"), computes dyadic
statistics against the real history at each row’s own time, evaluates
tv / tvnl terms at each row’s own time, and
drops events with no control; the same three datasets give 0.85, 1.02
and 1.01. The shift mean is now shift_scale times the
average event time (it was times the average inter-arrival time), and a
window argument is passed through. Results of earlier
compare_models_global() fits change and should be
re-run.
widen_case_control() and the clogit /
nn backends of rem() use the
stratum column written by sample_non_events()
when stratum = NULL, instead of rebuilding strata as
cumsum(case == 1). The rebuilt strata assumed each case was
followed by its controls, which stops holding once
endogenous_features() re-sorts rows by time with ties, or
with shifted controls, and then paired cases with the wrong controls.
Data without a stratum column (eventnet output) is handled
as before.
sample_non_events() risk-set edge cases
(#102).
exclude_pairs and, under risk = "remove",
same-time events are now part of the check for whether any valid control
exists, so a stratum whose every alternative is excluded gets no
controls instead of stopping with “Unable to sample a valid non-event
after max_attempts attempts”.scope = "appearance" no longer falls back to all actors
when no actor has appeared yet: the first event gets no controls, and
controls are only ever drawn from actors seen in prior events, as
documented. Results change for the first stratum(s) of
scope = "appearance" fits.sender / receiver columns are
coerced to character, so the output columns are character whatever the
input type.mode states which risk set each
mode gives: "two" never draws a receiver-only actor as a
control sender (or vice versa), so networks with one node set should use
mode = "one".sample_non_events() now defaults to
mode = "one", the risk set of networks whose senders and
receivers are one node set, and the default of
compare_models(), compare_models_smooth(),
compare_models_global(), gof() and
martingale_residuals(). Calls that relied on the old
default mode = "two" (bipartite networks) must now pass
it.New dataset enso_nino34: the
tree-ring reconstruction of the November–January Niño3.4 sea-surface
temperature anomaly by Li et al. (2013), one value per year from 1301 to
2005 (NOAA NCEI study 14632), as a global covariate on a yearly clock.
The raw NOAA file ships in inst/extdata/enso_nino34/, and
data-raw/enso_nino34.R rebuilds the object.
vignette("species-invasion") now simulates five
centuries of invasions (1500–2005) driven by distance, a neighbour
pressure and ENSO. It shows that ordinary case-control sampling gives an
ENSO difference of zero in every stratum, and recovers all three effects
with time-shifted sampling and rem(), reporting standard
errors.
Time-shifted case-control sampling for global covariates
(#101). sample_non_events(shift = "exponential")
implements Section 4 of Lembo, Juozaitienė, Vinciotti & Wit (2025,
JRSS-C): one exponential shift per dyad, each control drawn uniformly
from the dyads whose back-shifted time lies in the observation
window and stored at that time, so covariates that depend
only on time no longer cancel within strata. shift_scale
sets the mean shift as a multiple of the average event time, as in the
paper. Risk-set rules (exclude_pairs,
risk = "remove", scope = "appearance") are
evaluated at the control’s own time; events with no other dyad in their
shifted risk set get no control and are listed in
attr(, "shift")$uninformative. The attribute also holds the
shift mean, the window and the per-dyad shifts.
endogenous_features(history_log = ) and
prior_log now work for every statistic, including
reciprocity_exp_decay, reciprocity_time_recent
and reciprocity_time_first, which the compiled engine does
not cover.
Per-term basis settings in rem() formulas
(#91). Smooth terms take the basis arguments of
mgcv::s() / mgcv::te() after the covariate, so
terms in one model can use different basis dimensions and types:
tv(x, k = 20, bs = "cr") + nl(y, k = 5, bs = "ps").
tvnl() takes one value per margin
(tvnl(x, k = c(5, 8))). A new global bs
argument joins the global k as the default for terms that
set neither; existing formulas give the same model as before.
sample_non_events(exclude_concurrent = ) controls
whether dyads with an event at the focal event’s own time can be
controls. The default keeps the existing behaviour: excluded under
risk = "remove", at risk under
risk = "standard" (the Breslow convention).
compare_models() did not stratify on the
matched sets under survival before 3.7-3. The
Cox formula was built with a namespace-qualified
survival::strata(stratum), and
terms(specials = ) does not match a qualified call, so the
matched-set identifier was silently fitted as an ordinary factor
covariate in an unstratified model. Coefficients and the
delta_AIC column were unaffected; the absolute
log_lik was shifted by
-n_events * log(n_strata) and the degrees of freedom
inflated by n_strata - 1, so reported AIC
values were wrong. The same applied to the frailty() terms
on the random-effects path, which is why the coxme two-axis
fit did not complete. All four call sites now use bare specials, which
every survival version matches, and regression tests
assert that AIC == -2 * log_lik + 2 * df and that no
stratum dummies enter as covariates. Anyone who published absolute
log-likelihood or AIC values from
compare_models(n_controls > 1) should re-run them.First CRAN release, under the name amorem. The
package was renamed from the working name amore, which
collided (case-insensitively) with the archived CRAN package
AMORE. This release consolidates the 0.9.0 development line
into the first stable, installable version: the unified
rem() front-end (the clogit, gam,
and nn backends, including the additive-spline
architecture), the Gillespie / tau-leap simulation engine, the
endogenous-statistics catalogue, and the martingale-residual
goodness-of-fit family. Relative to 0.9.0 the package was renamed to
amorem and the exported feature functions dropped their
compute_ prefix —
compute_endogenous_features() and
compute_hyperedge_features() became
endogenous_features() and
hyperedge_features(); the rest of the API is unchanged.
rem(method = "nn").
nn_control(engine = "torch") trains the same model and
conditional-logistic loss as the built-in pure-R engine using
torch (libtorch autograd + Adam), markedly faster and,
with batch_strata, scaling to large event logs (optionally
on GPU). The fitted object is interchangeable with the R engine.
torch is a Suggests dependency; the torch engine
requires equal-sized strata.nn_uncertainty() quantifies
uncertainty for a neural fit by a stratum bootstrap, returning
partial-dependence uncertainty bands and a concordance confidence
interval (with print() and plot() methods) —
the inferential counterpart the point-prediction nn backend
otherwise lacks.New neural backend and a small number of API refinements; the version intended for the first CRAN release.
nn_control(architecture = "additive_spline", batch_strata = )
fits per-covariate B-spline effects by (mini-batch) stochastic gradient
on the exact case-control partial likelihood — the construction of
Filippi-Mazzola & Wit (2024, JRSS-C, doi:10.1093/jrsssc/qlae023)
— giving interpretable additive smooth curves on the same objective as
clogit, with mini-batching for large event logs.rem(method = "nn") backend: a
multilayer perceptron scores every candidate in a case-control stratum
and is trained on the conditional-logistic partial likelihood (softmax
over each risk set) — a nonlinear, prediction-oriented counterpart of
clogit. Pure-R implementation (no extra dependencies),
configured via nn_control(); summary() reports
in-sample (and, with a validation split, held-out) concordance and
plot(type = "pdp") shows per-feature partial-dependence
curves.method = "gam" (was "degenerate"); the
smooth-term wrappers are tv() / nl() /
tvnl() (was tve() / nle() /
tvnle()); re() is unchanged.rem()’s case argument now defaults to
NULL and is taken from the formula’s left-hand side
(e.g. event ~ x) for the
clogit/nn backends.widen_case_control() auto-detects the 0/1 indicator
column (event or IS_OBSERVED) when
case is not given.widen_case_control() now carries the sender/receiver
identifiers of the case and its matched control into the output
(sender_ev/receiver_ev/
sender_nv/receiver_nv); the new
keep_ids argument controls this (default
TRUE). The dyads behind each pair are no longer lost, and
re() grouping terms can reach the actor levels (#92).rem(method = "gam") now detects long-format
case-control input (a event/IS_OBSERVED
indicator with control rows) and widens it with
widen_case_control() before fitting, emitting a message —
instead of silently misreading raw per-row values as event-minus-control
differences (#93).compute_endogenous_features() gains a
prior_log argument for warm-starting the network state from
events that precede the study window: its rows update the running state
but never appear in the output, separating warm-starting from the
non-event masking role of history_log (#94).cpp_supported_stats() is now exported.First release.
rem() unified fitter for preprocessed case-control
data, with a gam (case-1-control logistic via
mgcv::gam()) and a clogit backend.gam backend
(time-varying, non-linear, time-varying-non-linear) and an
re() grouping random effect; re() reproduces
the Intro-to-REM tutorial parameterization, and rem()
exposes a gam_method argument.simulate_relational_events() (Gillespie
and tau-leap), the endogenous-statistic feature engine, non-event
sampling, and the martingale-residual goodness-of-fit family.