Create a Mixed Model with Repeated Measures Using Natural Cubic Splines.
Source:R/ncs_mmrm_fit.R
ncs_mmrm_fit.RdBuilds an mmrm model that includes a study arm,
optionally a subgroup, and natural cubic splines applied to a continuous
time variable. A wrapper around mmrm::mmrm().
Constructs a call to mmrm::mmrm() for ncs analysis. Implements natural
cubic splines for the continuous time variable. Attempts a sequence of
covariance structures in order until one of them successfully converges.
Title
Usage
ncs_mmrm_fit(
data,
type = c("basic", "subgroup_full", "subgroup_reduced"),
response,
subject,
cov_structs = c("us", "toeph", "ar1h", "csh", "cs"),
cov_struct_group = NULL,
time_observed_continuous,
df = 2,
spline_basis = NULL,
time_observed_index,
time_scheduled_continuous = NULL,
arm = NULL,
control_group = "control",
subgroup = NULL,
subgroup_comparator = NULL,
covariates = ~1,
expand_spline_terms = TRUE,
mmrm_args = list(method = "Satterthwaite"),
...
)Arguments
- data
(
data frame)
data set supplied to thedataargument ofmmrm::mmrm()when fitting models. The supplied expression is quoted and must evaluate to a data frame. See Tidy evaluation support.- type
(
string)
one of"basic","subgroup_full", or"subgroup_reduced".- response
(
numericorstring)
the response variable. It can be astringidentifying the name of an existing variable; otherwise, the supplied expression will be quoted and added to the formula as is (see Tidy evaluation support).- subject
(
atomicorstring)
the unique subject identifier forwarded to thesubjectargument ofmmrm::cov_struct(). Ignored ifcov_structsis alist. Can be astringidentifying an existing variable; otherwise the supplied expression will be quoted and turned into astringwithrlang::expr_deparse()(see Tidy evaluation support).- cov_structs
(
characterorlist)
either alistof uniquecov_structobjects or acharactervector of one or more of the covariance structure abbreviations as described inmmrm::cov_types(). These covariance structures will be attempted in order until one of them achieves a converging model fit. Defaults toc("us", "toeph", "ar1h", "csh", "cs").- cov_struct_group
(
atomicorstring)
optional grouping variable to be passed to thegroupargument ofmmrm::cov_struct(). It can be astringidentifying an existing variable name; otherwise the supplied expression will be quoted and turned into astringwithrlang::expr_deparse()(see Tidy evaluation support). Ignored ifcov_structsis alist. Defaults toNULL, in which case no grouping variable will be used.- time_observed_continuous
(
numericorstring)
the visit's observed time point. It must either be astringor a name identifying an existing variable (i.e., it cannot be a call). If a name is provided, it is quoted and incorporated into the model formula as is (see Tidy evaluation support).- df
(scalar
integer)
number of degrees of freedom to use to create the spline basis. Passed to thedfargument oftime_spline_basis(). Ignored if thespline_basisargument is notNULL.- spline_basis
(
basismatrix)
a spline basis: probably a value returned bytime_spline_basis()(which wrapssplines::ns()). IfNULL(the default), then the spline basis will be the result of forwardingtime_observed_continuousanddftotime_spline_basis(). See Providing a spline basis.- time_observed_index
(
orderedorstring)
the visit index that the visit shall be associated with, based on the visit's observed time point. This will be passed as thevisitsargument ofmmrm::cov_struct(). It can be astringidentifying an existing variable; otherwise the supplied expression will be quoted and turned into astringwithrlang::expr_deparse()(see Tidy evaluation support). If it does not evaluate to anorderedfactor, it will be wrapped withas.ordered(). Ignored ifcov_structsis alist.- time_scheduled_continuous
(
numericorstring)
the continuous time point when the visit was scheduled to occur. Its unique values will identify the time points at which the marginal means and other results will be calculated. It can be astringidentifying an existing variable name; otherwise the supplied expression will be quoted before being evaluated (see Tidy evaluation support).- arm
(
factororstring)
the study arm. It must be astringor a name identifying an existing variable (i.e., it cannot be a call). If a name, it will be quoted before being added to the model formula (see Tidy evaluation support). If it does not evaluate to a factor or ifcontrol_groupis not its first level, thedataargument will be wrapped in adplyr::mutate()call that forces this to be the case.- control_group
(
string)
the value inarmdenoting the control group. If necessary,armwill be preprocessed such that it is a factor withcontrol_groupas its first level.- subgroup
(
factororstring)
the subgroup. It must be astringor a name identifying an existing variable (i.e., it cannot be a call). If a name, it will be quoted before being added to the model formula (see Tidy evaluation support). If it does not evaluate to a factor or ifsubgroup_comparatoris not its first level, thedataargument will be wrapped in adplyr::mutate()call that forces this to be the case.- subgroup_comparator
(
string)
the value insubgroupdenoting the "main" subgroup that all other subgroups should be compared to. If necessary,subgroupwill be preprocessed such that it is a factor withcontrol_groupas its first level.- covariates
(
formula)
formula containing additional terms that should be added to themmrmmodel. Defaults to~ 1, in which no additional terms will be added. Must not have a left side. Cannot contain.. To specify that the model shall not have an intercept, use include+ 0or- 1in this formula.- expand_spline_terms
(
flag)
flag indicating whether or not to separate the cubic spline matrix into separate terms (one for each degree of freedom). Defaults toTRUE. See Expanding spline terms.- mmrm_args
(named
list)
arguments to be passed tommrm::mmrm(). If any elements have the namesformula,data, orcovariancethey will be ignored. An element namedvcovwill also be ignored unless fitting a model with an unstructured covariance. Defaults tolist(method = "Satterthwaite").- ...
additional arguments to be passed to
mmrm::mmrm(). If any elements have the namesformula,data, orcovariancethey will be ignored. An element namedvcovwill also be ignored unless fitting a model with an unstructured covariance. Defaults tolist(method = "Satterthwaite"). Arguments named inmmrm_argssupersede any named arguments in....
Value
An mmrm object created by mmrm::mmrm().
Providing a spline basis
This function's spline_basis argument was designed with splines::ns() in
mind, which creates a matrix object with classes basis and matrix as well
as multiple attributes. In theory, spline_basis does not have to be a
matrix; however, it still must have a stats::predict() method wherein
stats::predict(spline_basis, data[[time_observed_continuous]]) produces an
object that can serve as a term in the model.
Covariance structures
The user specifies covariance structure candidates via the cov_structs
argument. These structures will be attempted in order until a model converges
successfully.
When any covariance structure other than "us" (heterogeneous unstructured)
is used, "Empirical-Bias-Reduced" is passed to mmrm::mmrm() as the vcov
argument (see mmrm::mmrm_control()).
When fitting models, these analysis functions specify the covariance
structure through the covariance argument of mmrm::mmrm().
Building the model formula
These analysis functions automatically build the model formula from its
arguments. The user cannot remove any of these auto-generated terms, but
terms can be added via the covariates argument.
Time spline terms
Natural cubic splines will be applied to the time_observed_continuous
variable in data. These splines will be constructed according to the
user-specified spline_basis. A custom spline_fn() is constructed under
the hood that accepts time_observed_continuous and produces a spline matrix
based on the spline_basis. Thus, the model formula includes a time spline
term resembling spline_fn(time_observed_continuous).
arm and subgroup terms
All generated models include an interaction term between the time spline term
and the study arm term, but arm is not included as a main effect by
default. If this is desired, use the covariates argument (e.g., specify
covariates = ~ arm).
Concerning ncs_analysis_subgroup(), the subgroup variable is included as
a main effect, and its interaction with the time spline is also included.
Furthermore, the second-order interaction term between the time spline,
subgroup, and arm is also included for the main analysis model and the
"full" model (when subgroup_interaction_test = TRUE; see Subgroup
interaction test below).
Adding terms with covariates
The user can specify additional terms through the covariates argument,
which must be a formula.
The user cannot specify the covariance structure with this argument. See the Covariance structures section above.
The user can remove the intercept from the model by including 0 as a term
in covariates.
Model formula templates
The model formulas that the analysis functions construct will take the form of the formula templates below.
ncs_analysis() (i.e., no subgroup)
ncs_analysis_subgroup()
Main analysis model and "full" model:
response ~
spline_fn(time_observed_continuous) +
subgroup +
spline_fn(time_observed_continuous):subgroup +
spline_fn(time_observed_continuous):arm +
spline_fn(time_observed_continuous):subgroup:arm {+
covariates}"reduced" model:
Expanding spline terms
When expand_spline_terms = TRUE and spline_basis has at least two
dimensions (e.g., if it is a matrix, which is typical), the spline term
will be split into multiple terms: one for each of its columns.
For instance, if the user specifies a spline_basis with 3 degrees of
freedom, the above no-subgroup model formula template would become:
Examples
# Create a usable data set out of mmrm::fev_data
fev_mod <- mmrm::fev_data
fev_mod$VISITN <- fev_mod$VISITN * 10
fev_mod$time_cont <- fev_mod$VISITN + rnorm(nrow(fev_mod))
fev_mod$obs_visit_index <- round(fev_mod$time_cont)
# Example without subgroup:
ncs_mmrm_fit(
data = fev_mod,
type = "basic",
response = FEV1,
subject = USUBJID,
cov_structs = c("ar1", "us"),
time_observed_continuous = time_cont,
df = 2,
time_observed_index = obs_visit_index,
time_scheduled_continuous = VISITN,
arm = ARMCD,
control_group = "PBO",
covariates = ~ FEV1_BL + RACE
)
#> In as.ordered(obs_visit_index) there are dropped visits: 27, 33.
#> Additional attributes including contrasts are lost.
#> To avoid this behavior, make sure use `drop_visit_levels = FALSE`.
#> mmrm fit
#>
#> Formula: FEV1 ~ spline_fn(time_cont)[, 1] + spline_fn(time_cont)[, 2] +
#> FEV1_BL + RACE + spline_fn(time_cont)[, 1]:ARMCD + spline_fn(time_cont)[,
#> 2]:ARMCD
#> Data: fev_mod (used 537 observations from 197 subjects with maximum 23
#> timepoints)
#> Covariance: auto-regressive order one (2 variance parameters)
#> Inference: REML
#> Deviance: 3519.085
#>
#> Coefficients:
#> (Intercept) spline_fn(time_cont)[, 1]
#> 21.9675040 21.6539457
#> spline_fn(time_cont)[, 2] FEV1_BL
#> 16.2898692 0.1697069
#> RACEBlack or African American RACEWhite
#> 0.4284112 5.2781845
#> spline_fn(time_cont)[, 1]:ARMCDTRT spline_fn(time_cont)[, 2]:ARMCDTRT
#> 7.5780942 0.3654192
#>
#> Model Inference Optimization:
#> Converged with code 0 and message: convergence: rel_reduction_of_f <= factr*epsmch
# Example with subgroup:
ncs_mmrm_fit(
data = fev_mod,
type = "subgroup_full",
response = FEV1,
subject = USUBJID,
cov_structs = c("ar1", "us"),
time_observed_continuous = time_cont,
df = 2,
time_observed_index = obs_visit_index,
time_scheduled_continuous = VISITN,
arm = ARMCD,
control_group = "PBO",
subgroup = SEX,
subgroup_comparator = "Male",
covariates = ~ FEV1_BL + RACE
)
#> In as.ordered(obs_visit_index) there are dropped visits: 27, 33.
#> Additional attributes including contrasts are lost.
#> To avoid this behavior, make sure use `drop_visit_levels = FALSE`.
#> mmrm fit
#>
#> Formula: FEV1 ~ spline_fn(time_cont)[, 1] + spline_fn(time_cont)[, 2] +
#> SEX + FEV1_BL + RACE + spline_fn(time_cont)[, 1]:SEX + spline_fn(time_cont)[,
#> 2]:SEX + spline_fn(time_cont)[, 1]:ARMCD + spline_fn(time_cont)[,
#> 2]:ARMCD + spline_fn(time_cont)[, 1]:SEX:ARMCD + spline_fn(time_cont)[,
#> 2]:SEX:ARMCD
#> Data: fev_mod (used 537 observations from 197 subjects with maximum 23
#> timepoints)
#> Covariance: auto-regressive order one (2 variance parameters)
#> Inference: REML
#> Deviance: 3495.243
#>
#> Coefficients:
#> (Intercept)
#> 19.04064075
#> spline_fn(time_cont)[, 1]
#> 26.03036523
#> spline_fn(time_cont)[, 2]
#> 16.16544536
#> SEXFemale
#> 4.84326016
#> FEV1_BL
#> 0.17108349
#> RACEBlack or African American
#> 0.62450086
#> RACEWhite
#> 5.45148575
#> spline_fn(time_cont)[, 1]:SEXFemale
#> -7.52228108
#> spline_fn(time_cont)[, 2]:SEXFemale
#> 0.36217537
#> spline_fn(time_cont)[, 1]:ARMCDTRT
#> 10.16711616
#> spline_fn(time_cont)[, 2]:ARMCDTRT
#> 0.01344647
#> spline_fn(time_cont)[, 1]:SEXFemale:ARMCDTRT
#> -4.60721973
#> spline_fn(time_cont)[, 2]:SEXFemale:ARMCDTRT
#> 0.38589869
#>
#> Model Inference Optimization:
#> Converged with code 0 and message: convergence: rel_reduction_of_f <= factr*epsmch