# proj_linpred() ----------------------------------------------------------
context("proj_linpred()")
## object -----------------------------------------------------------------
test_that("pl: `object` of class `projection` works", {
skip_if_not(run_prj)
for (tstsetup in names(prjs)) {
if (args_prj[[tstsetup]]$prj_nm == "augdat") {
ncats_nlats_expected_crr <- length(
refmods[[args_prj[[tstsetup]]$tstsetup_ref]]$family$cats
) - 1L
} else {
ncats_nlats_expected_crr <- integer()
}
ndr_ncl <- ndr_ncl_dtls(args_prj[[tstsetup]])
if (!has_const_wdr_prj(prjs[[tstsetup]])) {
wdr_crr <- prjs[[tstsetup]][["wdraws_prj"]]
} else {
wdr_crr <- NULL
}
pl_tester(pls[[tstsetup]],
nprjdraws_expected = ndr_ncl$nprjdraws,
wdraws_prj_expected = wdr_crr,
ncats_nlats_expected = list(ncats_nlats_expected_crr),
info_str = tstsetup)
if (run_snaps) {
if (testthat_ed_max2) local_edition(3)
width_orig <- options(width = 145)
expect_snapshot({
print(tstsetup)
print(rlang::hash(pls[[tstsetup]]))
})
options(width_orig)
if (testthat_ed_max2) local_edition(2)
}
}
})
test_that(paste(
"pl: `object` of (informal) class `proj_list` (based on varsel()) works"
), {
skip_if_not(run_vs)
for (tstsetup in names(prjs_vs)) {
tstsetup_vs <- args_prj_vs[[tstsetup]]$tstsetup_vsel
nterms_crr <- args_prj_vs[[tstsetup]]$nterms
if (is.null(nterms_crr)) {
nterms_crr <- suggest_size(vss[[tstsetup_vs]], warnings = FALSE)
}
if (args_prj_vs[[tstsetup]]$prj_nm == "augdat") {
ncats_nlats_expected_crr <- length(
refmods[[args_prj_vs[[tstsetup]]$tstsetup_ref]]$family$cats
) - 1L
} else {
ncats_nlats_expected_crr <- integer()
}
ndr_ncl <- ndr_ncl_dtls(args_prj_vs[[tstsetup]])
if (!has_const_wdr_prj(prjs_vs[[tstsetup]])) {
if (length(nterms_crr) > 1) {
wdr_crr <- drop(unique(do.call(rbind, lapply(prjs_vs[[tstsetup]], "[[",
"wdraws_prj"))))
} else {
wdr_crr <- prjs_vs[[tstsetup]][["wdraws_prj"]]
}
} else {
wdr_crr <- NULL
}
pl_tester(pls_vs[[tstsetup]],
len_expected = length(nterms_crr),
nprjdraws_expected = ndr_ncl$nprjdraws,
wdraws_prj_expected = wdr_crr,
ncats_nlats_expected = replicate(length(nterms_crr),
ncats_nlats_expected_crr,
simplify = FALSE),
info_str = tstsetup)
if (run_snaps) {
if (testthat_ed_max2) local_edition(3)
width_orig <- options(width = 145)
expect_snapshot({
print(tstsetup)
print(rlang::hash(pls_vs[[tstsetup]]))
})
options(width_orig)
if (testthat_ed_max2) local_edition(2)
}
}
})
test_that(paste(
"pl: `object` of (informal) class `proj_list` (based on cv_varsel()) works"
), {
skip_if_not(run_cvvs)
for (tstsetup in names(prjs_cvvs)) {
tstsetup_cvvs <- args_prj_cvvs[[tstsetup]]$tstsetup_vsel
nterms_crr <- args_prj_cvvs[[tstsetup]]$nterms
if (is.null(nterms_crr)) {
nterms_crr <- suggest_size(cvvss[[tstsetup_cvvs]], warnings = FALSE)
}
if (args_prj_cvvs[[tstsetup]]$prj_nm == "augdat") {
ncats_nlats_expected_crr <- length(
refmods[[args_prj_cvvs[[tstsetup]]$tstsetup_ref]]$family$cats
) - 1L
} else {
ncats_nlats_expected_crr <- integer()
}
ndr_ncl <- ndr_ncl_dtls(args_prj_cvvs[[tstsetup]])
if (!has_const_wdr_prj(prjs_cvvs[[tstsetup]])) {
if (length(nterms_crr) > 1) {
wdr_crr <- drop(unique(do.call(rbind, lapply(prjs_cvvs[[tstsetup]],
"[[", "wdraws_prj"))))
} else {
wdr_crr <- prjs_cvvs[[tstsetup]][["wdraws_prj"]]
}
} else {
wdr_crr <- NULL
}
pl_tester(pls_cvvs[[tstsetup]],
len_expected = length(nterms_crr),
nprjdraws_expected = ndr_ncl$nprjdraws,
wdraws_prj_expected = wdr_crr,
ncats_nlats_expected = replicate(length(nterms_crr),
ncats_nlats_expected_crr,
simplify = FALSE),
info_str = tstsetup)
if (run_snaps) {
if (testthat_ed_max2) local_edition(3)
width_orig <- options(width = 145)
expect_snapshot({
print(tstsetup)
print(rlang::hash(pls_cvvs[[tstsetup]]))
})
options(width_orig)
if (testthat_ed_max2) local_edition(2)
}
}
})
test_that(paste(
"`object` of (informal) class `proj_list` (created manually) works"
), {
skip_if_not(run_prj)
tstsetups <- grep(
"rstanarm\\.glm\\.gauss\\.stdformul\\..*\\.trad\\..*\\.clust$",
names(prjs), value = TRUE
)
stopifnot(length(tstsetups) > 1)
pl <- proj_linpred(prjs[tstsetups], allow_nonconst_wdraws_prj = TRUE,
.seed = seed2_tst)
wdr_crr <- unique(do.call(rbind, lapply(prjs[tstsetups], "[[", "wdraws_prj")))
stopifnot(nrow(wdr_crr) == 1)
wdr_crr <- drop(wdr_crr)
pl_tester(pl,
len_expected = length(tstsetups),
wdraws_prj_expected = wdr_crr,
ncats_nlats_expected = lapply(tstsetups, function(tstsetup) {
if (args_prj[[tstsetup]]$prj_nm == "augdat" &&
args_prj[[tstsetup]]$fam_nm == "brnll") {
return(1L)
} else {
return(integer())
}
}),
info_str = paste(tstsetups, collapse = ","))
})
test_that(paste(
"`object` of class `refmodel` and passing arguments to project() works"
), {
skip_if_not(run_prj)
tstsetups <- grep("\\.brnll\\..*\\.prd_trms_x\\.clust$", names(prjs),
value = TRUE)
for (tstsetup in tstsetups) {
args_prj_i <- args_prj[[tstsetup]]
pl_from_refmod <- do.call(proj_linpred, c(
list(object = refmods[[args_prj_i$tstsetup_ref]],
allow_nonconst_wdraws_prj = TRUE, .seed = seed2_tst),
excl_nonargs(args_prj_i)
))
pl_from_prj <- pls[[tstsetup]]
expect_equal(pl_from_refmod, pl_from_prj, info = tstsetup)
}
})
test_that(paste(
"`object` of class `stanreg` or `brmsfit` and passing arguments to",
"project() works"
), {
skip_if_not(run_prj)
tstsetups <- grep("\\.brnll\\..*\\.prd_trms_x\\.clust$", names(prjs),
value = TRUE)
for (tstsetup in tstsetups) {
args_prj_i <- args_prj[[tstsetup]]
pl_from_fit <- do.call(proj_linpred, c(
list(object = fits[[args_prj_i$tstsetup_fit]],
allow_nonconst_wdraws_prj = TRUE, .seed = seed2_tst),
excl_nonargs(args_prj_i),
excl_nonargs(args_ref[[args_prj_i$tstsetup_ref]])
))
pl_from_prj <- pls[[tstsetup]]
expect_equal(pl_from_fit, pl_from_prj, info = tstsetup)
}
})
test_that(paste(
"`object` of class `vsel` (created by varsel()) and passing arguments",
"to project() works"
), {
skip_if_not(run_vs)
tstsetups <- grep("\\.brnll\\..*\\.subvec", names(prjs_vs), value = TRUE)
if (any(grepl("\\.L1\\.", tstsetups))) {
tstsetups <- grep("\\.L1\\.", tstsetups, value = TRUE)
}
stopifnot(length(tstsetups) > 0)
for (tstsetup in tstsetups) {
args_prj_vs_i <- args_prj_vs[[tstsetup]]
pl_from_vsel <- do.call(proj_linpred, c(
list(object = vss[[args_prj_vs_i$tstsetup_vsel]],
allow_nonconst_wdraws_prj = TRUE, .seed = seed2_tst),
excl_nonargs(args_prj_vs_i)
))
pl_from_prj <- pls_vs[[tstsetup]]
expect_equal(pl_from_vsel, pl_from_prj, info = tstsetup)
}
})
test_that(paste(
"`object` of class `vsel` (created by cv_varsel()) and passing arguments",
"to project() works"
), {
skip_if_not(run_cvvs)
tstsetups <- grep("\\.brnll\\..*\\.default_cvmeth\\..*\\.subvec",
names(prjs_cvvs), value = TRUE)
if (any(grepl("\\.L1\\.", tstsetups))) {
tstsetups <- grep("\\.L1\\.", tstsetups, value = TRUE)
}
if (length(tstsetups) == 0) {
tstsetups <- grep("\\.glm\\.gauss.*\\.default_cvmeth\\..*\\.subvec",
names(prjs_cvvs), value = TRUE)
if (any(grepl("\\.L1\\.", tstsetups))) {
tstsetups <- grep("\\.L1\\.", tstsetups, value = TRUE)
}
tstsetups <- head(tstsetups, 1)
}
stopifnot(length(tstsetups) > 0)
for (tstsetup in tstsetups) {
args_prj_cvvs_i <- args_prj_cvvs[[tstsetup]]
pl_from_vsel <- do.call(proj_linpred, c(
list(object = cvvss[[args_prj_cvvs_i$tstsetup_vsel]],
allow_nonconst_wdraws_prj = TRUE, .seed = seed2_tst),
excl_nonargs(args_prj_cvvs_i)
))
pl_from_prj <- pls_cvvs[[tstsetup]]
expect_equal(pl_from_vsel, pl_from_prj, info = tstsetup)
}
})
test_that("`object` not of class `vsel` and missing `predictor_terms` fails", {
expect_error(
proj_linpred(1, .seed = seed2_tst),
paste("^Please provide an `object` of class `vsel` or use argument",
"`predictor_terms`\\.$")
)
if (length(fits)) {
expect_error(
proj_linpred(fits[[1]], .seed = seed2_tst),
paste("^Please provide an `object` of class `vsel` or use argument",
"`predictor_terms`\\.$")
)
expect_error(
proj_linpred(refmods[[1]], .seed = seed2_tst),
paste("^Please provide an `object` of class `vsel` or use argument",
"`predictor_terms`\\.$")
)
}
if (run_prj) {
expect_error(
proj_linpred(c(prjs, list(dat)), .seed = seed2_tst),
paste("Please provide an `object` of class `vsel` or use argument",
"`predictor_terms`\\.")
)
}
})
## newdata and integrated -------------------------------------------------
test_that("invalid `newdata` fails", {
skip_if_not(run_prj)
expect_error(
proj_linpred(prjs, newdata = dat[, 1], .seed = seed2_tst),
"must be a data\\.frame or a matrix"
)
stopifnot(length(prd_trms_x) > 1)
prj_crr <- prjs[[head(grep("\\.glm\\.gauss.*\\.prd_trms_x", names(prjs)), 1)]]
expect_error(
proj_linpred(prj_crr,
newdata = dat[, head(prd_trms_x, -1), drop = FALSE],
weightsnew = prj_crr$refmodel$wobs,
offsetnew = prj_crr$refmodel$offset,
.seed = seed2_tst),
"^object '.*' not found$"
)
})
test_that("`newdata` and `integrated` work (even in edge cases)", {
skip_if_not(run_prj)
for (tstsetup in names(prjs)) {
ndr_ncl <- ndr_ncl_dtls(args_prj[[tstsetup]])
if (!has_const_wdr_prj(prjs[[tstsetup]])) {
wdr_crr <- prjs[[tstsetup]][["wdraws_prj"]]
} else {
wdr_crr <- NULL
}
dat_crr <- get_dat(tstsetup)
for (nobsv_crr in nobsv_tst) {
if (args_prj[[tstsetup]]$mod_nm == "gamm") {
# TODO (GAMMs): Fix this.
next
}
if (args_prj[[tstsetup]]$prj_nm == "augdat") {
ncats_nlats_expected_crr <- length(
refmods[[args_prj[[tstsetup]]$tstsetup_ref]]$family$cats
) - 1L
} else {
ncats_nlats_expected_crr <- integer()
}
if (grepl("\\.with_wobs|\\.binom", tstsetup)) {
wobs_crr <- head(prjs[[tstsetup]]$refmodel$wobs, nobsv_crr)
} else {
wobs_crr <- NULL
}
if (grepl("\\.with_offs", tstsetup)) {
offs_crr <- head(prjs[[tstsetup]]$refmodel$offset, nobsv_crr)
} else {
offs_crr <- NULL
}
expect_warning(
pl_false <- proj_linpred(
prjs[[tstsetup]],
newdata = head(dat_crr, nobsv_crr),
weightsnew = wobs_crr,
offsetnew = offs_crr,
allow_nonconst_wdraws_prj = ndr_ncl$clust_used_gt1,
.seed = seed2_tst
),
get_warn_wrhs_orhs(tstsetup, weightsnew = wobs_crr,
offsetnew = offs_crr),
info = tstsetup
)
pl_tester(pl_false,
nprjdraws_expected = ndr_ncl$nprjdraws,
wdraws_prj_expected = wdr_crr,
nobsv_expected = nobsv_crr,
ncats_nlats_expected = list(ncats_nlats_expected_crr),
info_str = paste(tstsetup, nobsv_crr, sep = "__"))
expect_warning(
pl_true <- proj_linpred(prjs[[tstsetup]],
newdata = head(dat_crr, nobsv_crr),
weightsnew = wobs_crr,
offsetnew = offs_crr,
integrated = TRUE,
.seed = seed2_tst),
get_warn_wrhs_orhs(tstsetup, weightsnew = wobs_crr,
offsetnew = offs_crr),
info = tstsetup
)
pl_tester(pl_true,
nprjdraws_expected = 1L,
nobsv_expected = nobsv_crr,
ncats_nlats_expected = list(ncats_nlats_expected_crr),
info_str = paste(tstsetup, nobsv_crr, "integrated", sep = "__"))
pred_false <- pl_false$pred
if (args_prj[[tstsetup]]$prj_nm == "augdat") {
pred_false <- t(arr2augmat(pred_false, margin_draws = 1))
}
pred_true <- pl_true$pred
if (args_prj[[tstsetup]]$prj_nm == "augdat") {
pred_true <- t(arr2augmat(pred_true, margin_draws = 1))
}
expect_equal(prjs[[!!tstsetup]]$wdraws_prj %*% pred_false, pred_true,
info = nobsv_crr)
}
}
})
test_that("`newdata` set to the original dataset doesn't change results", {
skip_if_not(run_prj)
for (tstsetup in names(prjs)) {
ndr_ncl <- ndr_ncl_dtls(args_prj[[tstsetup]])
dat_crr <- get_dat(tstsetup)
if (grepl("\\.with_wobs|\\.binom", tstsetup)) {
wobs_crr <- wobs_tst
} else {
wobs_crr <- NULL
}
if (grepl("\\.with_offs", tstsetup)) {
offs_crr <- offs_tst
} else {
offs_crr <- NULL
}
# With `transform = FALSE`:
expect_warning(
pl_newdata <- proj_linpred(
prjs[[tstsetup]], newdata = dat_crr, weightsnew = wobs_crr,
offsetnew = offs_crr,
allow_nonconst_wdraws_prj = ndr_ncl$clust_used_gt1, .seed = seed2_tst
),
get_warn_wrhs_orhs(tstsetup, weightsnew = wobs_crr,
offsetnew = offs_crr),
info = tstsetup
)
pl_orig <- pls[[tstsetup]]
expect_equal(pl_newdata, pl_orig, info = tstsetup)
# With `transform = TRUE`:
expect_warning(
pl_newdata_t <- proj_linpred(
prjs[[tstsetup]], newdata = dat_crr, weightsnew = wobs_crr,
offsetnew = offs_crr,
allow_nonconst_wdraws_prj = ndr_ncl$clust_used_gt1, transform = TRUE,
.seed = seed2_tst
),
get_warn_wrhs_orhs(tstsetup, weightsnew = wobs_crr,
offsetnew = offs_crr),
info = tstsetup
)
pl_orig_t <- proj_linpred(
prjs[[tstsetup]], transform = TRUE,
allow_nonconst_wdraws_prj = ndr_ncl$clust_used_gt1, .seed = seed2_tst
)
expect_equal(pl_newdata_t, pl_orig_t, info = tstsetup)
}
})
test_that(paste(
"omitting the response in `newdata` (not possible for ``brmsfit``-based",
"reference models) causes output element `lpd` to be `NULL` but doesn't",
"change results otherwise"
), {
skip_if_not(run_prj)
for (tstsetup in names(prjs)) {
if (args_prj[[tstsetup]]$pkg_nm == "brms") {
next
}
ndr_ncl <- ndr_ncl_dtls(args_prj[[tstsetup]])
if (!has_const_wdr_prj(prjs[[tstsetup]])) {
wdr_crr <- prjs[[tstsetup]][["wdraws_prj"]]
} else {
wdr_crr <- NULL
}
resp_nm <- extract_terms_response(
prjs[[tstsetup]]$refmodel$formula
)$response
if (prjs[[tstsetup]]$refmodel$family$for_latent) {
resp_nm <- sub("^\\.", "", resp_nm)
}
stopifnot(!exists(resp_nm))
dat_crr <- get_dat(tstsetup)
if (grepl("\\.with_wobs|\\.binom", tstsetup)) {
wobs_crr <- wobs_tst
} else {
wobs_crr <- NULL
}
if (grepl("\\.with_offs", tstsetup)) {
offs_crr <- offs_tst
} else {
offs_crr <- NULL
}
pl_noresp <- proj_linpred(
prjs[[tstsetup]],
newdata = dat_crr[, setdiff(names(dat_crr), resp_nm)],
weightsnew = wobs_crr,
offsetnew = offs_crr,
allow_nonconst_wdraws_prj = ndr_ncl$clust_used_gt1,
.seed = seed2_tst
)
if (args_prj[[tstsetup]]$prj_nm == "augdat") {
ncats_nlats_expected_crr <- length(
refmods[[args_prj[[tstsetup]]$tstsetup_ref]]$family$cats
) - 1L
} else {
ncats_nlats_expected_crr <- integer()
}
pl_tester(pl_noresp,
nprjdraws_expected = ndr_ncl$nprjdraws,
wdraws_prj_expected = wdr_crr,
lpd_null_expected = TRUE,
ncats_nlats_expected = list(ncats_nlats_expected_crr),
info_str = tstsetup)
pl_orig <- pls[[tstsetup]]
expect_equal(pl_noresp$pred, pl_orig$pred, info = tstsetup)
}
})
## weightsnew -------------------------------------------------------------
test_that("`weightsnew` works", {
skip_if_not(run_prj)
for (tstsetup in names(prjs)) {
ndr_ncl <- ndr_ncl_dtls(args_prj[[tstsetup]])
if (!has_const_wdr_prj(prjs[[tstsetup]])) {
wdr_crr <- prjs[[tstsetup]][["wdraws_prj"]]
} else {
wdr_crr <- NULL
}
if (grepl("\\.with_offs", tstsetup)) {
offs_crr <- offs_tst
} else {
offs_crr <- NULL
}
if (args_prj[[tstsetup]]$prj_nm == "augdat") {
ncats_nlats_expected_crr <- length(
refmods[[args_prj[[tstsetup]]$tstsetup_ref]]$family$cats
) - 1L
} else {
ncats_nlats_expected_crr <- integer()
}
pl_orig <- pls[[tstsetup]]
expect_warning(
pl_ones <- proj_linpred(
prjs[[tstsetup]],
newdata = get_dat(tstsetup, dat_wobs_ones,
wobs_brms = 1),
weightsnew = ~ wobs_col_ones,
offsetnew = offs_crr,
allow_nonconst_wdraws_prj = ndr_ncl$clust_used_gt1,
.seed = seed2_tst
),
get_warn_wrhs_orhs(tstsetup, weightsnew = ~ wobs_col_ones,
offsetnew = offs_crr),
info = tstsetup
)
pl_tester(pl_ones,
nprjdraws_expected = ndr_ncl$nprjdraws,
wdraws_prj_expected = wdr_crr,
ncats_nlats_expected = list(ncats_nlats_expected_crr),
info_str = tstsetup)
if (!args_prj[[tstsetup]]$prj_nm %in% c("latent", "augdat")) {
expect_warning(
pl <- proj_linpred(prjs[[tstsetup]],
newdata = get_dat(tstsetup, dat,
wobs_brms = dat$wobs_col),
weightsnew = ~ wobs_col,
offsetnew = offs_crr,
allow_nonconst_wdraws_prj = ndr_ncl$clust_used_gt1,
.seed = seed2_tst),
get_warn_wrhs_orhs(tstsetup, weightsnew = ~ wobs_col,
offsetnew = offs_crr),
info = tstsetup
)
pl_tester(pl,
nprjdraws_expected = ndr_ncl$nprjdraws,
wdraws_prj_expected = wdr_crr,
ncats_nlats_expected = list(ncats_nlats_expected_crr),
info_str = tstsetup)
expect_warning(
plw <- proj_linpred(prjs[[tstsetup]],
newdata = get_dat(
tstsetup,
dat_wobs_new,
wobs_brms = dat_wobs_new$wobs_col_new
),
weightsnew = ~ wobs_col_new,
offsetnew = offs_crr,
allow_nonconst_wdraws_prj = ndr_ncl$clust_used_gt1,
.seed = seed2_tst),
get_warn_wrhs_orhs(tstsetup, weightsnew = ~ wobs_col_new,
offsetnew = offs_crr),
info = tstsetup
)
pl_tester(plw,
nprjdraws_expected = ndr_ncl$nprjdraws,
wdraws_prj_expected = wdr_crr,
ncats_nlats_expected = list(ncats_nlats_expected_crr),
info_str = tstsetup)
}
expect_equal(pl_ones$pred, pl_orig$pred, info = tstsetup)
if (!args_prj[[tstsetup]]$prj_nm %in% c("latent", "augdat")) {
expect_equal(pl$pred, pl_orig$pred, info = tstsetup)
expect_equal(plw$pred, pl_orig$pred, info = tstsetup)
}
if (grepl("\\.with_wobs|\\.binom", tstsetup)) {
expect_false(isTRUE(all.equal(pl_ones$lpd, pl_orig$lpd)), info = tstsetup)
if (!args_prj[[tstsetup]]$prj_nm %in% c("latent", "augdat")) {
expect_equal(pl$lpd, pl_orig$lpd, info = tstsetup)
expect_false(isTRUE(all.equal(plw$lpd, pl_ones$lpd)), info = tstsetup)
expect_false(isTRUE(all.equal(plw$lpd, pl$lpd)), info = tstsetup)
}
} else {
expect_equal(pl_ones$lpd, pl_orig$lpd, info = tstsetup)
if (!args_prj[[tstsetup]]$prj_nm %in% c("latent", "augdat")) {
if (args_prj[[tstsetup]]$pkg_nm == "rstanarm") {
expect_false(isTRUE(all.equal(pl$lpd, pl_orig$lpd)), info = tstsetup)
expect_false(isTRUE(all.equal(plw$lpd, pl_orig$lpd)), info = tstsetup)
expect_false(isTRUE(all.equal(plw$lpd, pl$lpd)), info = tstsetup)
} else if (args_prj[[tstsetup]]$pkg_nm == "brms") {
expect_equal(pl$lpd, pl_orig$lpd, info = tstsetup)
expect_equal(plw$lpd, pl_orig$lpd, info = tstsetup)
}
}
}
}
})
## offsetnew --------------------------------------------------------------
test_that("`offsetnew` works", {
skip_if_not(run_prj)
for (tstsetup in names(prjs)) {
ndr_ncl <- ndr_ncl_dtls(args_prj[[tstsetup]])
if (!has_const_wdr_prj(prjs[[tstsetup]])) {
wdr_crr <- prjs[[tstsetup]][["wdraws_prj"]]
} else {
wdr_crr <- NULL
}
if (grepl("\\.with_wobs|\\.binom", tstsetup)) {
wobs_crr <- wobs_tst
} else {
wobs_crr <- NULL
}
if (args_prj[[tstsetup]]$prj_nm == "augdat") {
ncats_nlats_expected_crr <- length(
refmods[[args_prj[[tstsetup]]$tstsetup_ref]]$family$cats
) - 1L
} else {
ncats_nlats_expected_crr <- integer()
}
pl_orig <- pls[[tstsetup]]
add_offs_crr <- args_prj[[tstsetup]]$prj_nm == "latent" &&
args_prj[[tstsetup]]$pkg_nm == "rstanarm" &&
grepl("\\.with_offs\\.", tstsetup)
expect_warning(
pl_zeros <- proj_linpred(
prjs[[tstsetup]],
newdata = get_dat(tstsetup, dat_offs_zeros,
offs_ylat = 0,
add_offs_dummy = add_offs_crr,
offs_brms = 0),
weightsnew = wobs_crr,
offsetnew = ~ offs_col_zeros,
allow_nonconst_wdraws_prj = ndr_ncl$clust_used_gt1,
.seed = seed2_tst
),
get_warn_wrhs_orhs(tstsetup, weightsnew = wobs_crr,
offsetnew = ~ offs_col_zeros),
info = tstsetup
)
pl_tester(pl_zeros,
nprjdraws_expected = ndr_ncl$nprjdraws,
wdraws_prj_expected = wdr_crr,
ncats_nlats_expected = list(ncats_nlats_expected_crr),
info_str = tstsetup)
expect_warning(
pl <- proj_linpred(prjs[[tstsetup]],
newdata = get_dat(tstsetup, dat),
weightsnew = wobs_crr,
offsetnew = ~ offs_col,
allow_nonconst_wdraws_prj = ndr_ncl$clust_used_gt1,
.seed = seed2_tst),
get_warn_wrhs_orhs(tstsetup, weightsnew = wobs_crr,
offsetnew = ~ offs_col),
info = tstsetup
)
pl_tester(pl,
nprjdraws_expected = ndr_ncl$nprjdraws,
wdraws_prj_expected = wdr_crr,
ncats_nlats_expected = list(ncats_nlats_expected_crr),
info_str = tstsetup)
expect_warning(
plo <- proj_linpred(prjs[[tstsetup]],
newdata = get_dat(
tstsetup, dat_offs_new,
offs_ylat = dat_offs_new$offs_col_new,
add_offs_dummy = add_offs_crr,
offs_brms = dat_offs_new$offs_col_new
),
weightsnew = wobs_crr,
offsetnew = ~ offs_col_new,
allow_nonconst_wdraws_prj = ndr_ncl$clust_used_gt1,
.seed = seed2_tst),
get_warn_wrhs_orhs(tstsetup, weightsnew = wobs_crr,
offsetnew = ~ offs_col_new),
info = tstsetup
)
pl_tester(plo,
nprjdraws_expected = ndr_ncl$nprjdraws,
wdraws_prj_expected = wdr_crr,
ncats_nlats_expected = list(ncats_nlats_expected_crr),
info_str = tstsetup)
pred_pl <- pl$pred
pred_pl_orig <- pl_orig$pred
pred_plo <- plo$pred
if (args_prj[[tstsetup]]$prj_nm == "augdat") {
pred_pl <- t(arr2augmat(pred_pl, margin_draws = 1))
pred_pl_orig <- t(arr2augmat(pred_pl_orig, margin_draws = 1))
pred_plo <- t(arr2augmat(pred_plo, margin_draws = 1))
}
if (grepl("\\.with_offs", tstsetup)) {
expect_equal(pl, pl_orig, info = tstsetup)
expect_false(isTRUE(all.equal(pl_zeros, pl)), info = tstsetup)
expect_false(isTRUE(all.equal(plo, pl)), info = tstsetup)
if (args_prj[[tstsetup]]$prj_nm != "latent") {
expect_false(isTRUE(all.equal(pl_zeros$pred, pl$pred)), info = tstsetup)
expect_false(isTRUE(all.equal(plo$pred, pl$pred)), info = tstsetup)
expect_false(isTRUE(all.equal(pl_zeros$lpd, pl$lpd)), info = tstsetup)
expect_false(isTRUE(all.equal(plo$lpd, pl$lpd)), info = tstsetup)
} else {
# Latent projection is an exception because the reference model's
# latent predictions (i.e., the artificial latent response `ynew`
# recomputed inside of proj_linpred_aux()) are shifted by the same
# offsets as the submodel's predictions (i.e., the mean values for the
# latent Gaussian distributions), so the log predictive values are
# unchanged:
expect_false(isTRUE(all.equal(pl_zeros$pred, pl$pred)), info = tstsetup)
expect_false(isTRUE(all.equal(plo$pred, pl$pred)), info = tstsetup)
expect_equal(pl_zeros$lpd, pl$lpd, info = tstsetup)
expect_equal(plo$lpd, pl$lpd, info = tstsetup)
}
} else {
expect_equal(pl_zeros, pl_orig, info = tstsetup)
if (args_prj[[tstsetup]]$pkg_nm == "rstanarm") {
expect_false(isTRUE(all.equal(plo, pl)), info = tstsetup)
if (args_prj[[tstsetup]]$fam_nm %in% c("brnll", "binom")) {
# To avoid failing tests due to numerical inaccuracies for extreme
# values:
is_extreme <- which(abs(pred_pl_orig) > f_binom$linkfun(1 - 1e-12),
arr.ind = TRUE)
pred_pl_orig[is_extreme] <- NA
pred_pl[is_extreme] <- NA
pred_plo[is_extreme] <- NA
}
pred_pl_no_offs <- t(pred_pl)
if (args_prj[[tstsetup]]$prj_nm == "augdat" &&
get_fam_long(args_prj[[tstsetup]]$fam_nm) %in% fams_neg_linpred()) {
pred_pl_no_offs <- pred_pl_no_offs + dat$offs_col
} else {
pred_pl_no_offs <- pred_pl_no_offs - dat$offs_col
}
expect_equal(pred_pl_no_offs, t(pred_pl_orig), info = tstsetup)
pred_plo_no_offs <- t(pred_plo)
if (args_prj[[tstsetup]]$prj_nm == "augdat" &&
get_fam_long(args_prj[[tstsetup]]$fam_nm) %in% fams_neg_linpred()) {
pred_plo_no_offs <- pred_plo_no_offs + dat_offs_new$offs_col_new
} else {
pred_plo_no_offs <- pred_plo_no_offs - dat_offs_new$offs_col_new
}
expect_equal(pred_plo_no_offs, t(pred_pl_orig), info = tstsetup)
expect_false(isTRUE(all.equal(pl$lpd, pl_orig$lpd)), info = tstsetup)
expect_false(isTRUE(all.equal(plo$lpd, pl_orig$lpd)), info = tstsetup)
expect_false(isTRUE(all.equal(plo$lpd, pl$lpd)), info = tstsetup)
} else if (args_prj[[tstsetup]]$pkg_nm == "brms") {
expect_equal(pl, pl_orig, info = tstsetup)
expect_equal(plo, pl_orig, info = tstsetup)
}
}
}
})
## transform --------------------------------------------------------------
test_that("`transform` works", {
skip_if_not(run_prj)
for (tstsetup in names(prjs)) {
ndr_ncl <- ndr_ncl_dtls(args_prj[[tstsetup]])
if (!has_const_wdr_prj(prjs[[tstsetup]])) {
wdr_crr <- prjs[[tstsetup]][["wdraws_prj"]]
} else {
wdr_crr <- NULL
}
if (!is.null(refmods[[args_prj[[tstsetup]]$tstsetup_ref]]$family$cats)) {
ncats_nlats_expected_crr <- length(
refmods[[args_prj[[tstsetup]]$tstsetup_ref]]$family$cats
)
} else {
ncats_nlats_expected_crr <- integer()
}
pl_false <- pls[[tstsetup]]
pl_true <- proj_linpred(prjs[[tstsetup]], transform = TRUE,
allow_nonconst_wdraws_prj = ndr_ncl$clust_used_gt1,
.seed = seed2_tst)
pl_tester(pl_true,
nprjdraws_expected = ndr_ncl$nprjdraws,
wdraws_prj_expected = wdr_crr,
ncats_nlats_expected = list(ncats_nlats_expected_crr),
info_str = tstsetup)
pred_false <- pl_false$pred
if (args_prj[[tstsetup]]$prj_nm == "augdat") {
pred_false <- arr2augmat(pred_false, margin_draws = 1)
} else {
pred_false <- t(pred_false)
}
pred_true <- pl_true$pred
if (args_prj[[tstsetup]]$prj_nm == "augdat") {
pred_true <- arr2augmat(pred_true, margin_draws = 1)
} else if (args_prj[[tstsetup]]$prj_nm != "latent") {
pred_true <- t(pred_true)
}
if (args_prj[[tstsetup]]$prj_nm != "latent") {
pred_false2true <- prjs[[tstsetup]]$refmodel$family$linkinv(pred_false)
} else {
if (exists(".Random.seed", envir = .GlobalEnv)) {
rng_old <- get(".Random.seed", envir = .GlobalEnv)
}
set.seed(args_prj[[tstsetup]]$seed)
clust_ref <- get_refdist(prjs[[tstsetup]]$refmodel,
ndraws = args_prj[[tstsetup]]$ndraws,
nclusters = args_prj[[tstsetup]]$nclusters)
pred_false2true <- structure(
prjs[[tstsetup]]$refmodel$family$latent_ilink(
t(pred_false), cl_ref = clust_ref$cl
),
wdraws_prj = wdr_crr
)
}
expect_equal(pred_false2true, pred_true, info = tstsetup)
if (exists("rng_old")) assign(".Random.seed", rng_old, envir = .GlobalEnv)
}
})
## regul ------------------------------------------------------------------
test_that("`regul` works", {
skip_if_not(run_prj)
regul_tst <- c(1e-6, 1e-1, 1e2)
stopifnot(identical(regul_tst, sort(regul_tst)))
tstsetups <- grep("\\.glm\\..*\\.prd_trms_x\\.clust$", names(prjs),
value = TRUE)
tstsetups <- grep(fam_nms_aug_regex, tstsetups, value = TRUE, invert = TRUE)
for (tstsetup in tstsetups) {
args_prj_i <- args_prj[[tstsetup]]
if (args_prj_i$prj_nm == "augdat") {
ncats_nlats_expected_crr <- length(
refmods[[args_prj_i$tstsetup_ref]]$family$cats
) - 1L
} else {
ncats_nlats_expected_crr <- integer()
}
norms <- sapply(regul_tst, function(regul_crr) {
pl <- do.call(proj_linpred, c(
list(object = refmods[[args_prj_i$tstsetup_ref]],
integrated = TRUE,
.seed = seed2_tst,
regul = regul_crr),
excl_nonargs(args_prj_i)
))
pl_tester(pl,
nprjdraws_expected = 1L,
ncats_nlats_expected = list(ncats_nlats_expected_crr),
info_str = tstsetup)
return(sum(pl$pred^2))
})
for (j in head(seq_along(regul_tst), -1)) {
expect_true(all(norms[!!j] >= norms[!!(j + 1)]), info = tstsetup)
}
}
})
## filter_nterms ----------------------------------------------------------
test_that("`filter_nterms` works (for an `object` of class `projection`)", {
skip_if_not(run_prj)
tstsetups <- grep("\\.brnll\\..*\\.prd_trms_x\\.clust$", names(prjs),
value = TRUE)
for (tstsetup in tstsetups) {
nterms_avail_crr <- length(args_prj[[tstsetup]]$predictor_terms)
nterms_unavail_crr <- c(0L, nterms_avail_crr + 130L)
stopifnot(!nterms_avail_crr %in% nterms_unavail_crr)
for (filter_nterms_crr in nterms_unavail_crr) {
expect_error(proj_linpred(prjs[[tstsetup]],
filter_nterms = filter_nterms_crr,
allow_nonconst_wdraws_prj = TRUE,
.seed = seed2_tst),
"Invalid `filter_nterms`\\.",
info = paste(tstsetup, filter_nterms_crr, sep = "__"))
}
pl <- proj_linpred(prjs[[tstsetup]],
filter_nterms = nterms_avail_crr,
allow_nonconst_wdraws_prj = TRUE,
.seed = seed2_tst)
pl_orig <- pls[[tstsetup]]
expect_equal(pl, pl_orig, info = tstsetup)
}
})
test_that(paste(
"`filter_nterms` works (for an `object` of (informal) class `proj_list`)"
), {
skip_if_not(run_vs)
tstsetups <- grep("\\.glm\\..*\\.full$", names(prjs_vs), value = TRUE)
if (any(grepl("\\.L1\\.", tstsetups))) {
tstsetups <- grep("\\.L1\\.", tstsetups, value = TRUE)
}
for (tstsetup in tstsetups) {
ndr_ncl <- ndr_ncl_dtls(args_prj_vs[[tstsetup]])
if (!has_const_wdr_prj(prjs_vs[[tstsetup]])) {
wdr_crr <- prjs_vs[[tstsetup]][[1]][["wdraws_prj"]]
} else {
wdr_crr <- NULL
}
if (args_prj_vs[[tstsetup]]$prj_nm == "augdat") {
ncats_nlats_expected_crr <- length(
refmods[[args_prj_vs[[tstsetup]]$tstsetup_ref]]$family$cats
) - 1L
} else {
ncats_nlats_expected_crr <- integer()
}
# Unavailable number(s) of terms:
for (filter_nterms_crr in nterms_unavail) {
expect_error(
proj_linpred(prjs_vs[[tstsetup]],
filter_nterms = filter_nterms_crr,
allow_nonconst_wdraws_prj = ndr_ncl$clust_used_gt1,
.seed = seed2_tst),
"Invalid `filter_nterms`\\.",
info = paste(tstsetup,
paste(filter_nterms_crr, collapse = ","),
sep = "__")
)
}
# Available number(s) of terms:
nterms_avail_filter <- c(
nterms_avail,
list(partvec = c(nterms_max_tst %/% 2L, nterms_max_tst + 130L))
)
for (filter_nterms_crr in nterms_avail_filter) {
pl_crr <- proj_linpred(prjs_vs[[tstsetup]],
filter_nterms = filter_nterms_crr,
allow_nonconst_wdraws_prj = ndr_ncl$clust_used_gt1,
.seed = seed2_tst)
if (is.null(filter_nterms_crr)) filter_nterms_crr <- 0:nterms_max_tst
nhits_nterms <- sum(filter_nterms_crr <= nterms_max_tst)
pl_tester(pl_crr,
len_expected = nhits_nterms,
wdraws_prj_expected = wdr_crr,
ncats_nlats_expected = replicate(nhits_nterms,
ncats_nlats_expected_crr,
simplify = FALSE),
info_str = paste(tstsetup,
paste(filter_nterms_crr, collapse = ","),
sep = "__"))
if (identical(filter_nterms_crr, 0:nterms_max_tst)) {
# The special case of all possible numbers of terms:
pl_orig <- pls_vs[[tstsetup]]
expect_equal(pl_crr, pl_orig, info = tstsetup)
}
}
}
})
## Single observation, single draw ----------------------------------------
test_that(paste(
"a single observation and a single draw work (which implicitly tests",
"this edge case for family$ll_fun(), too)"
), {
skip_if_not(run_prj)
for (tstsetup in grep("\\.clust$", names(prjs), value = TRUE)) {
if (args_prj[[tstsetup]]$mod_nm == "gamm") {
# TODO (GAMMs): Fix this.
next
}
if (grepl("\\.with_wobs|\\.binom", tstsetup)) {
wobs_crr <- head(wobs_tst, 1)
} else {
wobs_crr <- NULL
}
if (grepl("\\.with_offs", tstsetup)) {
offs_crr <- head(offs_tst, 1)
} else {
offs_crr <- NULL
}
if (args_prj[[tstsetup]]$prj_nm == "augdat") {
ncats_nlats_expected_crr <- length(
refmods[[args_prj[[tstsetup]]$tstsetup_ref]]$family$cats
) - 1L
} else {
ncats_nlats_expected_crr <- integer()
}
pl_args <- list(refmods[[args_prj[[tstsetup]]$tstsetup_ref]],
newdata = head(get_dat(tstsetup), 1),
weightsnew = wobs_crr,
offsetnew = offs_crr,
.seed = seed2_tst,
predictor_terms = args_prj[[tstsetup]]$predictor_terms,
nclusters = 1L,
seed = seed_tst)
if (args_prj[[tstsetup]]$fam_nm == "categ" &&
any(grepl("\\|", args_prj[[tstsetup]]$predictor_terms))) {
pl_args <- c(pl_args, list(avoid.increase = TRUE))
}
# Use suppressWarnings() because test_that() somehow redirects stderr() and
# so throws warnings that projpred wants to capture internally:
pl1 <- suppressWarnings(do.call(proj_linpred, pl_args))
pl_tester(pl1,
nprjdraws_expected = 1L,
nobsv_expected = 1L,
ncats_nlats_expected = list(ncats_nlats_expected_crr),
info_str = tstsetup)
}
})
## Projected draws with different weights ---------------------------------
test_that("`allow_nonconst_wdraws_prj = FALSE` causes an error", {
skip_if_not(run_prj)
for (tstsetup in grep("\\.clust", names(prjs), value = TRUE)) {
if (grepl("\\.clust1", tstsetup)) {
err_expected <- NA
} else {
err_expected <- "different .* weights"
}
expect_error(proj_linpred(prjs[[tstsetup]], .seed = seed2_tst),
err_expected, info = tstsetup)
}
})
test_that(paste(
"`return_draws_matrix` causes a conversion of the output type,",
"with different weights of the projected draws causing the application of",
"posterior::weight_draws()"
), {
skip_if_not(run_prj)
skip_if_not_installed("posterior")
for (tstsetup in names(prjs)) {
ndr_ncl <- ndr_ncl_dtls(args_prj[[tstsetup]])
for (transf_crr in c(FALSE, TRUE)) {
for (intgr_crr in c(FALSE, TRUE)) {
if (!transf_crr && !intgr_crr) {
pl_orig <- pls[[tstsetup]]
} else {
pl_orig <- proj_linpred(
prjs[[tstsetup]], transform = transf_crr, integrated = intgr_crr,
allow_nonconst_wdraws_prj = ndr_ncl$clust_used_gt1,
.seed = seed2_tst
)
}
pl_dr <- proj_linpred(
prjs[[tstsetup]], transform = transf_crr, integrated = intgr_crr,
return_draws_matrix = TRUE, .seed = seed2_tst
)
if (args_prj[[tstsetup]]$prj_nm == "augdat" ||
(args_prj[[tstsetup]]$prj_nm == "latent" && !is.null(
refmods[[args_prj[[tstsetup]]$tstsetup_ref]]$family$cats
) && transf_crr)) {
pl_orig_pred <- do.call(rbind, apply(pl_orig$pred, 1, as.vector,
simplify = FALSE))
} else {
pl_orig_pred <- pl_orig$pred
}
pl_dr_repl <- list(
pred = posterior::as_draws_matrix(pl_orig_pred),
lpd = posterior::as_draws_matrix(pl_orig$lpd)
)
if (!has_const_wdr_prj(prjs[[tstsetup]]) && !intgr_crr) {
pl_dr_repl$pred <- posterior::weight_draws(
pl_dr_repl$pred, weights = prjs[[tstsetup]][["wdraws_prj"]]
)
pl_dr_repl$lpd <- posterior::weight_draws(
pl_dr_repl$lpd, weights = prjs[[tstsetup]][["wdraws_prj"]]
)
}
expect_equal(pl_dr, pl_dr_repl,
info = paste(tstsetup, transf_crr, intgr_crr, sep = "__"))
}
}
}
})
# proj_predict() ----------------------------------------------------------
context("proj_predict()")
## seed -------------------------------------------------------------------
test_that("`.seed` works (and restores the RNG state afterwards)", {
skip_if_not(run_prj)
for (tstsetup in names(prjs)) {
pp_orig <- pps[[tstsetup]]
rand_orig <- runif(1) # Just to advance `.Random.seed[2]`.
.Random.seed_new1 <- .Random.seed
pp_new <- proj_predict(prjs[[tstsetup]], .seed = seed2_tst + 1L)
.Random.seed_new2 <- .Random.seed
rand_new <- runif(1) # Just to advance `.Random.seed[2]`.
.Random.seed_repr1 <- .Random.seed
pp_repr <- proj_predict(prjs[[tstsetup]], .seed = seed2_tst)
.Random.seed_repr2 <- .Random.seed
rand_repr <- runif(1) # Just to advance `.Random.seed[2]`.
.Random.seed_null1 <- .Random.seed
expect_equal(pp_orig, pp_repr, info = tstsetup)
if (!args_prj[[tstsetup]]$fam_nm %in% c("brnll")) {
# The Bernoulli family is excluded because two possible response values
# are too few to reliably check non-equality:
expect_false(isTRUE(all.equal(pp_orig, pp_new)), info = tstsetup)
}
expect_equal(.Random.seed_new2, .Random.seed_new1, info = tstsetup)
expect_equal(.Random.seed_repr2, .Random.seed_repr1, info = tstsetup)
expect_false(isTRUE(all.equal(rand_new, rand_orig)), info = tstsetup)
expect_false(isTRUE(all.equal(rand_repr, rand_orig)), info = tstsetup)
expect_false(isTRUE(all.equal(rand_repr, rand_new)), info = tstsetup)
}
})
## object -----------------------------------------------------------------
test_that("pp: `object` of class `projection` works", {
skip_if_not(run_prj)
for (tstsetup in names(prjs)) {
pp_tester(pps[[tstsetup]],
nprjdraws_out_expected = ndr_pp_out(args_prj[[tstsetup]],
prj_out = prjs[[tstsetup]]),
cats_expected =
list(refmods[[args_prj[[tstsetup]]$tstsetup_ref]]$family$cats),
info_str = tstsetup)
if (run_snaps) {
if (testthat_ed_max2) local_edition(3)
width_orig <- options(width = 145)
expect_snapshot({
print(tstsetup)
print(rlang::hash(pps[[tstsetup]]))
})
options(width_orig)
if (testthat_ed_max2) local_edition(2)
}
}
})
test_that(paste(
"pp: `object` of (informal) class `proj_list` (based on varsel()) works"
), {
skip_if_not(run_vs)
for (tstsetup in names(prjs_vs)) {
tstsetup_vs <- args_prj_vs[[tstsetup]]$tstsetup_vsel
nterms_crr <- args_prj_vs[[tstsetup]]$nterms
if (is.null(nterms_crr)) {
nterms_crr <- suggest_size(vss[[tstsetup_vs]], warnings = FALSE)
}
pp_tester(pps_vs[[tstsetup]],
len_expected = length(nterms_crr),
nprjdraws_out_expected = ndr_pp_out(
args_prj_vs[[tstsetup]], prj_out = prjs_vs[[tstsetup]]
),
cats_expected = replicate(
length(nterms_crr),
refmods[[args_prj_vs[[tstsetup]]$tstsetup_ref]]$family$cats,
simplify = FALSE
),
info_str = tstsetup)
if (run_snaps) {
if (testthat_ed_max2) local_edition(3)
width_orig <- options(width = 145)
expect_snapshot({
print(tstsetup)
print(rlang::hash(pps_vs[[tstsetup]]))
})
options(width_orig)
if (testthat_ed_max2) local_edition(2)
}
}
})
test_that(paste(
"pp: `object` of (informal) class `proj_list` (based on cv_varsel()) works"
), {
skip_if_not(run_cvvs)
for (tstsetup in names(prjs_cvvs)) {
tstsetup_cvvs <- args_prj_cvvs[[tstsetup]]$tstsetup_vsel
nterms_crr <- args_prj_cvvs[[tstsetup]]$nterms
if (is.null(nterms_crr)) {
nterms_crr <- suggest_size(cvvss[[tstsetup_cvvs]], warnings = FALSE)
}
pp_tester(pps_cvvs[[tstsetup]],
len_expected = length(nterms_crr),
nprjdraws_out_expected = ndr_pp_out(
args_prj_cvvs[[tstsetup]], prj_out = prjs_cvvs[[tstsetup]]
),
cats_expected = replicate(
length(nterms_crr),
refmods[[args_prj_cvvs[[tstsetup]]$tstsetup_ref]]$family$cats,
simplify = FALSE
),
info_str = tstsetup)
if (run_snaps) {
if (testthat_ed_max2) local_edition(3)
width_orig <- options(width = 145)
expect_snapshot({
print(tstsetup)
print(rlang::hash(pps_cvvs[[tstsetup]]))
})
options(width_orig)
if (testthat_ed_max2) local_edition(2)
}
}
})
test_that(paste(
"`object` of (informal) class `proj_list` (created manually) works"
), {
skip_if_not(run_prj)
tstsetups <- grep("\\.trad\\..*\\.clust$", names(prjs), value = TRUE)
stopifnot(length(tstsetups) > 1)
pp <- proj_predict(prjs[tstsetups], .seed = seed2_tst)
pp_tester(pp,
len_expected = length(tstsetups),
cats_expected = lapply(
refmods[sapply(args_prj[tstsetups], "[[", "tstsetup_ref")],
function(refmod_crr) {
refmod_crr$family$cats
}
),
info_str = paste(tstsetups, collapse = ","))
})
test_that(paste(
"`object` of class `refmodel` and passing arguments to project() works"
), {
skip_if_not(run_prj)
tstsetups <- grep("\\.brnll\\..*\\.prd_trms_x\\.clust$", names(prjs),
value = TRUE)
for (tstsetup in tstsetups) {
args_prj_i <- args_prj[[tstsetup]]
pp_from_refmod <- do.call(proj_predict, c(
list(object = refmods[[args_prj_i$tstsetup_ref]],
.seed = seed2_tst),
excl_nonargs(args_prj_i)
))
pp_from_prj <- pps[[tstsetup]]
expect_equal(pp_from_refmod, pp_from_prj, info = tstsetup)
}
})
test_that(paste(
"`object` of class `stanreg` or `brmsfit` and passing arguments to",
"project() works"
), {
skip_if_not(run_prj)
tstsetups <- grep("\\.brnll\\..*\\.prd_trms_x\\.clust$", names(prjs),
value = TRUE)
for (tstsetup in tstsetups) {
args_prj_i <- args_prj[[tstsetup]]
pp_from_fit <- do.call(proj_predict, c(
list(object = fits[[args_prj_i$tstsetup_fit]],
.seed = seed2_tst),
excl_nonargs(args_ref[[args_prj_i$tstsetup_ref]]),
excl_nonargs(args_prj_i)
))
pp_from_prj <- pps[[tstsetup]]
expect_equal(pp_from_fit, pp_from_prj, info = tstsetup)
}
})
test_that(paste(
"`object` of class `vsel` (created by varsel()) and passing arguments",
"to project() works"
), {
skip_if_not(run_vs)
tstsetups <- grep("\\.brnll\\..*\\.subvec", names(prjs_vs), value = TRUE)
if (any(grepl("\\.L1\\.", tstsetups))) {
tstsetups <- grep("\\.L1\\.", tstsetups, value = TRUE)
}
stopifnot(length(tstsetups) > 0)
for (tstsetup in tstsetups) {
args_prj_vs_i <- args_prj_vs[[tstsetup]]
pp_from_vsel <- do.call(proj_predict, c(
list(object = vss[[args_prj_vs_i$tstsetup_vsel]],
.seed = seed2_tst),
excl_nonargs(args_prj_vs_i)
))
pp_from_prj <- pps_vs[[tstsetup]]
expect_equal(pp_from_vsel, pp_from_prj, info = tstsetup)
}
})
test_that(paste(
"`object` of class `vsel` (created by cv_varsel()) and passing arguments",
"to project() works"
), {
skip_if_not(run_cvvs)
tstsetups <- grep("\\.brnll\\..*\\.default_cvmeth\\..*\\.subvec",
names(prjs_cvvs), value = TRUE)
if (any(grepl("\\.L1\\.", tstsetups))) {
tstsetups <- grep("\\.L1\\.", tstsetups, value = TRUE)
}
if (length(tstsetups) == 0) {
tstsetups <- grep("\\.glm\\.gauss.*\\.default_cvmeth\\..*\\.subvec",
names(prjs_cvvs), value = TRUE)
if (any(grepl("\\.L1\\.", tstsetups))) {
tstsetups <- grep("\\.L1\\.", tstsetups, value = TRUE)
}
tstsetups <- head(tstsetups, 1)
}
stopifnot(length(tstsetups) > 0)
for (tstsetup in tstsetups) {
args_prj_cvvs_i <- args_prj_cvvs[[tstsetup]]
pp_from_vsel <- do.call(proj_predict, c(
list(object = cvvss[[args_prj_cvvs_i$tstsetup_vsel]],
.seed = seed2_tst),
excl_nonargs(args_prj_cvvs_i)
))
pp_from_prj <- pps_cvvs[[tstsetup]]
expect_equal(pp_from_vsel, pp_from_prj, info = tstsetup)
}
})
test_that("`object` not of class `vsel` and missing `predictor_terms` fails", {
expect_error(
proj_predict(1, .seed = seed2_tst),
paste("^Please provide an `object` of class `vsel` or use argument",
"`predictor_terms`\\.$")
)
if (length(fits)) {
expect_error(
proj_predict(fits[[1]], .seed = seed2_tst),
paste("^Please provide an `object` of class `vsel` or use argument",
"`predictor_terms`\\.$")
)
expect_error(
proj_predict(refmods[[1]], .seed = seed2_tst),
paste("^Please provide an `object` of class `vsel` or use argument",
"`predictor_terms`\\.$")
)
}
if (run_prj) {
expect_error(
proj_predict(c(prjs, list(dat)), .seed = seed2_tst),
paste("Please provide an `object` of class `vsel` or use argument",
"`predictor_terms`\\.")
)
}
})
## newdata and nresample_clusters -----------------------------------------
test_that("invalid `newdata` fails", {
skip_if_not(run_prj)
expect_error(
proj_predict(prjs, newdata = dat[, 1], .seed = seed2_tst),
"must be a data\\.frame or a matrix"
)
stopifnot(length(prd_trms_x) > 1)
prj_crr <- prjs[[head(grep("\\.glm\\.gauss.*\\.prd_trms_x", names(prjs)), 1)]]
expect_error(
proj_predict(prjs[[head(grep("\\.glm\\.gauss.*\\.prd_trms_x", names(prjs)),
1)]],
newdata = dat[, head(prd_trms_x, -1), drop = FALSE],
weightsnew = prj_crr$refmodel$wobs,
offsetnew = prj_crr$refmodel$offset,
.seed = seed2_tst,
predictor_terms = prd_trms_x),
"^object '.*' not found$"
)
})
test_that("`newdata` and `nresample_clusters` work (even in edge cases)", {
skip_if_not(run_prj)
for (tstsetup in names(prjs)) {
for (nobsv_crr in nobsv_tst) {
if (args_prj[[tstsetup]]$mod_nm == "gamm") {
# TODO (GAMMs): Fix this.
next
}
if (grepl("\\.with_wobs|\\.binom", tstsetup)) {
wobs_crr <- head(prjs[[tstsetup]]$refmodel$wobs, nobsv_crr)
} else {
wobs_crr <- NULL
}
if (grepl("\\.with_offs", tstsetup)) {
offs_crr <- head(prjs[[tstsetup]]$refmodel$offset, nobsv_crr)
} else {
offs_crr <- NULL
}
for (nresample_clusters_crr in nresample_clusters_tst) {
expect_warning(
pp <- proj_predict(prjs[[tstsetup]],
newdata = head(dat, nobsv_crr),
weightsnew = wobs_crr,
offsetnew = offs_crr,
nresample_clusters = nresample_clusters_crr,
.seed = seed2_tst),
get_warn_wrhs_orhs(tstsetup, weightsnew = wobs_crr,
offsetnew = offs_crr),
info = tstsetup
)
pp_tester(pp,
nprjdraws_out_expected = ndr_pp_out(
args_prj[[tstsetup]], prj_out = prjs[[tstsetup]],
nresample_clusters_crr = nresample_clusters_crr
),
nobsv_expected = nobsv_crr,
cats_expected = list(
refmods[[args_prj[[tstsetup]]$tstsetup_ref]]$family$cats
),
info_str = paste(tstsetup, nobsv_crr, nresample_clusters_crr,
sep = "__"))
}
}
}
})
test_that("`newdata` set to the original dataset doesn't change results", {
skip_if_not(run_prj)
for (tstsetup in names(prjs)) {
if (grepl("\\.with_wobs|\\.binom", tstsetup)) {
wobs_crr <- wobs_tst
} else {
wobs_crr <- NULL
}
if (grepl("\\.with_offs", tstsetup)) {
offs_crr <- offs_tst
} else {
offs_crr <- NULL
}
expect_warning(
pp_newdata <- proj_predict(prjs[[tstsetup]],
newdata = dat,
weightsnew = wobs_crr,
offsetnew = offs_crr,
.seed = seed2_tst),
get_warn_wrhs_orhs(tstsetup, weightsnew = wobs_crr,
offsetnew = offs_crr),
info = tstsetup
)
pp_orig <- pps[[tstsetup]]
expect_equal(pp_newdata, pp_orig, info = tstsetup)
}
})
test_that(paste(
"omitting the response in `newdata` (not possible for ``brmsfit``-based",
"reference models) doesn't change results"
), {
skip_if_not(run_prj)
for (tstsetup in names(prjs)) {
if (args_prj[[tstsetup]]$pkg_nm == "brms") {
next
}
if (grepl("\\.with_wobs|\\.binom", tstsetup)) {
wobs_crr <- wobs_tst
} else {
wobs_crr <- NULL
}
if (grepl("\\.with_offs", tstsetup)) {
offs_crr <- offs_tst
} else {
offs_crr <- NULL
}
resp_nm <- extract_terms_response(
prjs[[tstsetup]]$refmodel$formula
)$response
stopifnot(!exists(resp_nm))
pp_noresp <- proj_predict(prjs[[tstsetup]],
newdata = dat[, setdiff(names(dat), resp_nm)],
weightsnew = wobs_crr,
offsetnew = offs_crr,
.seed = seed2_tst)
pp_orig <- pps[[tstsetup]]
expect_equal(pp_noresp, pp_orig, info = tstsetup)
}
})
## weightsnew -------------------------------------------------------------
test_that("`weightsnew` works", {
skip_if_not(run_prj)
for (tstsetup in names(prjs)) {
nprjdraws_out_crr <- ndr_pp_out(args_prj[[tstsetup]],
prj_out = prjs[[tstsetup]])
if (grepl("\\.with_offs", tstsetup)) {
offs_crr <- offs_tst
} else {
offs_crr <- NULL
}
pp_orig <- pps[[tstsetup]]
expect_warning(
pp_ones <- proj_predict(prjs[[tstsetup]],
newdata = get_dat(tstsetup, dat_wobs_ones,
wobs_brms = 1),
weightsnew = ~ wobs_col_ones,
offsetnew = offs_crr,
.seed = seed2_tst),
get_warn_wrhs_orhs(tstsetup, weightsnew = ~ wobs_col_ones,
offsetnew = offs_crr),
info = tstsetup
)
pp_tester(pp_ones,
nprjdraws_out_expected = nprjdraws_out_crr,
cats_expected = list(
refmods[[args_prj[[tstsetup]]$tstsetup_ref]]$family$cats
),
info_str = tstsetup)
if (!args_prj[[tstsetup]]$prj_nm %in% c("latent", "augdat")) {
expect_warning(
pp <- proj_predict(prjs[[tstsetup]],
newdata = get_dat(tstsetup, dat,
wobs_brms = dat$wobs_col),
weightsnew = ~ wobs_col,
offsetnew = offs_crr,
.seed = seed2_tst),
get_warn_wrhs_orhs(tstsetup, weightsnew = ~ wobs_col,
offsetnew = offs_crr),
info = tstsetup
)
pp_tester(pp,
nprjdraws_out_expected = nprjdraws_out_crr,
cats_expected = list(
refmods[[args_prj[[tstsetup]]$tstsetup_ref]]$family$cats
),
info_str = tstsetup)
expect_warning(
ppw <- proj_predict(prjs[[tstsetup]],
newdata = get_dat(
tstsetup,
dat_wobs_new,
wobs_brms = dat_wobs_new$wobs_col_new
),
weightsnew = ~ wobs_col_new,
offsetnew = offs_crr,
.seed = seed2_tst),
get_warn_wrhs_orhs(tstsetup, weightsnew = ~ wobs_col_new,
offsetnew = offs_crr),
info = tstsetup
)
pp_tester(ppw,
nprjdraws_out_expected = nprjdraws_out_crr,
cats_expected = list(
refmods[[args_prj[[tstsetup]]$tstsetup_ref]]$family$cats
),
info_str = tstsetup)
}
# Weights are only relevant for the binomial() family:
if (!args_prj[[tstsetup]]$fam_nm %in% c("brnll", "binom")) {
expect_equal(pp_ones, pp_orig, info = tstsetup)
if (!args_prj[[tstsetup]]$prj_nm %in% c("latent", "augdat")) {
expect_equal(pp, pp_orig, info = tstsetup)
expect_equal(ppw, pp_orig, info = tstsetup)
}
} else if (args_prj[[tstsetup]]$fam_nm == "brnll") {
expect_equal(pp_ones, pp_orig, info = tstsetup)
if (!args_prj[[tstsetup]]$prj_nm %in% c("latent", "augdat")) {
if (args_prj[[tstsetup]]$pkg_nm == "rstanarm") {
expect_false(isTRUE(all.equal(pp, pp_orig)), info = tstsetup)
expect_false(isTRUE(all.equal(ppw, pp_orig)), info = tstsetup)
expect_false(isTRUE(all.equal(ppw, pp)), info = tstsetup)
} else if (args_prj[[tstsetup]]$pkg_nm == "brms") {
expect_equal(pp, pp_orig, info = tstsetup)
expect_equal(ppw, pp_orig, info = tstsetup)
}
}
} else if (args_prj[[tstsetup]]$fam_nm == "binom") {
expect_false(isTRUE(all.equal(pp_ones, pp_orig)), info = tstsetup)
if (!args_prj[[tstsetup]]$prj_nm %in% c("latent", "augdat")) {
expect_equal(pp, pp_orig, info = tstsetup)
expect_false(isTRUE(all.equal(ppw, pp_orig)), info = tstsetup)
expect_false(isTRUE(all.equal(ppw, pp_ones)), info = tstsetup)
}
}
}
})
## offsetnew --------------------------------------------------------------
test_that("`offsetnew` works", {
skip_if_not(run_prj)
for (tstsetup in names(prjs)) {
nprjdraws_out_crr <- ndr_pp_out(args_prj[[tstsetup]],
prj_out = prjs[[tstsetup]])
if (grepl("\\.with_wobs|\\.binom", tstsetup)) {
wobs_crr <- wobs_tst
} else {
wobs_crr <- NULL
}
pp_orig <- pps[[tstsetup]]
add_offs_crr <- args_prj[[tstsetup]]$prj_nm == "latent" &&
args_prj[[tstsetup]]$pkg_nm == "rstanarm" &&
grepl("\\.with_offs\\.", tstsetup)
expect_warning(
pp_zeros <- proj_predict(prjs[[tstsetup]],
newdata = get_dat(tstsetup, dat_offs_zeros,
add_offs_dummy = add_offs_crr,
offs_brms = 0),
weightsnew = wobs_crr,
offsetnew = ~ offs_col_zeros,
.seed = seed2_tst),
get_warn_wrhs_orhs(tstsetup, weightsnew = wobs_crr,
offsetnew = ~ offs_col_zeros),
info = tstsetup
)
pp_tester(pp_zeros,
nprjdraws_out_expected = nprjdraws_out_crr,
cats_expected = list(
refmods[[args_prj[[tstsetup]]$tstsetup_ref]]$family$cats
),
info_str = tstsetup)
expect_warning(
pp <- proj_predict(prjs[[tstsetup]],
newdata = dat,
weightsnew = wobs_crr,
offsetnew = ~ offs_col,
.seed = seed2_tst),
get_warn_wrhs_orhs(tstsetup, weightsnew = wobs_crr,
offsetnew = ~ offs_col),
info = tstsetup
)
pp_tester(pp,
nprjdraws_out_expected = nprjdraws_out_crr,
cats_expected = list(
refmods[[args_prj[[tstsetup]]$tstsetup_ref]]$family$cats
),
info_str = tstsetup)
expect_warning(
ppo <- proj_predict(prjs[[tstsetup]],
newdata = get_dat(
tstsetup, dat_offs_new,
offs_ylat = dat_offs_new$offs_col_new,
add_offs_dummy = add_offs_crr,
offs_brms = dat_offs_new$offs_col_new
),
weightsnew = wobs_crr,
offsetnew = ~ offs_col_new,
.seed = seed2_tst),
get_warn_wrhs_orhs(tstsetup, weightsnew = wobs_crr,
offsetnew = ~ offs_col_new),
info = tstsetup
)
pp_tester(ppo,
nprjdraws_out_expected = nprjdraws_out_crr,
cats_expected = list(
refmods[[args_prj[[tstsetup]]$tstsetup_ref]]$family$cats
),
info_str = tstsetup)
if (grepl("\\.with_offs", tstsetup)) {
expect_equal(pp, pp_orig, info = tstsetup)
expect_false(isTRUE(all.equal(pp_zeros, pp_orig)), info = tstsetup)
expect_false(isTRUE(all.equal(ppo, pp_orig)), info = tstsetup)
# For the gaussian() family, we can perform an easy check (because of
# the identity link):
if (args_prj[[tstsetup]]$fam_nm == "gauss") {
expect_equal(t(pp) - dat$offs_col, t(pp_zeros), info = tstsetup)
expect_equal(t(ppo) - dat_offs_new$offs_col_new, t(pp_zeros),
info = tstsetup)
}
} else {
if (args_prj[[tstsetup]]$pkg_nm == "rstanarm") {
expect_equal(pp_zeros, pp_orig, info = tstsetup)
expect_false(isTRUE(all.equal(pp, pp_orig)), info = tstsetup)
# For the gaussian() family, we can perform an easy check (because of
# the identity link):
if (args_prj[[tstsetup]]$fam_nm == "gauss") {
expect_equal(t(pp) - dat$offs_col, t(pp_orig), info = tstsetup)
expect_equal(t(ppo) - dat_offs_new$offs_col_new, t(pp_orig),
info = tstsetup)
} else {
expect_false(isTRUE(all.equal(ppo, pp_orig)), info = tstsetup)
expect_false(isTRUE(all.equal(ppo, pp)), info = tstsetup)
}
} else if (args_prj[[tstsetup]]$pkg_nm == "brms") {
expect_equal(pp, pp_orig, info = tstsetup)
}
}
}
})
## filter_nterms ----------------------------------------------------------
test_that("`filter_nterms` works (for an `object` of class `projection`)", {
skip_if_not(run_prj)
tstsetups <- grep("\\.brnll\\..*\\.prd_trms_x\\.clust$", names(prjs),
value = TRUE)
for (tstsetup in tstsetups) {
nterms_avail_crr <- length(args_prj[[tstsetup]]$predictor_terms)
nterms_unavail_crr <- c(0L, nterms_avail_crr + 130L)
stopifnot(!nterms_avail_crr %in% nterms_unavail_crr)
for (filter_nterms_crr in nterms_unavail_crr) {
expect_error(proj_predict(prjs[[tstsetup]],
filter_nterms = filter_nterms_crr,
.seed = seed2_tst),
"Invalid `filter_nterms`\\.",
info = paste(tstsetup, filter_nterms_crr, sep = "__"))
}
pp <- proj_predict(prjs[[tstsetup]],
filter_nterms = nterms_avail_crr,
.seed = seed2_tst)
pp_orig <- pps[[tstsetup]]
expect_equal(pp, pp_orig, info = tstsetup)
}
})
test_that(paste(
"`filter_nterms` works (for an `object` of (informal) class `proj_list`)"
), {
skip_if_not(run_vs)
tstsetups <- grep("\\.glm\\..*\\.full$", names(prjs_vs), value = TRUE)
if (any(grepl("\\.L1\\.", tstsetups))) {
tstsetups <- grep("\\.L1\\.", tstsetups, value = TRUE)
}
for (tstsetup in tstsetups) {
# Unavailable number(s) of terms:
for (filter_nterms_crr in nterms_unavail) {
expect_error(proj_predict(prjs_vs[[tstsetup]],
filter_nterms = filter_nterms_crr,
.seed = seed2_tst),
"Invalid `filter_nterms`\\.",
info = paste(tstsetup,
paste(filter_nterms_crr, collapse = ","),
sep = "__"))
}
# Available number(s) of terms:
nterms_avail_filter <- c(
nterms_avail,
list(partvec = c(nterms_max_tst %/% 2L, nterms_max_tst + 130L))
)
for (filter_nterms_crr in nterms_avail_filter) {
pp_crr <- proj_predict(prjs_vs[[tstsetup]],
filter_nterms = filter_nterms_crr,
.seed = seed2_tst)
if (is.null(filter_nterms_crr)) filter_nterms_crr <- 0:nterms_max_tst
nhits_nterms <- sum(filter_nterms_crr <= nterms_max_tst)
pp_tester(pp_crr,
len_expected = nhits_nterms,
cats_expected = replicate(
nhits_nterms,
refmods[[args_prj_vs[[tstsetup]]$tstsetup_ref]]$family$cats,
simplify = FALSE
),
info_str = paste(tstsetup,
paste(filter_nterms_crr, collapse = ","),
sep = "__"))
if (identical(filter_nterms_crr, 0:nterms_max_tst)) {
# The special case of all possible numbers of terms:
pp_orig <- pps_vs[[tstsetup]]
expect_equal(pp_crr, pp_orig, info = tstsetup)
}
}
}
})
## Single observation, single draw ----------------------------------------
test_that(paste(
"a single observation and a single draw work (which implicitly tests",
"this edge case for family$ppd(), too)"
), {
skip_if_not(run_prj)
for (tstsetup in grep("\\.clust$", names(prjs), value = TRUE)) {
if (args_prj[[tstsetup]]$mod_nm == "gamm") {
# TODO (GAMMs): Fix this.
next
}
if (grepl("\\.with_wobs|\\.binom", tstsetup)) {
wobs_crr <- head(wobs_tst, 1)
} else {
wobs_crr <- NULL
}
if (grepl("\\.with_offs", tstsetup)) {
offs_crr <- head(offs_tst, 1)
} else {
offs_crr <- NULL
}
pp_args <- list(refmods[[args_prj[[tstsetup]]$tstsetup_ref]],
newdata = head(get_dat(tstsetup), 1),
weightsnew = wobs_crr,
offsetnew = offs_crr,
nresample_clusters = 1L,
.seed = seed2_tst,
predictor_terms = args_prj[[tstsetup]]$predictor_terms,
nclusters = 1L,
seed = seed_tst)
if (args_prj[[tstsetup]]$fam_nm == "categ" &&
any(grepl("\\|", args_prj[[tstsetup]]$predictor_terms))) {
pp_args <- c(pp_args, list(avoid.increase = TRUE))
}
# Use suppressWarnings() because test_that() somehow redirects stderr() and
# so throws warnings that projpred wants to capture internally:
pp1 <- suppressWarnings(do.call(proj_predict, pp_args))
pp_tester(pp1,
nprjdraws_out_expected = 1L,
nobsv_expected = 1L,
cats_expected = list(
refmods[[args_prj[[tstsetup]]$tstsetup_ref]]$family$cats
),
info_str = tstsetup)
}
})
## Projected draws with different weights ---------------------------------
test_that("`return_draws_matrix` causes a conversion of the output type", {
skip_if_not(run_prj)
skip_if_not_installed("posterior")
for (tstsetup in names(prjs)) {
for (r_oscale_crr in c(FALSE, TRUE)) {
if (!r_oscale_crr && args_prj[[tstsetup]]$prj_nm != "latent") next
if (r_oscale_crr) {
pp_orig <- pps[[tstsetup]]
} else {
pp_orig <- proj_predict(
prjs[[tstsetup]], resp_oscale = r_oscale_crr, .seed = seed2_tst
)
}
pp_dr <- proj_predict(
prjs[[tstsetup]], resp_oscale = r_oscale_crr,
return_draws_matrix = TRUE, .seed = seed2_tst
)
pp_dr_repl <- posterior::as_draws_matrix(pp_orig)
expect_equal(pp_dr, pp_dr_repl,
info = paste(tstsetup, r_oscale_crr, sep = "__"))
}
}
})
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.