# fit_single_optimizer ----
test_that("fit_single_optimizer works as expected with defaults", {
dat <- fev_data
form <- FEV1 ~ ARMCD * RACE + us(AVISIT | USUBJID)
result <- fit_single_optimizer(
formula = form,
data = dat,
weights = rep(1, nrow(dat))
)
expect_identical(class(result), c("mmrm_fit", "mmrm_tmb"))
expect_identical(component(result, "optimizer"), "L-BFGS-B")
expect_identical(attr(result, "messages"), NULL)
expect_identical(attr(result, "warnings"), NULL)
expect_true(attr(result, "converged"))
})
test_that("fit_single_optimizer works as expected with nlminb optimizer but no starting values", {
dat <- fev_data
form <- FEV1 ~ SEX + us(AVISIT | USUBJID)
result <- fit_single_optimizer(
formula = form,
data = dat,
weights = rep(1, nrow(dat)),
optimizer = "nlminb"
)
expect_identical(class(result), c("mmrm_fit", "mmrm_tmb"))
expect_identical(component(result, "optimizer"), "nlminb")
expect_identical(attr(result, "messages"), NULL)
expect_identical(attr(result, "warnings"), NULL)
expect_true(attr(result, "converged"))
})
test_that("fit_single_optimizer works as expected with optimizer inputted but no starting values", {
dat <- fev_data
form <- FEV1 ~ SEX + us(AVISIT | USUBJID)
result <- fit_single_optimizer(
formula = form,
data = dat,
weights = rep(1, nrow(dat)),
optimizer = "BFGS"
)
expect_identical(class(result), c("mmrm_fit", "mmrm_tmb"))
expect_identical(component(result, "optimizer"), "BFGS")
expect_identical(attr(result, "messages"), NULL)
expect_identical(attr(result, "warnings"), NULL)
expect_true(attr(result, "converged"))
})
test_that("fit_single_optimizer works as expected with starting values and optimizer inputted", {
dat <- fev_data
form <- FEV1 ~ RACE + ARMCD + us(AVISIT | USUBJID)
result <- fit_single_optimizer(
formula = form,
data = dat,
weights = rep(1, nrow(dat)),
optimizer = "BFGS",
start = 1:10
)
expect_identical(class(result), c("mmrm_fit", "mmrm_tmb"))
expect_identical(component(result, "optimizer"), "BFGS")
expect_identical(attr(result, "messages"), NULL)
expect_identical(attr(result, "warnings"), NULL)
expect_true(attr(result, "converged"))
})
test_that("fit_single_optimizer gives error messages", {
formula <- FEV1 ~ bla
expect_error(
fit_mmrm(formula, fev_data),
paste(
"Covariance structure must be specified in formula.",
"Possible covariance structures include:",
"us, toep, toeph, ar1, ar1h, ad, adh, cs, csh, sp_exp"
),
fixed = TRUE
)
expect_error(
fit_single_optimizer(formula, fev_data, weights = rep(1, nrow(fev_data))),
paste(
"Covariance structure must be specified in formula.",
"Possible covariance structures include:",
"us, toep, toeph, ar1, ar1h, ad, adh, cs, csh"
),
fixed = TRUE
)
})
test_that("fit_single_optimizer is stable to extreme scaling with defaults", {
# We generate an example data set with two variables on very different scales.
# After rescaling to sd = 1 both would have unit effect on the outcome.
scaling_factor <- 1e6
set.seed(42L)
id <- factor(rep(1:50, each = 2))
visit <- factor(rep(c(1, 2), 50))
x_large <- rep(rnorm(50, sd = sqrt(scaling_factor)), each = 2)
x_small <- rep(rnorm(50, sd = 1 / sqrt(scaling_factor)), each = 2)
y <- x_large / sqrt(scaling_factor) + sqrt(scaling_factor) * x_small + rnorm(100, sd = .5) # add some noise
dat <- data.frame(id = id, x_large = x_large, x_small = x_small, visit = visit, y = y)
result <- fit_single_optimizer(
formula = y ~ x_large + x_small + us(visit | id),
data = dat,
weights = rep(1, nrow(dat))
)
# Compute relative error on both coefficients and check that it is small.
beta_est <- coef(result)[c("x_large", "x_small")]
rel_err <- c(beta_est - c(1 / sqrt(scaling_factor), sqrt(scaling_factor))) /
c(1 / sqrt(scaling_factor), sqrt(scaling_factor))
expect_true(attr(result, "converged"))
expect_true(all(abs(rel_err) <= 0.05))
})
test_that("fit_single_optimizer catches convergence warning as expected", {
dat <- data.frame(
FEV1 = c(1, 2, 3, 4, 5),
AVISIT = factor(c("V1", "V1", "V2", "V3", "V4")),
USUBJID = c("A", "B", "A", "C", "A")
)
vars <- list(
response = "FEV1",
id = "USUBJID",
visit = "AVISIT"
)
result <- expect_silent(fit_single_optimizer(
formula = FEV1 ~ AVISIT + us(AVISIT | USUBJID),
data = dat,
weights = rep(1, nrow(dat)),
optimizer = "L-BFGS-B"
))
expect_match(attr(result, "warnings"), regexp = "Model convergence problem")
expect_false(attr(result, "converged"))
expect_class(component(result, "theta_vcov"), "try-error")
})
test_that("fit_single_optimizer deals correctly with unobserved visits message", {
data_unobs <- fev_data[fev_data$AVISIT != "VIS3", ]
result <- expect_silent(fit_single_optimizer(
formula = FEV1 ~ RACE + ad(AVISIT | USUBJID),
data = data_unobs,
weights = rep(1, nrow(data_unobs))
))
expect_identical(
attr(result, "messages"),
paste0(
"In AVISIT there are dropped visits: VIS3.\n Additional attributes including contrasts are lost.",
"\nTo avoid this behavior, make sure use `drop_visit_levels = FALSE`."
)
)
expect_true(attr(result, "converged"))
})
test_that("fit_single_optimizer fails if formula contains `.`", {
expect_error(
fit_single_optimizer(FEV1 ~ ., data = fev_data, weights = rep(1, 800)),
"`.` is not allowed in mmrm models!"
)
})
test_that("fit_single_optimizer signals non-convergence but does not fail for finite values error", {
fake_optimizer <- function(par, fun, grad, ...) {
stop("L-BFGS-B needs finite values of 'fn'")
}
result <- expect_silent(fit_single_optimizer(
formula = FEV1 ~ AVISIT + us(AVISIT | USUBJID),
data = fev_data,
weights = rep(1, nrow(fev_data)),
control = mmrm_control(
optimizer_fun = fake_optimizer
)
))
expect_false(attr(result, "converged"))
expect_identical(attr(result, "divergence"), "L-BFGS-B needs finite values of 'fn'")
})
test_that("fit_single_optimizer signals non-convergence but does not fail for NA/NaN Hessian error", {
fake_optimizer <- function(par, fun, grad, ...) {
stop("NA/NaN Hessian evaluation")
}
result <- expect_silent(fit_single_optimizer(
formula = FEV1 ~ AVISIT + us(AVISIT | USUBJID),
data = fev_data,
weights = rep(1, nrow(fev_data)),
control = mmrm_control(
optimizer_fun = fake_optimizer
)
))
expect_false(attr(result, "converged"))
expect_identical(attr(result, "divergence"), "NA/NaN Hessian evaluation")
})
# h_summarize_all_fits ----
test_that("h_summarize_all_fits works as expected", {
mod_fit <- fit_single_optimizer(
formula = FEV1 ~ RACE + SEX + ARMCD * AVISIT + us(AVISIT | USUBJID),
data = fev_data,
weights = rep(1, nrow(fev_data)),
optimizer = "nlminb"
)
mod_fit2 <- fit_single_optimizer(
formula = FEV1 ~ RACE + SEX + ARMCD * AVISIT + us(AVISIT | USUBJID),
data = fev_data,
weights = rep(1, nrow(fev_data)),
optimizer = "L-BFGS-B"
)
all_fits <- list(mod_fit, mod_fit2)
result <- expect_silent(h_summarize_all_fits(all_fits))
skip_if_r_devel_linux_clang()
expected <- list(
warnings = list(NULL, NULL),
messages = list(NULL, NULL),
log_liks = c(-1693.22493558573, -1693.22493812251),
converged = c(TRUE, TRUE)
)
expect_equal(result, expected)
})
test_that("h_summarize_all_fits works when some list elements are try-error objects", {
skip_if_r_devel_linux_clang()
mod_fit <- get_mmrm()
mod_fit2 <- try(stop("bla"), silent = TRUE)
mod_fit3 <- get_mmrm()
all_fits <- list(mod_fit, mod_fit2, mod_fit3)
result <- expect_silent(h_summarize_all_fits(all_fits))
expected <- list(
warnings = list(NULL, "Error in try(stop(\"bla\"), silent = TRUE) : bla\n", NULL),
messages = list(NULL, NULL, NULL),
log_liks = c(-1693.225, NA, -1693.225),
converged = c(TRUE, FALSE, TRUE)
)
expect_equal(result, expected, tolerance = 1e-3)
})
# refit_multiple_optimizers ----
test_that("refit_multiple_optimizers works as expected with default arguments", {
fit <- fit_single_optimizer(
formula = FEV1 ~ ar1(AVISIT | USUBJID),
data = fev_data,
weights = rep(1, nrow(fev_data)),
optimizer = "nlminb"
)
assert_true(attr(fit, "converged"))
# Mock here that it did not converge.
attr(fit, "converged") <- FALSE
fit$neg_log_lik <- fit$neg_log_lik + 10
result <- expect_silent(refit_multiple_optimizers(fit = fit, optimizer = "nlminb"))
expect_class(result, "mmrm_fit")
expect_true(attr(result, "converged"))
expect_identical("nlminb", component(result, "optimizer"))
expect_true(logLik(result) > logLik(fit))
})
test_that("refit_multiple_optimizers works with parallel computations and selected optimizers", {
skip_on_cran()
skip_if(!isTRUE(parallel::detectCores() > 1), "unable to detect more than one core")
has_parallelly <- length(find.package("parallelly", quiet = TRUE)) > 0
n_cores <- if (has_parallelly) parallelly::availableCores(omit = 1) else 2
fit <- fit_single_optimizer(
formula = FEV1 ~ RACE + SEX + ARMCD * AVISIT + us(AVISIT | USUBJID),
data = fev_data,
weights = rep(1, nrow(fev_data)),
optimizer = "nlminb"
)
# Mock here that it did not converge.
attr(fit, "converged") <- FALSE
fit$neg_log_lik <- fit$neg_log_lik + 10
result <- expect_silent(refit_multiple_optimizers(
fit = fit,
n_cores = n_cores,
optimizer = c("BFGS", "CG")
))
expect_class(result, "mmrm_fit")
expect_true(attr(result, "converged"))
expect_subset(component(result, "optimizer"), choices = c("BFGS", "CG"))
expect_true(logLik(result) > logLik(fit))
})
# mmrm ----
## convergence ----
test_that("mmrm works as expected for unstructured", {
formula <- FEV1 ~ us(AVISIT | USUBJID)
result <- expect_silent(mmrm(formula, fev_data, reml = FALSE))
expect_class(result, c("mmrm", "mmrm_fit", "mmrm_tmb"))
expect_true(attr(result, "converged"))
expect_list(result$jac_list, types = "matrix")
expect_class(result$call, "call")
expect_false(result$reml)
})
test_that("mmrm works as expected for antedependence", {
formula <- FEV1 ~ RACE + SEX + ARMCD * AVISIT + ad(AVISIT | USUBJID)
result <- expect_silent(mmrm(formula, fev_data, reml = TRUE))
expect_class(result, c("mmrm", "mmrm_fit", "mmrm_tmb"))
expect_true(attr(result, "converged"))
expect_list(result$jac_list, types = "matrix")
expect_class(result$call, "call")
expect_true(result$reml)
})
test_that("mmrm works as expected for toeplitz", {
formula <- FEV1 ~ RACE + SEX + ARMCD * AVISIT + toep(AVISIT | USUBJID)
result <- expect_silent(mmrm(formula, fev_data, reml = TRUE))
expect_class(result, c("mmrm", "mmrm_fit", "mmrm_tmb"))
expect_true(attr(result, "converged"))
expect_list(result$jac_list, types = "matrix")
expect_class(result$call, "call")
expect_true(result$reml)
})
## general ----
test_that("mmrm falls back to other optimizers if default does not work", {
formula <- FEV1 ~ ar1(AVISIT | USUBJID)
# Chosen optimizer does not work.
fake_optimizer <- function(par, fun, grad, ...) {
stop("NA/NaN Hessian evaluation")
}
expect_error(
expect_warning(
mmrm(formula, fev_data, optimizer_fun = fake_optimizer),
"Divergence with optimizer"
),
"Consider trying multiple or different optimizers"
)
# But another one works.
# Note: We disable parallel processing here to comply with CRAN checks.
expect_warning(
result <- mmrm(
formula, fev_data,
n_cores = 1L,
optimizer_fun = c(fake = fake_optimizer, h_get_optimizers("L-BFGS-B"))
),
"Divergence with optimizer"
)
expect_true(attr(result, "converged"))
expect_true(identical(component(result, "optimizer"), "L-BFGS-B"))
})
test_that("mmrm fails if no optimizer works", {
skip_on_ci()
skip_on_cran()
# We skip this test on CI and CRAN since it can be flaky on different platforms.
formula <- FEV1 ~ RACE + SEX + ARMCD * AVISIT + us(AVISIT | USUBJID)
data_small <- fev_data[1:30, ]
# Note: Here we are using parallel computations.
expect_error(
expect_message(
mmrm(formula, data_small, reml = FALSE),
"Some factor levels are dropped due to singular design matrix: RACE"
),
"No optimizer led to a successful model fit"
)
})
test_that("mmrm works for rank deficient original design matrix by default", {
formula <- FEV1 ~ SEX + SEX2 + ar1(AVISIT | USUBJID)
dat <- fev_data
dat$SEX2 <- dat$SEX # nolint
result <- expect_silent(mmrm(formula, dat))
expect_true(attr(result, "converged"))
expect_true(is.na(coef(result)["SEX2Female"]))
})
test_that("mmrm works if data is not provided as argument", {
result <- expect_silent(
with(
fev_data,
mmrm(FEV1 ~ RACE + SEX + ARMCD * AVISIT + us(AVISIT | USUBJID))
)
)
expect_true(attr(result, "converged"))
})
test_that("mmrm works if formula contains variables not in data", {
set.seed(123L)
y <- rnorm(800)
wt <- exp(rnorm(800))
result <- expect_silent(
mmrm(y ~ RACE + SEX + ARMCD * AVISIT + us(AVISIT | USUBJID), weights = wt, data = fev_data)
)
expect_true(attr(result, "converged"))
})
test_that("mmrm works for specific small data example", {
small_dat <- data.frame(
FEV1 = c(1, 2, 3, 4, 5, 6, 7, 8),
AVISIT = factor(c("V1", "V1", "V2", "V3", "V3", "V4", "V4", "V4")),
USUBJID = c("A", "B", "A", "C", "D", "A", "B", "C")
)
vars <- list(
response = "FEV1",
id = "USUBJID",
visit = "AVISIT"
)
fit <- expect_silent(mmrm(
formula = FEV1 ~ AVISIT + ar1(AVISIT | USUBJID),
data = small_dat
))
expect_true(attr(fit, "converged"))
})
test_that("mmrm works for custom optimizer", {
custom_optimizer <- optim
fit <- mmrm(
FEV1 ~ ARMCD + ar1(AVISIT | SEX / USUBJID),
data = fev_data,
reml = TRUE,
optimizer_fun = custom_optimizer,
optimizer_args = list(method = "Nelder-Mead", hessian = TRUE),
start = c(1, 2, 3, 4),
method = "Kenward-Roger"
)
expect_equal(
fit$theta_est, c(2.2225, 0.4054, 2.2136, 0.4389),
tolerance = 1e-4
)
})
test_that("mmrm works for constructed control", {
expect_silent(mmrm(
FEV1 ~ ARMCD + ar1(AVISIT | SEX / USUBJID),
data = fev_data,
reml = TRUE,
control = mmrm_control(optimizer = c("BFGS", "CG"))
))
})
test_that("mmrm works for start = NULL", {
expect_silent(mmrm(
FEV1 ~ ARMCD + ar1(AVISIT | SEX / USUBJID),
data = fev_data,
reml = TRUE,
control = mmrm_control(optimizer = c("BFGS", "CG"), start = NULL)
))
})
test_that("mmrm returns the correct best fit", {
opts <- list(
a = h_partial_fun_args(fail_optimizer, message = "this is wrong"),
b = h_partial_fun_args(fail_optimizer, message = "this is wrong too"),
c = h_partial_fun_args(silly_optimizer, value_add = 0, message = "silly success")
)
fit <- expect_silent(mmrm(
FEV1 ~ ARMCD + ar1(AVISIT | SEX / USUBJID),
data = fev_data,
reml = TRUE,
control = mmrm_control(optimizers = opts)
))
expect_identical(
fit$opt_details,
list(convergence = 0, message = "silly success")
)
})
test_that("divergent optimizer will not be marked as success", {
fev <- fev_data
fev$FEV1[seq(1, 800, 4)] <- 0
expect_error(
expect_warning(
mmrm(FEV1 ~ AVISIT + us(AVISIT | USUBJID), data = fev),
"Divergence with optimizer"
),
"No optimizer led to a successful model fit."
)
})
test_that("mmrm will use the provided contrast", {
fev2 <- fev_data
contrasts(fev2$ARMCD) <- contr.poly(n = 2)
fit <- expect_silent(mmrm(FEV1 ~ ARMCD * AVISIT + ar1(AVISIT | USUBJID), data = fev2))
expect_snapshot_tolerance(coef(fit))
})
## start values ----
test_that("start can be emp_start or std_start and they work", {
expect_silent(
mmrm(
formula = FEV1 ~ ARMCD + us(AVISIT | USUBJID),
data = fev_data,
start = emp_start
)
)
expect_silent(
mmrm(
formula = FEV1 ~ ARMCD + us(AVISIT | USUBJID),
data = fev_data,
start = std_start
)
)
})
test_that("mmrm fails if start function does not provide correct values", {
wrong_start <- function(...) {
c(NA_real_, 0L)
}
expect_error(
mmrm(
formula = FEV1 ~ ARMCD + us(AVISIT | USUBJID),
data = fev_data,
start = wrong_start
),
"Assertion on 'start_values' failed: Must have length 10, but has length 2."
)
expect_error(
mmrm(
formula = FEV1 ~ ARMCD + ar1(AVISIT | USUBJID),
data = fev_data,
start = wrong_start
),
"Assertion on 'start_values' failed: Contains missing values \\(element 1\\)"
)
})
test_that("mmrm fails if start function fails", {
wrong_start <- function(...) {
stop("this is wrong")
}
expect_error(
mmrm(
formula = FEV1 ~ ARMCD + us(AVISIT | USUBJID),
data = fev_data,
start = wrong_start
),
"this is wrong"
)
})
test_that("mmrm works for transformed response using emp_start", {
expect_silent(
mmrm(
formula = log(FEV1) ~ ARMCD + exp(FEV1_BL) + us(AVISIT | USUBJID),
data = fev_data,
start = std_start
)
)
expect_silent(
mmrm(
formula = log(FEV1) ~ ARMCD + exp(FEV1_BL) + us(AVISIT | USUBJID),
data = fev_data,
start = emp_start
)
)
})
test_that("mmrm works for character covariate using emp_start", {
fev_data2 <- fev_data
fev_data2$ARMCD <- as.character(fev_data2$ARMCD)
fev_data2$USUBJID <- as.character(fev_data2$USUBJID)
expect_silent(
mmrm(
formula = log(FEV1) ~ ARMCD + exp(FEV1_BL) + us(AVISIT | USUBJID),
data = fev_data2,
start = emp_start
)
)
})
test_that("mmrm still works for deprecated 'automatic' optimizer", {
expect_warning(
mmrm(
FEV1 ~ ARMCD + ar1(AVISIT | SEX / USUBJID),
data = fev_data,
reml = TRUE,
optimizer = "automatic"
),
"\"automatic\" optimizer was deprecated in mmrm 0.2.0.",
fixed = TRUE
)
})
test_that("mmrm works and gives message for data with unobserved visit levels", {
data_unobs <- fev_data[fev_data$AVISIT != "VIS3", ]
expect_message(
result <- mmrm(
FEV1 ~ RACE + ad(AVISIT | USUBJID),
data = data_unobs
),
"In AVISIT there are dropped visits: VIS3"
)
data_dropped <- droplevels(data_unobs)
expected <- mmrm(
FEV1 ~ RACE + ad(AVISIT | USUBJID),
data = data_dropped
)
expect_identical(deviance(result), deviance(expected))
})
test_that("mmrm fails when using ... and control at the same time", {
expect_error(
mmrm(
formula = FEV1 ~ us(AVISIT | USUBJID),
data = fev_data,
accept_singular = FALSE,
control = mmrm_control(method = "Kenward-Roger")
),
"Assertion on '!missing(control) && !missing(...)' failed",
fixed = TRUE
)
})
test_that("mmrm fails when using formula covariance with covariance argument", {
expect_error(
mmrm(
formula = FEV1 ~ us(AVISIT | USUBJID),
covariance = cov_struct("us", "AVISIT", "USUBJID"),
data = fev_data,
),
"Redundant covariance structure",
fixed = TRUE
)
})
test_that("mmrm works when using formula directly in covariance", {
expect_silent(
mmrm(
formula = FEV1 ~ ARMCD,
covariance = ~ us(AVISIT | USUBJID),
data = fev_data,
)
)
})
test_that("mmrm works for different na.actions", {
na_action <- getOption("na.action")
on.exit(options(na.action = na_action))
options(na.action = "na.omit")
formula <- FEV1 ~ ARMCD + us(AVISIT | USUBJID)
res1 <- expect_silent(mmrm(formula, fev_data))
expect_class(res1, "mmrm")
options(na.action = "na.pass")
expect_warning(
res2 <- mmrm(formula, fev_data),
"na.action is always set to `na.omit` for `mmrm` fit!"
)
expect_class(res2, "mmrm")
options(na.action = "na.fail")
expect_warning(
res3 <- mmrm(formula, fev_data),
"na.action is always set to `na.omit` for `mmrm` fit!"
)
expect_class(res3, "mmrm")
options(na.action = "na.exclude")
expect_warning(
res4 <- mmrm(formula, fev_data),
"na.action is always set to `na.omit` for `mmrm` fit!"
)
expect_class(res4, "mmrm")
})
test_that("mmrm still works for a model that only contains an interaction term", {
expect_silent(
mmrm(
FEV1 ~ ARMCD:SEX + ar1(AVISIT | SEX / USUBJID),
data = fev_data,
reml = TRUE
)
)
})
test_that("mmrm fails if formula contains `.`", {
expect_error(
mmrm(FEV1 ~ ., data = fev_data, weights = rep(1, 800)),
"`.` is not allowed in mmrm models!"
)
})
test_that("mmrm can proceed to second optimizer if first one has divergence error", {
fake_optimizer <- function(par, fun, grad, ...) {
stop("NA/NaN Hessian evaluation")
}
expect_warning(
result <- mmrm(
formula = FEV1 ~ ARMCD + us(AVISIT | USUBJID),
data = fev_data,
control = mmrm_control(optimizers = c(fake = fake_optimizer, h_get_optimizers()))
),
"Divergence with optimizer fake due to problems"
)
expect_true(attr(result, "converged"))
})
test_that("mmrm behaves correctly when some of alternative optimizers have divergence errors", {
fake_optimizer <- function(par, fun, grad, ...) {
stop("NA/NaN Hessian evaluation")
}
normal_optimizers <- h_get_optimizers()
expect_warning(
result <- mmrm(
formula = FEV1 ~ ARMCD + us(AVISIT | USUBJID),
data = fev_data,
control = mmrm_control(
optimizers = c(fake = fake_optimizer, normal_optimizers[1:2], fake2 = fake_optimizer)
)
),
"Divergence with optimizer fake due to problems"
)
expect_true(attr(result, "converged"))
})
test_that("mmrm works as expected when the only provided optimizer fails with divergence error", {
fake_optimizer <- function(par, fun, grad, ...) {
stop("NA/NaN Hessian evaluation")
}
expect_error(
expect_warning(
result <- mmrm(
formula = FEV1 ~ ARMCD + us(AVISIT | USUBJID),
data = fev_data,
optimizer_fun = fake_optimizer
),
"Divergence with optimizer"
),
"Consider trying multiple or different optimizers"
)
})
## vcov and method combination ----
test_that("mmrm works for vcov: Asymptotic and method: Sattherthwaite", {
result <- expect_silent(
mmrm(
formula = FEV1 ~ ARMCD + ar1(AVISIT | USUBJID),
data = fev_data,
method = "Satterthwaite",
vcov = "Asymptotic"
)
)
expect_class(result, c("mmrm", "mmrm_fit", "mmrm_tmb"))
expect_true(attr(result, "converged"))
expect_class(result$call, "call")
expect_true(result$reml)
expect_list(result$jac_list, types = "matrix")
})
test_that("mmrm works for vcov: Asymptotic and method: Between-Within", {
result <- expect_silent(
mmrm(
formula = FEV1 ~ ARMCD + ar1(AVISIT | USUBJID),
data = fev_data,
method = "Between-Within",
vcov = "Asymptotic"
)
)
expect_class(result, c("mmrm", "mmrm_fit", "mmrm_tmb"))
expect_true(attr(result, "converged"))
expect_class(result$call, "call")
expect_true(result$reml)
})
test_that("mmrm fails for vcov: Kenward-Roger and method: Sattherthwaite", {
expect_error(
mmrm(
formula = FEV1 ~ ARMCD + ar1(AVISIT | USUBJID),
data = fev_data,
method = "Satterthwaite",
vcov = "Kenward-Roger"
),
"Kenward-Roger degrees of freedom must work together with Kenward-Roger or Kenward-Roger-Linear covariance!"
)
})
test_that("mmrm fails for vcov: Kenward-Roger-Linear and method: Sattherthwaite", {
expect_error(
mmrm(
formula = FEV1 ~ ARMCD + ar1(AVISIT | USUBJID),
data = fev_data,
method = "Satterthwaite",
vcov = "Kenward-Roger-Linear"
),
"Kenward-Roger degrees of freedom must work together with Kenward-Roger or Kenward-Roger-Linear covariance!"
)
})
test_that("mmrm works for vcov: Empirical and method: Residual", {
result <- expect_silent(
mmrm(
formula = FEV1 ~ ARMCD + ar1(AVISIT | USUBJID),
data = fev_data,
method = "Residual",
vcov = "Empirical"
)
)
expect_class(result, c("mmrm", "mmrm_fit", "mmrm_tmb"))
expect_true(attr(result, "converged"))
expect_class(result$call, "call")
expect_true(result$reml)
expect_matrix(result$beta_vcov_adj)
})
test_that("mmrm works for vcov: Jackknife and method: Residual", {
result <- expect_silent(
mmrm(
formula = FEV1 ~ ARMCD + ar1(AVISIT | USUBJID),
data = fev_data,
method = "Residual",
vcov = "Empirical-Jackknife"
)
)
expect_class(result, c("mmrm", "mmrm_fit", "mmrm_tmb"))
expect_true(attr(result, "converged"))
expect_class(result$call, "call")
expect_true(result$reml)
expect_matrix(result$beta_vcov_adj)
})
test_that("mmrm works for vcov: Empirical and method: Satterthwaite", {
result <- expect_silent(
mmrm(
formula = FEV1 ~ ARMCD + ar1(AVISIT | USUBJID),
data = fev_data,
method = "Satterthwaite",
vcov = "Empirical"
)
)
expect_class(result, c("mmrm", "mmrm_fit", "mmrm_tmb"))
expect_true(attr(result, "converged"))
expect_class(result$call, "call")
expect_true(result$reml)
expect_matrix(result$beta_vcov_adj)
# Here we don't need the Jacobian list.
expect_null(result$jac_list)
})
test_that("mmrm works for vcov: Jackknife and method: Satterthwaite", {
result <- expect_silent(
mmrm(
formula = FEV1 ~ ARMCD + ar1(AVISIT | USUBJID),
data = fev_data,
method = "Satterthwaite",
vcov = "Empirical-Jackknife"
)
)
expect_class(result, c("mmrm", "mmrm_fit", "mmrm_tmb"))
expect_true(attr(result, "converged"))
expect_class(result$call, "call")
expect_true(result$reml)
expect_matrix(result$beta_vcov_adj)
# Here we don't need the Jacobian list.
expect_null(result$jac_list)
})
test_that("mmrm fails for vcov: Asymptotic and method: Kenward-Roger", {
expect_error(
mmrm(
formula = FEV1 ~ ARMCD + ar1(AVISIT | USUBJID),
data = fev_data,
method = "Kenward-Roger",
vcov = "Asymptotic"
),
"Kenward-Roger degrees of freedom must work together with Kenward-Roger or Kenward-Roger-Linear covariance!"
)
})
test_that("mmrm works for vcov: Kenward-Roger and method: Kenward-Roger", {
result <- expect_silent(
mmrm(
formula = FEV1 ~ ARMCD + ar1(AVISIT | USUBJID),
data = fev_data,
method = "Kenward-Roger",
vcov = "Kenward-Roger"
)
)
expect_class(result, c("mmrm", "mmrm_fit", "mmrm_tmb"))
expect_true(attr(result, "converged"))
expect_class(result$call, "call")
expect_true(result$reml)
expect_list(result$kr_comp, types = "matrix")
expect_matrix(result$beta_vcov_adj)
})
test_that("mmrm works for vcov: Kenward-Roger-Linear and method: Kenward-Roger", {
result <- expect_silent(
mmrm(
formula = FEV1 ~ ARMCD + ar1(AVISIT | USUBJID),
data = fev_data,
method = "Kenward-Roger",
vcov = "Kenward-Roger-Linear"
)
)
expect_class(result, c("mmrm", "mmrm_fit", "mmrm_tmb"))
expect_true(attr(result, "converged"))
expect_class(result$call, "call")
expect_true(result$reml)
expect_list(result$kr_comp, types = "matrix")
expect_matrix(result$beta_vcov_adj)
})
test_that("mmrm fails for vcov: Empirical and method: Kenward-Roger", {
expect_error(
mmrm(
formula = FEV1 ~ ARMCD + ar1(AVISIT | USUBJID),
data = fev_data,
method = "Kenward-Roger",
vcov = "Empirical"
),
"Kenward-Roger degrees of freedom must work together with Kenward-Roger or Kenward-Roger-Linear covariance!"
)
})
test_that("mmrm fails for vcov: Jackknife and method: Kenward-Roger", {
expect_error(
mmrm(
formula = FEV1 ~ ARMCD + ar1(AVISIT | USUBJID),
data = fev_data,
method = "Kenward-Roger",
vcov = "Empirical-Jackknife"
),
"Kenward-Roger degrees of freedom must work together with Kenward-Roger or Kenward-Roger-Linear covariance!"
)
})
test_that("mmrm gives warning if not reproducible TMB option is used", {
TMB::config(tmbad_deterministic_hash = 0, DLL = "mmrm")
expect_warning(
mmrm(
formula = FEV1 ~ ARMCD + ar1(AVISIT | USUBJID),
data = fev_data
),
"TMB is configured to use a non-deterministic hash"
)
TMB::config(tmbad_deterministic_hash = 1, DLL = "mmrm")
})
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.