Specify regression models for the time-varying variables to be used
within the g-formula simulation. This function creates unevaluated models and
can further pass to gformula or mediation.
Arguments
- formula
an object of class formula: An object of class
formula: symbolic model specification to be fitted (e.g.,Y ~ A + L + time). The variables referenced informulamust exist in the analysisdata.framewhen fitting/evaluating the model during g-formula simulation.- subset
Optional. An unquoted logical expression naming columns of the analysis data (e.g.
platnormm1 == 0) that restricts this model to a subset of observations. It is passed through when fitting and re-evaluated at each time step during simulation, so only the rows satisfying it have their response drawn from this model. Rows that never satisfy it keep whatever value they already carry.- recode
Optional. One or more recoding statements built with
recodes(e.g.recodes(L_lag1 = L)orrecodes(M_lag1 = 0)), applied before fitting the model and before simulating its response (useful for dynamic recoding). Anything that is not arecodes()object is rejected.- var_type
Character. The response type for simulation/prediction:
"normal"(the default),"binary","categorical", or"custom". By default, values are simulated via:"binary": Bernoulli draws using the fitted mean."normal": Gaussian draws using fitted mean, clipped to the observed range of the response (seetruncate)."categorical": Multinomial draws viamultinom."custom": user-specified viacustom_fitand/orcustom_sim(numeric output is also clipped to the observed range unlesstruncate = FALSE).
- mod_type
Character. The role of this model in the data-generating process:
"covariate"(the default),"exposure","mediator","outcome","censor", or"survival".- custom_fit
Optional. A model fitting function, used only when
var_type = "custom"(it is ignored, with a warning, for the other types). Ifvar_type = "custom"andcustom_fitis not provided,glmis used by default. This can be used to define a fitting function other thanglmandmultinom.Scope:
spec_model()records the function name, not the function object, and the fit is evaluated inside the package. The name must therefore resolve from the global environment or from a package namespace — a fitter defined inside another function or insidelocal()will not be found. Prefer a fully qualified name (e.g.truncreg::truncregfor truncated regression), which is also what makes the bootstrap work under a parallelplan, where each worker is a fresh session.What the fitted object must provide: without
custom_simthe simulation evaluates the fit's linear predictor, so it needs atermscomponent and acoefmethod; a fit lacking either is rejected with an explanatory error naming the variable. Withcustom_simthe drawing is delegated, and neither is required. Choosing a model that is appropriate for the variable, and acustom_simthat draws from the distribution that model implies, remains the analyst's responsibility.- custom_sim
Optional. A simulation function for the model. It must accept two arguments – the fitted model object and a
data.frameof new data to predict on – and return a vector of simulated responses of matching length. When supplied it takes priority over the drawing rule implied byvar_type. If omitted andvar_type = "custom", normal draws are used by default, which requires the fitted object to have atermscomponent and acoefmethod.It supplies a draw, not a fitted value. At each time step the Monte Carlo engine assigns this variable the vector
custom_simreturns, in place of the draw the built-invar_typerule would have made (a Bernoulli draw for"binary", a Gaussian draw around the linear predictor for"normal"). Returningpredict()'s fitted value therefore assigns the conditional mean rather than a draw from the conditional distribution. Whether that is appropriate for the variable being simulated is the analyst's decision.It does not apply to the outcome. For
mod_type = "outcome"or"survival"the reported risk is computed from the fitted model's own linear predictor, socustom_simaffects only the simulated response value, never the estimate. Those models must therefore have extractable coefficients.- truncate
Logical. If
TRUE(default), simulated numeric values are clipped to the range of the response observed in the data — i.e. a"normal"draw is clipped to[min, max]of the observed response, and numeric output ofcustom_simis clipped as well.TRUEis the default. It corresponds to thesim_truncargument of gfoRmula, documented there as "whether to truncate simulated covariates to their range in the observed data set", whose default is alsoTRUE. SetFALSEto draw from the untruncated fitted distribution (corresponding tosim_trunc = FALSE), or to let acustom_simfunction be authoritative over its own output range. Which is appropriate depends on the variable being simulated and is the analyst's decision. Has no effect on"binary"or"categorical"responses.- ...
Other parameters passed to the model fitting function,
glm,multinomorcustom_fit.
Value
An object of class "causalMed_gmodel":
callAn unevaluated call (function + arguments) to fit the model.
subsetThe unevaluated subset expression provided via
subset.recodeThe recoding statements provided via
recode.var_typeThe response type, as provided.
mod_typeThe model role, as provided.
custom_simThe simulation function provided via
custom_sim.truncateThe truncation flag, as provided.
Details
This function will be used to create an unevaluated model for the g-formula.
spec_model() does not fit the model immediately. It returns an unevaluated
call plus metadata (var_type, mod_type, subset, recode,
custom_sim) that are used later by gformula/mediation
to fit in temporal order and to simulate counterfactual trajectories.
Examples
data(gvhd)
mod_cov1 <- spec_model(platnorm ~ all + cmv + male + age + agecurs1 +
agecurs2 + gvhdm1 + daysgvhd + daysnorelapse + wait,
var_type = "binary",
mod_type = "covariate",
subset = platnormm1 == 0
)
## For Poisson regression
predict_poisson <- function(fit, newdf) {
theta <- stats::predict(object = fit, type = "response", newdata = newdf)
prediction <- rpois(n = nrow(newdf), lambda = theta)
return(prediction)
}
mod_cov1 <- spec_model(platnorm ~ all + cmv + male + age + agecurs1 +
agecurs2 + gvhdm1 + daysgvhd + daysnorelapse + wait,
var_type = "custom",
mod_type = "covariate",
subset = platnormm1 == 0,
custom_sim = predict_poisson,
family = "poisson"(link = "log"),
y = TRUE
)