testthat::context('logregbin') testthat::test_that('All options in the logRegBin work (sunny)', { suppressWarnings(RNGversion("3.5.0")) set.seed(1337) N <- 100 cov1 <- rnorm(N) cov2 <- rnorm(N) z <- 1 + 2*cov1 + 3*cov2 pr <- 1 / ( 1 + exp(-z)) dep <- factor(rbinom(N, 1, pr)) df <- data.frame( `dep 1`=dep, `cov 1`=cov1, `cov 2`=cov2, check.names = FALSE ) r <- jmv::logRegBin( data = df, dep = "dep 1", covs = c("cov 1", "cov 2"), blocks = list(list("cov 1", "cov 2")), refLevels = list(list(var="dep 1", ref="0")), modelTest = TRUE, bic = TRUE, pseudoR2 = c("r2mf", "r2cs", "r2n", "r2t"), omni = TRUE, ci = TRUE, OR = TRUE, ciOR = TRUE, class = TRUE, acc = TRUE, spec = TRUE, sens = TRUE, auc = TRUE, collin = TRUE, emMeans = ~`cov 1` + `cov 2`, emmPlots = FALSE, emmTables = TRUE ) # Test model fit table modelFitTable <- r$modelFit$asDF testthat::expect_equal(1, modelFitTable[['model']]) testthat::expect_equal(39.039, modelFitTable[['dev']], tolerance = 1e-3) testthat::expect_equal(45.039, modelFitTable[['aic']], tolerance = 1e-3) testthat::expect_equal(52.854, modelFitTable[['bic']], tolerance = 1e-3) testthat::expect_equal(0.701, modelFitTable[['r2mf']], tolerance = 1e-3) testthat::expect_equal(0.6, modelFitTable[['r2cs']], tolerance = 1e-3) testthat::expect_equal(0.823, modelFitTable[['r2n']], tolerance = 1e-3) testthat::expect_equal(0.733, modelFitTable[['r2t']], tolerance = 1e-3) testthat::expect_equal(91.645, modelFitTable[['chi']], tolerance = 1e-3) testthat::expect_equal(2, modelFitTable[['df']]) testthat::expect_equal(0, modelFitTable[['p']]) # Test omnibus likelihood ratio tests table lrtTable <- r$models[[1]]$lrt$asDF testthat::expect_equal(c('cov 1', 'cov 2'), lrtTable[['term']]) testthat::expect_equal(c(43.325, 72.433), lrtTable[['chi']], tolerance = 1e-3) testthat::expect_equal(c(1, 1), lrtTable[['df']]) testthat::expect_equal(c(0, 0), lrtTable[['p']], tolerance = 1e-3) # Test model coefficients table coefTable <- r$models[[1]]$coef$asDF testthat::expect_equal(c('Intercept', 'cov 1', 'cov 2'), coefTable[['term']]) testthat::expect_equal(c(0.926, 3.042, 4.929), coefTable[['est']], tolerance = 1e-3) testthat::expect_equal(c(0.022, 1.445, 2.643), coefTable[['lower']], tolerance = 1e-3) testthat::expect_equal(c(1.829, 4.639, 7.215), coefTable[['upper']], tolerance = 1e-3) testthat::expect_equal(c(0.461, 0.815, 1.166), coefTable[['se']], tolerance = 1e-3) testthat::expect_equal(c(2.008, 3.734, 4.226), coefTable[['z']], tolerance = 1e-3) testthat::expect_equal(c(0.045, 0, 0), coefTable[['p']], tolerance = 1e-3) testthat::expect_equal(c(2.524, 20.944, 138.297), coefTable[['odds']], tolerance = 1e-3) testthat::expect_equal(c(1.023, 4.242, 14.06), coefTable[['oddsLower']], tolerance = 1e-3) testthat::expect_equal(c(6.229, 103.41, 1360.308), coefTable[['oddsUpper']], tolerance = 1e-3) # Test collinearity table collinTable <- r$models[[1]]$assump$collin$asDF testthat::expect_equal(c('cov 1', 'cov 2'), collinTable[['term']]) testthat::expect_equal(c(2.331, 2.331), collinTable[['vif']], tolerance = 1e-3) testthat::expect_equal(c(0.429, 0.429), collinTable[['tol']], tolerance = 1e-3) # Test estimated marginal means table emmeansTable1 <- r$models[[1]]$emm[[1]]$emmTable$asDF testthat::expect_equal(c(-0.828, 0.237, 1.302), emmeansTable1[['cov 1']], tolerance = 1e-3) testthat::expect_equal(c(0.199, 0.864, 0.994), emmeansTable1[['prob']], tolerance = 1e-3) testthat::expect_equal(c(0.126, 0.062, 0.007), emmeansTable1[['se']], tolerance = 1e-3) testthat::expect_equal(c(0.05, 0.691, 0.939), emmeansTable1[['lower']], tolerance = 1e-3) testthat::expect_equal(c(0.539, 0.947, 0.999), emmeansTable1[['upper']], tolerance = 1e-3) emmeansTable2 <- r$models[[1]]$emm[[2]]$emmTable$asDF testthat::expect_equal(c(-0.965, 0.041, 1.048), emmeansTable2[['cov 2']], tolerance = 1e-3) testthat::expect_equal(c(0.043, 0.864, 0.999), emmeansTable2[['prob']], tolerance = 1e-3) testthat::expect_equal(c(0.038, 0.062, 0.002), emmeansTable2[['se']], tolerance = 1e-3) testthat::expect_equal(c(0.007, 0.691, 0.977), emmeansTable2[['lower']], tolerance = 1e-3) testthat::expect_equal(c(0.218, 0.947, 1), emmeansTable2[['upper']], tolerance = 1e-3) # Test classification table classTable <- r$models[[1]]$pred$class$asDF testthat::expect_equal('0', classTable[['name[0]']]) testthat::expect_equal(28, classTable[['neg[0]']]) testthat::expect_equal(8, classTable[['pos[0]']]) testthat::expect_equal(77.778, classTable[['perc[0]']], tolerance = 1e-3) testthat::expect_equal('1', classTable[['name[1]']]) testthat::expect_equal(5, classTable[['neg[1]']]) testthat::expect_equal(59, classTable[['pos[1]']]) testthat::expect_equal(92.188, classTable[['perc[1]']], tolerance = 1e-3) # Test predictive measures table measuresTable <- r$models[[1]]$pred$measures$asDF testthat::expect_equal(0.87, measuresTable[['accuracy']], tolerance = 1e-3) testthat::expect_equal(0.778, measuresTable[['spec']], tolerance = 1e-3) testthat::expect_equal(0.922, measuresTable[['sens']], tolerance = 1e-3) testthat::expect_equal(0.976, measuresTable[['auc']], tolerance = 1e-3) }) testthat::test_that('logregbin works with factors', { set.seed(1337) N <- 100 x <- sample(LETTERS[1:3], N, replace=TRUE) y <- sample(0:1, N, replace=TRUE) df <- data.frame(y=y, x=x) refLevels <- list(list(var="y", ref="0"), list(var="x", ref="A")) logReg <- jmv::logRegBin(data = df, dep = "y", factors = "x", blocks = list("x"), refLevels = refLevels) # Test coefficients table coef <- logReg$models[[1]]$coef$asDF testthat::expect_equal("x:", coef$term[2]) testthat::expect_equal("B – A", coef$term[3]) testthat::expect_equal("C – A", coef$term[4]) testthat::expect_equal(-0.0606, coef$est[1], tolerance = 1e-3) testthat::expect_equal(-0.0824, coef$est[3], tolerance = 1e-3) testthat::expect_equal(0.112, coef$est[4], tolerance = 1e-3) testthat::expect_equal(0.348, coef$se[1], tolerance = 1e-3) testthat::expect_equal(0.515, coef$se[3], tolerance = 1e-3) testthat::expect_equal(0.473, coef$se[4], tolerance = 1e-3) testthat::expect_equal(-0.174, coef$z[1], tolerance = 1e-3) testthat::expect_equal(-0.160, coef$z[3], tolerance = 1e-3) testthat::expect_equal(0.236, coef$z[4], tolerance = 1e-3) testthat::expect_equal(0.862, coef$p[1], tolerance = 1e-3) testthat::expect_equal(0.873, coef$p[3], tolerance = 1e-3) testthat::expect_equal(0.813, coef$p[4], tolerance = 1e-3) }) testthat::test_that('logregbin works with ordered factors', { suppressWarnings(RNGversion("3.5.0")) set.seed(1337) N <- 100 x <- factor(sample(LETTERS[1:3], N, replace=TRUE), ordered = TRUE) y <- factor(sample(0:1, N, replace=TRUE), ordered = TRUE) df <- data.frame(y=y, x=x) refLevels <- list(list(var="y", ref="0"), list(var="x", ref="A")) logReg <- jmv::logRegBin(data = df, dep = "y", factors = "x", blocks = list("x"), refLevels = refLevels) # Test coefficients table coef <- logReg$models[[1]]$coef$asDF testthat::expect_equal("x:", coef$term[2]) testthat::expect_equal("B – A", coef$term[3]) testthat::expect_equal("C – A", coef$term[4]) testthat::expect_equal(-0.0606, coef$est[1], tolerance = 1e-3) testthat::expect_equal(-0.0824, coef$est[3], tolerance = 1e-3) testthat::expect_equal(0.112, coef$est[4], tolerance = 1e-3) testthat::expect_equal(0.348, coef$se[1], tolerance = 1e-3) testthat::expect_equal(0.515, coef$se[3], tolerance = 1e-3) testthat::expect_equal(0.473, coef$se[4], tolerance = 1e-3) testthat::expect_equal(-0.174, coef$z[1], tolerance = 1e-3) testthat::expect_equal(-0.160, coef$z[3], tolerance = 1e-3) testthat::expect_equal(0.236, coef$z[4], tolerance = 1e-3) testthat::expect_equal(0.862, coef$p[1], tolerance = 1e-3) testthat::expect_equal(0.873, coef$p[3], tolerance = 1e-3) testthat::expect_equal(0.813, coef$p[4], tolerance = 1e-3) }) testthat::test_that('Emmeans work with nuisance parameters (no interactions)', { #' Test that nuisance factors are handled correctly in the estimated marginal means #' See: https://cran.r-project.org/web/packages/emmeans/vignettes/messy-data.html suppressWarnings(RNGversion("3.5.0")) set.seed(1337) df <- data.frame( dep = sample(0:1, 100, replace=TRUE), cov1 = rnorm(100), cov2 = rnorm(100), factor1 = sample(letters[1:3], 100, replace=TRUE), factor2 = sample(LETTERS[1:2], 100, replace=TRUE), stringsAsFactors = TRUE ) dep <- "dep" covs <- paste0("cov", 1:2) factors <- paste0("factor", 1:2) blocks = list(as.list(c(covs, factors))) refLevels = list( list(var="dep", ref="0"), list(var=factors[1], ref="a"), list(var=factors[2], ref="A") ) r <- jmv::logRegBin( df, dep = !!dep, covs = !!covs, factors = !!factors, blocks = blocks, refLevels = refLevels, emMeans = ~ cov1:cov2, emmPlots = FALSE, emmTables = TRUE ) # Test estimated marginal means emmeansTable <- r$models[[1]]$emm[[1]]$emmTable$asDF testthat::expect_equal( c(-1.149, -1.149, -1.149, -0.08, -0.08, -0.08, 0.988, 0.988, 0.988), emmeansTable[['cov2']], tolerance = 1e-3 ) testthat::expect_equal( c(-0.852, 0.116, 1.083, -0.852, 0.116, 1.083, -0.852, 0.116, 1.083), emmeansTable[['cov1']], tolerance = 1e-3 ) testthat::expect_equal( c(0.593, 0.59, 0.587, 0.549, 0.546, 0.543, 0.505, 0.502, 0.499), emmeansTable[['prob']], tolerance = 1e-3 ) testthat::expect_equal( c(0.089, 0.072, 0.088, 0.074, 0.051, 0.073, 0.09, 0.073, 0.091), emmeansTable[['se']], tolerance = 1e-3 ) testthat::expect_equal( c(0.414, 0.445, 0.411, 0.405, 0.446, 0.4, 0.335, 0.362, 0.328), emmeansTable[['lower']], tolerance = 1e-3 ) testthat::expect_equal( c(0.75, 0.721, 0.743, 0.686, 0.643, 0.68, 0.674, 0.641, 0.67), emmeansTable[['upper']] , tolerance = 1e-3 ) }) testthat::test_that('Emmeans work with nuisance parameters (with interactions)', { #' Test that nuisance factors are handled correctly in the estimated marginal means #' When a nuisance factor is included in an interaction it should still be included #' in the reference grid. #' See: https://cran.r-project.org/web/packages/emmeans/vignettes/messy-data.html suppressWarnings(RNGversion("3.5.0")) set.seed(1337) df <- data.frame( dep = sample(0:1, 100, replace=TRUE), cov1 = rnorm(100), cov2 = rnorm(100), factor1 = sample(letters[1:3], 100, replace=TRUE), factor2 = sample(LETTERS[1:2], 100, replace=TRUE), stringsAsFactors = TRUE ) dep <- "dep" covs <- c("cov1", "cov2") factors <- c("factor1", "factor2") blocks = list(list("cov1", "cov2", "factor1", "factor2", c("cov1", "factor1"))) refLevels = list( list(var="dep", ref="0"), list(var=factors[1], ref="a"), list(var=factors[2], ref="A") ) r <- jmv::linReg( df, dep = !!dep, covs = !!covs, factors = !!factors, blocks = blocks, refLevels = refLevels, emMeans = ~ cov1:cov2, emmPlots = FALSE, emmTables = TRUE ) # Test estimated marginal means emmeansTable <- r$models[[1]]$emm[[1]]$emmTable$asDF testthat::expect_equal( c(-1.149, -1.149, -1.149, -0.08, -0.08, -0.08, 0.988, 0.988, 0.988), emmeansTable[['cov2']], tolerance = 1e-3 ) testthat::expect_equal( c(-0.852, 0.116, 1.083, -0.852, 0.116, 1.083, -0.852, 0.116, 1.083), emmeansTable[['cov1']], tolerance = 1e-3 ) testthat::expect_equal( c(0.613, 0.589, 0.564, 0.567, 0.542, 0.518, 0.521, 0.496, 0.472), emmeansTable[['emmean']], tolerance = 1e-3 ) testthat::expect_equal( c(0.089, 0.071, 0.088, 0.073, 0.05, 0.074, 0.088, 0.072, 0.091), emmeansTable[['se']], tolerance = 1e-3 ) testthat::expect_equal( c(0.436, 0.447, 0.389, 0.423, 0.442, 0.372, 0.346, 0.352, 0.291), emmeansTable[['lower']], tolerance = 1e-3 ) testthat::expect_equal( c(0.791, 0.731, 0.74, 0.711, 0.643, 0.664, 0.696, 0.64, 0.652), emmeansTable[['upper']], tolerance = 1e-3 ) }) testthat::test_that("Analysis works with global weights", { suppressWarnings(RNGversion("3.5.0")) set.seed(1337) weights <- sample(1:10, 100, replace=TRUE) df <- data.frame( dep = factor(sample(0:1, 100, replace=TRUE)), cov = rnorm(100), factor = factor(sample(LETTERS[1:3], 100, replace=TRUE)) ) attr(df, "jmv-weights") <- weights refLevels = list(list(var="dep", ref="0"), list(var="factor", ref="A")) r <- jmv::logRegBin( df, dep="dep", covs="cov", factors="factor", blocks=list(list("cov", "factor")), refLevels=refLevels, ) # Test model fit table modelFitTable <- r$modelFit$asDF testthat::expect_equal(1, modelFitTable[['model']], tolerance = 1e-3) testthat::expect_equal(793.107, modelFitTable[['dev']], tolerance = 1e-3) testthat::expect_equal(801.107, modelFitTable[['aic']], tolerance = 1e-3) testthat::expect_equal(0.02, modelFitTable[['r2mf']], tolerance = 1e-3) # Test model coefficients table coefTable <- r$models[[1]]$coef$asDF testthat::expect_equal(c(-0.199, -0.251, NA, 0.457, 0.027), coefTable[['est']], tolerance = 1e-3) testthat::expect_equal(c(0.14, 0.085, NA, 0.201, 0.21), coefTable[['se']], tolerance = 1e-3) testthat::expect_equal(c(-1.418, -2.949, NA, 2.276, 0.128), coefTable[['z']], tolerance = 1e-3) testthat::expect_equal(c(0.156, 0.003, NA, 0.023, 0.899), coefTable[['p']], tolerance = 1e-3) }) testthat::test_that("Analysis adds note when design matrix is singular", { # GIVEN a singular data set suppressWarnings(RNGversion("3.5.0")) set.seed(1337) df <- data.frame( dep = rep(0:1, times=50), var1 = c(sample(letters[2:3], replace=TRUE, 50), rep(letters[1], 50)), var2 = c(sample(LETTERS[2:3], replace=TRUE, 50), rep(LETTERS[1], 50)) ) refLevels = list( list(var="dep", ref="0"), list(var="var1", ref=letters[1]), list(var="var2", ref=LETTERS[1]) ) # WHEN a binomial logistic regression is run on this data set r <- jmv::logRegBin( df, dep="dep", factors=c("var1", "var2"), blocks=list(list("var1", "var2")), refLevels=refLevels ) # THEN the coefficients table contains a note informing the user on the singularity of the data notes <- r$models[[1]]$coef$notes testthat::expect_true("singular" %in% names(notes)) }) testthat::test_that('Model fit table contains sample size footnote', { df <- data.frame( y = sample(0:1, 11, replace = TRUE), x = rnorm(11) ) r <- jmv::logRegBin( df, dep="y", covs="x", blocks=list(list("x")), refLevels=list(list(var="y", ref="0")) ) testthat::expect_match(r$modelFit$notes$n$note, "N=11") })