"survival" outcome family. set_ipd() accepts time-to-event
data with right, left, interval and delayed-entry censoring through a
survival::Surv() object or time/status/entry_time columns, and
set_agd_surv() takes the comparator arm as reconstructed pseudo-IPD plus
its covariate moments. outcome is not required for this family.distribution
argument of mlumr(): proportional hazards ("exponential", "weibull",
"gompertz"), accelerated failure time ("exponential-aft",
"weibull-aft", "lognormal", "loglogistic", "gamma", "gengamma")
and flexible hazards ("mspline", "pexp") with a random-walk smoothing
prior. make_knots() places spline knots; knots accepts a custom set.aux_by = ".study"), each stratum with its own knots over its own
observed support, as multinma::nma() does. aux_by = "none" shares one
baseline across studies.prior_aux, prior_aux2 (second generalized-gamma
auxiliary) and prior_smooth, with default_prior_aux() and
default_prior_smooth().predict() on a survival fit returns "survival", "hazard",
"cumhaz", "rmst", "median" and "loghr" curves. times picks
evaluation times (snapped to the fitted grid, with a message when they
move), pred_times sets the grid, "median" carries p_not_reached, and
RMST rows carry their horizon. conditional_effects() and
conditional_predict() give covariate-conditional versions.marginal_effects() reports survival effects on the natural scale:
the hazard ratio (HR) for proportional-hazards fits, the time ratio (TR)
for shared-shape AFT fits, the exponentiated contrast (EXP_DELTA_ETA)
otherwise, plus the RMST difference (RMSTD) and ratio (RMSTR). Marginal
hazard ratios carry an at_time column because they are time-varying and
non-collapsible; predict(type = "loghr") gives the whole curve.effect = "tr" on a proportional-hazards
fit, effect = "hr" on an AFT fit, and either on a relaxed or
study-specific-shape AFT fit.naive() returns the unadjusted Cox log
hazard ratio and refuses a partial likelihood with no maximum or no
convergence. stc() returns the RMST difference by parametric
G-computation with flexsurv, with a bootstrap interval (n_boot,
default 200) and an rmst_horizon argument.survival_unit on calculate_loo(), calculate_waic() and
compare_models() chooses what one held-out unit is for the reconstructed
comparator: "observation" (default, optimistic), "arm" or
"aggregate".summary() are labeled by covariate name
(beta[age], beta_index[age], beta_comparator[age]); the stored
variable strings are unchanged.?mlumr.mlumr() refuses an M-spline basis column that no subject was at risk
under, judged over the merged [entry, exit] intervals of each study, and
refuses a shared baseline (aux_by = "none") whose studies never overlap
on a spline column. See ?mlumr.predict(type = "rmst") and predict(type = "median") warn
when the prediction grid is too coarse to trust and point at a finer
n_rmst_grid or pred_times.?set_agd_surv states that reconstruction uncertainty is not
propagated and which population the covariate moments must describe under
delayed entry.newdata argument on marginal_effects() and predict()
standardizes effects and absolute predictions to an arbitrary target
population by Bayesian g-computation, for every family. Standardizing to the
index covariates reproduces population = "index" exactly. Survival RMST
effects and absolute predictions transport; the marginal hazard ratio is
reported for a target too, with its at_time.marginal_effects() on a relaxed fit queried for the index
population prints a one-line note with the marginal posterior variance
change of beta_comparator per covariate, descriptive only. Silence it
with options(mlumr.quiet_relaxed_index = TRUE).plot() methods for marginal_effects() (forest),
predict() (curves with credible bands, or point-intervals for scalar
types) and conditional_effects() (effects by profile). Each forest draws
the null its measure implies, uses a log axis for ratio measures, and reads
its interval level from the result.geom_km() overlays the observed Kaplan-Meier curves on a model
survival plot, colored by treatment, honoring delayed entry, one panel per
population. It draws right-censored data only.plot_prior_posterior() overlays each named parameter's posterior
on the prior the fit recorded for it.mlumr_forest() draws a forest from a plain data frame, for mixed
comparisons such as naive(), stc() and both ML-UMR models on one axis;
a single very wide interval is clipped with an arrow instead of squeezing
the rest.marginal_effects(), predict() and conditional_effects()
return lightweight data.frame subclasses so the methods dispatch; data
frame behavior is unchanged.check_identification() reports, before fitting, whether the
aggregate subgroup rows can identify beta_comparator in
model = "relaxed": the row count against K + 1, and the balance,
effective dimension and spread of the centered subgroup-mean matrix, with a
descriptive-only label for nonlinear links.prior_beta_comparator argument to mlumr() sets a separate
prior on beta_comparator, including a different family. Defaults to
prior_beta; ignored for model = "spfa"; reported by prior_summary()
and swept by prior_sensitivity().set_agd() row as evidence; it triggers on the rank of the mean design
under the identity link and on the number of distinct integration grids
otherwise.distr() honors arguments passed by position. distr(qnorm, 10, 2)
previously integrated a standard normal without any message. Positional
and abbreviated arguments are now matched against the quantile function's
formals at construction, and an argument matching nothing is an error.qgamma()/pgamma()/dgamma() and
qlogitnorm()/plogitnorm()/dlogitnorm() accept mean and sd, so
distr(qgamma, mean = age_mean, sd = age_sd) works as printed in a
baseline table. Without those arguments they forward to stats. See
?GammaDist and ?logitNormal.set_agd() no longer rejects a valid binary covariate SD. The bound
was the population SD sqrt(p (1 - p)); it is now the finite-sample
maximum with a rounding allowance. See ?set_agd.set_agd() requires outcome_n when normal aggregate data
have more than one row, and the multi-row comparator estimand for the
normal family is the sample-size-weighted mean of the strata rather than
an inverse-variance average. naive() and stc() use the same weights.set_ipd() warns about a rank-deficient or nearly collinear
covariate design and names the near-redundant covariates. Autoscaling of a
covariate with no usable empirical scale falls back to the unscaled prior
with a warning.add_integration() rejects cor_adjust = "pearson" with
non-Gaussian margins, warns about a nonbinary discrete margin (count or
ordered category) that the copula correction does not cover, and warns when
a supplied distr() grossly contradicts the declared set_agd() moments.check_integration() compares realized and target correlations
on the same method (Pearson or Spearman), reports fidelity of each grid
margin to the declared mean and SD, lists which correlation pairs it could
and could not measure (correlation_pairs, with "partial" and "review"
verdicts), withholds the comparison under cor_adjust = "none", and reports
a comparison it could not make as "unavailable" instead of "close".family = "normal" the default priors are on the outcome's
scale. Under the identity link the intercepts and coefficients are in the
outcome's units, and the residual SD is under either link, so the fixed
normal(0, 10) intercept and half-normal(0, 2.5) residual-SD defaults were
informative for an outcome such as a 0 to 100 score or a blood pressure in
mmHg. They pulled each intercept toward zero, the comparator's (resting on
one aggregate mean) the most, which moved the mean difference, and they
understated the residual SD, which narrowed the intervals. With sd(y) the
IPD outcome SD, the defaults are now normal(0, 10 * sd(y)) for the
intercepts and normal(0, 2.5 * sd(y)) for the coefficients (identity
link), and a half-normal with scale 2.5 * sd(y) for the residual SD
(either link); autoscale = TRUE multiplies a coefficient's scale by
sd(y) as well as dividing it by sd(x) under the identity link. Priors
written out in full are used as given. prior_summary() prints the scales
the model used, and prior_sensitivity() sweeps a default or autoscaled
prior_beta in the same outcome-SD units. Refit normal-family analyses
that relied on the defaults or on autoscale.prior_normal(autoscale = TRUE) rescales the prior location as well
as the scale, so a nonzero prior mean is on the covariate's own scale.prior_sensitivity() varies the prior and nothing else: every
model-defining setting is replayed from the fit and ... may not override
it. Relaxed fits sweep the comparator prior alongside the index one
(prior_beta_comparator_scales, reported in scale_comparator), survival
rows carry effect and at_time, and a refit that cannot replay a sampler
argument the original fit used (such as thin or init) warns and names
it.prior_sensitivity() quantile columns are named q2.5, q50,
q97.5, matching marginal_effects(), rather than q2 and q98. Duplicate
probs are refused.prior_sensitivity() no longer claims a scale sweep proves the
inference is data-driven; its interpretation text points at
check_identification().prior_summary() names constrained priors correctly: a truncated
normal or t with a nonzero location is not a half-normal or half-t, and an
exponential is not truncated at all.stc() no longer reports an index-population contrast. That
estimate assumed a constant link-scale effect, which population adjustment
exists to avoid. stc() returns the comparator-population estimand only;
use mlumr() when the index population is the target.stc() under a log link reports the log mean
ratio in $estimate and the mean difference in $md, $md_se,
$md_lower, $md_upper. Under the identity link the two coincide.stc() refuses a binomial outcome model with complete separation and,
when detectseparation is installed, tests exactly for quasi-complete
separation; the result records a separation status. A Poisson model with
no events is refused the same way. See ?stc.naive(), and the
observed comparator proportion in a binomial stc(), use exact
Clopper-Pearson and Garwood intervals instead of Wald intervals, which
excluded the truth at zero counts. Contrasts remain Wald.naive() combines several aggregate rows as strata; the comparator
standard error is that of the size-weighted mean of the row proportions.naive() and stc() apply a continuity correction only to an
observed proportion of 0 or 1 instead of clamping every proportion, which
slightly changes the reported effect for arms with no events or no
non-events.mlumr() gains model-defining arguments ahead of chains,
iter and the other sampler controls. Pass sampler settings by name.mlumr() centers covariates by default (center = TRUE),
which removes the intercept-versus-slope collinearity that pushed the
sampler into deep trajectories on raw-scale covariates. Reported contrasts
are unchanged; prior_intercept then applies at the pooled covariate mean.
qr = TRUE offers a QR-rotated design instead.fit$summary$se_mean is the Monte Carlo
standard error of the posterior mean from posterior::mcse_mean(). It was
the posterior SD over the square root of the bulk ESS, which is computed on
rank-normalized draws and misstates the error for skewed quantities such as
a ratio.mlumr() refuses a normal fit whose outcome is constant or reproduced
exactly by its covariates, where the posterior for the residual SD is
improper, and warns when the design is saturated.safe_logit() and safe_divide() clamps are gone, so
ratios with a near-zero comparator are no longer understated and lor_*
is finite where it used to hit the clamp. A ratio beyond double precision
is Inf. See ?mlumr-numerical-evaluation.predict(type = "link") returns the marginal link
g(E[g^-1(eta)]) rather than the mean linear predictor E[eta]; the two
agree for the identity link only. This differs from multinma on purpose,
since every effect mlumr reports is population-standardized.seed = NULL uses the documented default of 2026 with a
warning instead of drawing an unrecorded seed from the session RNG.verbose = FALSE silences the cmdstanr sampler banner as well.control list is merged with the backend's instead
of failing argument matching.checkmate on a temporary path.#include, the
CmdStan version and its build flags; a changed include no longer reuses a
stale executable. Expect one recompile after upgrading.check_diagnostics() and the fit summary no longer drop an infinite
Rhat before taking the maximum, report missing or non-numeric diagnostics
as unknown rather than as zero, and compute tail ESS.predict(), marginal_effects(), conditional_effects() and
conditional_predict() warn once per call when NA or NaN draws were
dropped from a summary.conditional_predict() names quantile columns from the requested
probabilities, so non-round probs no longer return NA.calculate_loo() refuses moment_match = TRUE, which loo ignores
for a matrix.compare_models() with "loo" or "waic" refuses fits whose stored
outcomes differ. loo_compare() pairs the pointwise scores by position, so
the same data fitted in another row order gave a wrong se_diff. The
calculate_loo() and calculate_waic() results carry the outcomes as
loo's yhash, so loo::loo_compare() warns on the same mismatch.compare_models() printout no longer presents
se_diff > 2 as a decision rule.psoriasis_ipd/psoriasis_agd (binary),
shoulder_ipd/shoulder_agd (continuous), caries_ipd/caries_agd
(count) and ndmm_ipd/ndmm_agd/ndmm_agd_covs (survival). Provenance
and known quirks are on each help page;
data-raw/prepare_multinma_subsets.R rebuilds them.introduction,
data-preparation, binary-outcomes, continuous-outcomes,
count-outcomes, survival-outcomes, subgroup-identification,
fitting-and-diagnostics, choosing-a-method), precompiled through
R.rsp so no Stan model runs at check time.?set_agd states what an aggregate Poisson row assumes about
exposure, and the shoulder and caries help pages describe their
reference comparison as an estimate rather than a known truth.vignette("count-outcomes") explains why its SPFA rate
ratio is the same in both populations and at every covariate profile (a
directly transportable effect), and the README states that the marginal
hazard ratio varies over time even when both studies share one baseline shape.splines2 and survival added to Imports; ggplot2 moved from Suggests
to Imports (>= 3.4.0).flexsurv, detectseparation, ggsurvfit and R.rsp added to Suggests.copula is no longer imported: the Gaussian-copula integration points are
built from the Cholesky factor in base R.Additional_repositories is pinned to https://mc-stan.org/r-packages
so that rstan and StanHeaders resolve from one source. cmdstanr itself
comes from https://stan-dev.r-universe.dev; mlumr_engine("cmdstanr")
offers to install it from there.Initial CRAN release.
mlumr_engine() or the
engine argument.set_ipd(), set_agd(), combine_data() and add_integration()
(Sobol quasi-Monte Carlo points with a Gaussian copula), mirroring the
multinma interface.prior_normal(), prior_student_t(), prior_cauchy()
and prior_exponential(), per-coefficient priors, autoscale,
prior_summary() and prior_sensitivity().predict(), marginal_effects(), conditional_effects() and
conditional_predict().calculate_dic(), calculate_loo(), calculate_waic() and
compare_models().check_diagnostics() and check_integration().stc() (parametric G-computation) and naive().