Nothing
skip_on_cran()
skip_if_not_installed("emmeans")
skip_if_not_installed("marginaleffects", minimum_version = "0.29.0")
skip_on_os("mac")
test_that("estimate_contrasts - same sign of contrasts for both backends", {
data(iris)
m <- lm(Sepal.Length ~ Species, data = iris)
out1 <- estimate_contrasts(m, contrast = "Species", backend = "emmeans")
out2 <- estimate_contrasts(m, contrast = "Species", backend = "marginaleffects")
expect_equal(out1$Difference, out2$Difference, tolerance = 1e-4)
})
test_that("estimate_contrasts - Frequentist, one factor", {
data(iris)
# One factor
dat <<- iris
model <- lm(Sepal.Width ~ Species, data = dat)
estim <- suppressMessages(estimate_contrasts(model, backend = "emmeans"))
expect_identical(dim(estim), c(3L, 9L))
expect_equal(estim$Difference, c(-0.658, -0.454, 0.204), tolerance = 1e-4)
estim <- suppressMessages(estimate_contrasts(model, backend = "marginaleffects"))
expect_identical(dim(estim), c(3L, 9L))
expect_equal(estim$Difference, c(-0.658, -0.454, 0.204), tolerance = 1e-4)
# validate against new marginaleffects
out <- marginaleffects::avg_predictions(
model,
by = "Species",
newdata = insight::get_datagrid(model, "Species", factors = "all"),
hypothesis = ~pairwise
)
expect_equal(out$estimate, estim$Difference, tolerance = 1e-4)
estim <- suppressMessages(estimate_contrasts(
model,
by = "Species=c('versicolor', 'virginica')",
backend = "emmeans"
))
expect_identical(dim(estim), c(1L, 9L))
estim <- suppressMessages(estimate_contrasts(
model,
contrast = "Species=c('versicolor', 'virginica')",
backend = "marginaleffects"
))
expect_identical(dim(estim), c(1L, 9L))
})
test_that("estimate_contrasts - Frequentist, two factors", {
data(iris)
# Two factors
dat <- iris
dat$fac <- ifelse(dat$Sepal.Length < 5.8, "A", "B")
dat <<- dat
model <- lm(Sepal.Width ~ Species * fac, data = dat)
estim <- suppressMessages(estimate_contrasts(model, backend = "emmeans"))
expect_identical(dim(estim), c(3L, 9L))
estim <- suppressMessages(estimate_contrasts(
model,
levels = "Species",
backend = "emmeans"
))
expect_identical(dim(estim), c(3L, 9L))
estim <- suppressMessages(estimate_contrasts(
model,
by = c("Species", "fac='A'"),
backend = "emmeans"
))
expect_identical(dim(estim), c(3L, 10L))
estim <- suppressMessages(estimate_contrasts(
model,
contrast = "Species",
backend = "marginaleffects"
))
expect_identical(dim(estim), c(3L, 9L))
estim <- suppressMessages(estimate_contrasts(
model,
contrast = "Species",
by = "fac='A'",
backend = "marginaleffects"
))
expect_identical(dim(estim), c(3L, 10L))
})
test_that("estimate_contrasts - Frequentist, One factor and one continuous", {
data(iris)
# One factor and one continuous
model <- lm(Sepal.Width ~ Species * Petal.Width, data = iris)
estim <- suppressMessages(estimate_contrasts(model, backend = "emmeans"))
expect_identical(dim(estim), c(3L, 9L))
estim <- suppressMessages(estimate_contrasts(
model,
by = c("Species", "Petal.Width=0"),
backend = "emmeans"
))
expect_identical(dim(estim), c(3L, 10L))
estim <- suppressMessages(estimate_contrasts(
model,
by = "Petal.Width",
length = 4,
backend = "emmeans"
))
expect_identical(dim(estim), c(12L, 10L))
## FIXME: currently errors
# estim <- estimate_contrasts(model, contrast = "Species", by = "Petal.Width=0", backend = "marginaleffects")
# expect_identical(dim(estim), c(3L, 9L))
estim <- estimate_contrasts(
model,
contrast = "Petal.Width",
by = "Species",
length = 4,
backend = "marginaleffects"
)
expect_equal(estim$Difference, c(0.21646, -0.20579, -0.42224), tolerance = 1e-4)
})
test_that("estimate_contrasts - Frequentist, One factor and one continuous", {
data(iris)
# Contrast between continuous
model <- lm(Sepal.Width ~ Petal.Length, data = iris)
estim <- suppressMessages(estimate_contrasts(
model,
by = "Petal.Length=c(2.3, 3)",
backend = "emmeans"
))
expect_identical(dim(estim), c(1L, 9L))
estim <- suppressMessages(estimate_contrasts(
model,
by = "Petal.Length=c(2, 3, 4)",
backend = "emmeans"
))
expect_identical(dim(estim), c(3L, 9L))
estim <- estimate_contrasts(
model,
contrast = "Petal.Length=c(2.3, 3)",
backend = "marginaleffects"
)
expect_identical(dim(estim), c(1L, 9L))
expect_named(
estim,
c("Level1", "Level2", "Difference", "SE", "CI_low", "CI_high", "t", "df", "p")
)
expect_identical(as.character(estim$Level1), "3")
estim <- estimate_contrasts(
model,
contrast = "Petal.Length=c(2, 3, 4)",
backend = "marginaleffects"
)
expect_named(
estim,
c("Level1", "Level2", "Difference", "SE", "CI_low", "CI_high", "t", "df", "p")
)
expect_identical(as.character(estim$Level1), c("3", "4", "4"))
expect_identical(dim(estim), c(3L, 9L))
})
test_that("estimate_contrasts - Frequentist, Three factors 1", {
data(mtcars)
# Three factors
dat <- mtcars
dat[c("gear", "vs", "am")] <- sapply(dat[c("gear", "vs", "am")], as.factor)
dat <<- dat
model <- lm(mpg ~ gear * vs * am, data = dat)
estim <- suppressMessages(estimate_contrasts(model, by = "all", backend = "emmeans"))
expect_identical(dim(estim), c(12L, 11L))
estim <- suppressMessages(estimate_contrasts(
model,
contrast = c("vs", "am"),
by = "gear='5'",
backend = "emmeans"
))
expect_identical(dim(estim), c(1L, 10L))
## FIXME: doesn't work right nw
# estim <- suppressMessages(estimate_contrasts(model, by = "all", backend = "marginaleffects"))
# expect_identical(dim(estim), c(12L, 11L))
estim <- suppressMessages(estimate_contrasts(
model,
contrast = c("vs", "am"),
by = "gear='5'",
backend = "marginaleffects"
))
expect_identical(dim(estim), c(6L, 10L))
expect_equal(
estim$Difference,
c(6.98333, 11.275, 18.25833, 4.29167, 11.275, 6.98333),
tolerance = 1e-4
)
estim <- suppressMessages(estimate_contrasts(
model,
contrast = c("vs", "am"),
by = "gear",
backend = "marginaleffects"
))
expect_identical(dim(estim), c(18L, 10L))
expect_named(
estim,
c("Level1", "Level2", "gear", "Difference", "SE", "CI_low", "CI_high", "t", "df", "p")
)
expect_equal(
estim$Difference,
c(
6.98333,
5.28333,
12.26667,
-1.7,
5.28333,
6.98333,
6.98333,
7.03333,
14.01667,
0.05,
7.03333,
6.98333,
6.98333,
11.275,
18.25833,
4.29167,
11.275,
6.98333
),
tolerance = 1e-4
)
expect_snapshot(print(
estimate_contrasts(
model,
contrast = c("vs", "am"),
by = "gear",
backend = "marginaleffects"
),
zap_small = TRUE,
table_width = Inf
))
})
test_that("estimate_contrasts - Frequentist, Three factors 2", {
data(efc, package = "modelbased")
efc <- datawizard::to_factor(efc, c("c161sex", "c172code", "e16sex", "e42dep"))
levels(efc$c172code) <- c("low", "mid", "high")
fit <- lm(neg_c_7 ~ barthtot + e16sex * c172code * c161sex, data = efc)
estim <- estimate_contrasts(
fit,
contrast = c("c161sex", "c172code"),
by = "e16sex='male'",
backend = "marginaleffects"
)
# validate against marginaleffects
out <- marginaleffects::avg_predictions(
fit,
newdata = datawizard::data_arrange(
as.data.frame(insight::get_datagrid(
fit,
by = c("c161sex", "c172code", "e16sex"),
factors = "all"
)),
c("c161sex", "c172code", "e16sex")
),
by = c("c161sex", "c172code", "e16sex"),
hypothesis = ~ pairwise | e16sex
)
expect_equal(out$estimate[out$e16sex == "male"], estim$Difference, tolerance = 1e-4)
expect_identical(dim(estim), c(15L, 10L))
expect_equal(
estim$Difference,
c(
2.70334,
2.23511,
1.55845,
2.48322,
2.48543,
-0.46823,
-1.14489,
-0.22012,
-0.21791,
-0.67666,
0.24811,
0.25032,
0.92477,
0.92698,
0.00221
),
tolerance = 1e-4
)
expect_true(all(estim$e16sex == "male"))
expect_identical(
as.character(estim$Level1),
c(
"Male, mid",
"Male, high",
"Female, low",
"Female, mid",
"Female, high",
"Male, high",
"Female, low",
"Female, mid",
"Female, high",
"Female, low",
"Female, mid",
"Female, high",
"Female, mid",
"Female, high",
"Female, high"
)
)
expect_identical(
as.character(estim$Level2),
c(
"Male, low",
"Male, low",
"Male, low",
"Male, low",
"Male, low",
"Male, mid",
"Male, mid",
"Male, mid",
"Male, mid",
"Male, high",
"Male, high",
"Male, high",
"Female, low",
"Female, low",
"Female, mid"
)
)
})
test_that("estimate_contrasts - Frequentist, duplicated levels", {
data(mtcars)
# duplicated levels
dat <- mtcars
dat[c("vs", "am")] <- sapply(dat[c("vs", "am")], as.factor)
set.seed(123)
dat$three <- factor(sample(0:1, nrow(dat), replace = TRUE))
model <- lm(mpg ~ three * vs * am, data = dat)
expect_snapshot(
print(
estimate_contrasts(
model,
contrast = c("three", "vs", "am"),
backend = "marginaleffects"
),
digits = 1,
zap_small = TRUE,
table_width = Inf
),
variant = "windows"
)
expect_snapshot(
print(
estimate_contrasts(model, contrast = "am", backend = "marginaleffects"),
zap_small = TRUE,
table_width = Inf
),
variant = "windows"
)
dat <- iris
dat$factor1 <- ifelse(dat$Sepal.Width > 3, "A", "B")
dat$factor2 <- ifelse(dat$Petal.Length > 3.5, "C", "D")
dat$factor3 <- ifelse(dat$Sepal.Length > 5, "E", "F")
dat <<- dat
model <- lm(Petal.Width ~ factor1 * factor2 * factor3, data = dat)
estim <- suppressMessages(estimate_contrasts(
model,
contrast = c("factor1", "factor2", "factor3"),
by = "all",
backend = "emmeans"
))
expect_identical(dim(estim), c(28L, 9L))
estim <- suppressMessages(estimate_contrasts(
model,
contrast = c("factor1", "factor2"),
by = "factor3='F'",
backend = "emmeans"
))
expect_identical(dim(estim), c(6L, 10L))
estim <- suppressMessages(estimate_contrasts(
model,
contrast = c("factor1", "factor2"),
by = "factor3",
backend = "emmeans"
))
expect_identical(dim(estim), c(12L, 10L))
})
test_that("estimate_contrasts - Frequentist, Mixed models", {
skip_if_not_installed("logspline")
skip_if_not_installed("lme4")
data(iris)
# Mixed models
data <- iris
data$Petal.Length_factor <- ifelse(data$Petal.Length < 4.2, "A", "B")
model <- lme4::lmer(Sepal.Width ~ Species + (1 | Petal.Length_factor), data = data)
estim <- suppressMessages(estimate_contrasts(model, backend = "emmeans"))
expect_identical(dim(estim), c(3L, 9L))
})
test_that("estimate_contrasts - Frequentist, GLM", {
data(iris)
# GLM - binomial
dat <- iris
dat$y <- as.factor(ifelse(dat$Sepal.Width > 3, "A", "B"))
dat <<- dat
model <- glm(y ~ Species, family = "binomial", data = dat)
estim1 <- suppressMessages(estimate_contrasts(model, backend = "emmeans"))
expect_identical(dim(estim1), c(3L, 9L))
estim2 <- suppressMessages(estimate_contrasts(
model,
predict = "link",
backend = "emmeans"
))
expect_identical(dim(estim2), c(3L, 9L))
expect_true(all(estim1$Difference != estim2$Difference))
estim3 <- suppressWarnings(suppressMessages(estimate_contrasts(
model,
backend = "marginaleffects"
)))
expect_identical(estim3$Difference, estim1$Difference)
estim4 <- suppressWarnings(suppressMessages(estimate_contrasts(
model,
predict = "link",
backend = "marginaleffects"
)))
expect_identical(estim4$Difference, estim2$Difference)
# GLM - poisson
dat <- data.frame(counts = c(18, 17, 15, 20, 10, 20, 25, 13, 12), treatment = gl(3, 3))
dat <<- dat
model <- glm(counts ~ treatment, data = dat, family = poisson())
estim <- suppressMessages(estimate_contrasts(
model,
predict = "response",
backend = "emmeans"
))
expect_identical(dim(estim), c(3L, 9L))
})
test_that("estimate_contrasts - Bayesian", {
skip_on_cran()
skip_if_not_installed("logspline")
skip_if_not_installed("rstanarm")
skip_if_not_installed("lme4")
skip_if_not_installed("coda")
data(iris)
dat <- iris
dat$Petal.Length_factor <- ifelse(dat$Petal.Length < 4.2, "A", "B")
dat <<- dat
set.seed(123)
model <- suppressWarnings(rstanarm::stan_glm(
Sepal.Width ~ Species * Petal.Length_factor,
data = dat,
refresh = 0,
iter = 200,
chains = 2,
seed = 123
))
estim <- suppressMessages(estimate_contrasts(
model,
contrast = "all",
backend = "emmeans"
))
expect_identical(dim(estim), c(15L, 7L))
estim <- suppressMessages(estimate_contrasts(
model,
by = c("Species", "Petal.Length_factor='A'"),
backend = "emmeans"
))
expect_identical(dim(estim), c(3L, 8L))
estim <- estimate_contrasts(
model,
contrast = c("Species", "Petal.Length_factor"),
backend = "marginaleffects"
)
expect_identical(dim(estim), c(15L, 10L))
expect_named(
estim,
c(
"Level1",
"Level2",
"ROPE_CI",
"Median",
"CI_low",
"CI_high",
"pd",
"ROPE_low",
"ROPE_high",
"ROPE_Percentage"
)
)
expect_equal(
estim$Median,
c(
-0.05025,
-0.89132,
-0.52141,
-0.27182,
-0.45085,
-0.83305,
-0.47175,
0.00022,
-0.45184,
0.36936,
0.60636,
0.43568,
0.20898,
0.068,
-0.18029
),
tolerance = 1e-4
)
set.seed(123)
model <- suppressWarnings(rstanarm::stan_glm(
Sepal.Width ~ Species * Petal.Width,
data = iris,
refresh = 0,
iter = 200,
chains = 2,
seed = 123
))
estim <- suppressMessages(estimate_contrasts(model, backend = "emmeans"))
expect_identical(dim(estim), c(3L, 7L))
estim <- suppressMessages(estimate_contrasts(
model,
by = c("Species", "Petal.Width=0"),
backend = "emmeans"
))
expect_identical(dim(estim), c(3L, 8L))
estim <- suppressMessages(estimate_contrasts(
model,
by = "Petal.Width",
length = 4,
backend = "emmeans"
))
expect_identical(dim(estim), c(12L, 8L))
# GLM
dat <- iris
dat$y <- as.numeric(as.factor(ifelse(dat$Sepal.Width > 3, "A", "B"))) - 1
dat <<- dat
model <- suppressWarnings(rstanarm::stan_glm(
y ~ Species,
family = "binomial",
data = dat,
refresh = 0,
prior = rstanarm::normal(scale = 0.5)
))
estim <- suppressMessages(estimate_contrasts(model, backend = "emmeans"))
expect_identical(dim(estim), c(3L, 7L))
estim <- suppressMessages(estimate_contrasts(
model,
predict = "link",
backend = "emmeans"
))
expect_identical(dim(estim), c(3L, 7L))
estim <- suppressWarnings(suppressMessages(estimate_contrasts(
model,
test = "bf",
backend = "emmeans"
)))
expect_identical(dim(estim), c(3L, 6L))
estim <- suppressWarnings(suppressMessages(estimate_contrasts(
model,
predict = "link",
test = "bf",
backend = "emmeans"
)))
expect_identical(dim(estim), c(3L, 6L))
})
test_that("estimate_contrasts - p.adjust", {
data(iris)
model <- lm(Petal.Width ~ Species, data = iris)
p_none <- suppressMessages(estimate_contrasts(
model,
p_adjust = "none",
backend = "emmeans"
))
p_tuk <- suppressMessages(estimate_contrasts(
model,
p_adjust = "tukey",
backend = "emmeans"
))
expect_true(any(p_none$p != p_tuk$p))
p_none <- suppressMessages(estimate_contrasts(
model,
p_adjust = "none",
backend = "marginaleffects"
))
p_tuk <- suppressMessages(estimate_contrasts(
model,
p_adjust = "tukey",
backend = "marginaleffects"
))
expect_true(any(p_none$p != p_tuk$p))
# make sure upper case works
expect_no_error(estimate_contrasts(
model,
contrast = "Species",
p_adjust = "BH",
backend = "marginaleffects"
))
model <- lm(Petal.Width ~ Species, data = iris)
expect_error(
estimate_contrasts(model, p_adjust = "scheffe"),
regex = "is only available when"
)
expect_silent(estimate_contrasts(
model,
contrast = "Species",
p_adjust = "scheffe",
backend = "emmeans"
))
skip_if_not_installed("mvtnorm")
dat <- iris
dat$fac <- ifelse(dat$Sepal.Length < 5.8, "A", "B")
model <- lm(Sepal.Width ~ Species * fac, data = dat)
set.seed(123)
out <- estimate_contrasts(model, c("Species", "fac"), p_adjust = "sup-t")
expect_equal(
out$p,
c(
0.44686,
0,
0,
0.00048,
0,
0.00086,
0.0086,
0.00328,
0.02718,
0.10619,
0.99998,
0.00037,
0.71917,
0.51122,
0.28497
),
tolerance = 1e-3
)
expect_equal(
out$CI_low,
c(
-0.3461,
-1.02306,
-0.76301,
-1.36376,
-0.60638,
-2.30875,
-2.06719,
-2.46281,
-1.93229,
-0.0281,
-0.60143,
0.12295,
-0.82718,
-0.08844,
-0.15023
),
tolerance = 1e-3
)
skip_if_not_installed("glmmTMB")
d <- glmmTMB::Salamanders
model <- suppressWarnings(glmmTMB::glmmTMB(
count ~ mined + spp + (1 | site),
ziformula = ~mined,
family = poisson,
data = d
))
set.seed(123)
out <- head(estimate_contrasts(model, "spp", by = "mined", p_adjust = "sup-t"))
expect_equal(
out$p,
c(0.00259, 0.59628, 0.18012, 0.00475, 0.00674, 0.99467),
tolerance = 1e-3
)
expect_equal(
out$CI_low,
c(-0.29028, -0.04581, -0.21504, 0.04106, 0.03308, -0.0816),
tolerance = 1e-3
)
skip_if(getRversion() < "4.5.0")
skip_if_not_installed("emmeans")
data(penguins, package = "datasets")
m_spec <- lm(body_mass ~ species, data = penguins)
out1 <- estimate_contrasts(m_spec, p_adjust = "tukey")
out2 <- estimate_contrasts(m_spec, p_adjust = "tukey", backend = "emmeans")
expect_equal(out1$p, out2$p, tolerance = 1e-4)
m_spec <- lm(body_mass ~ species * sex, data = penguins)
out1 <- estimate_contrasts(m_spec, p_adjust = "tukey")
out2 <- estimate_contrasts(
m_spec,
c("species", "sex"),
p_adjust = "tukey",
backend = "emmeans"
)
expect_equal(out1$p[7], out2$p[6], tolerance = 1e-4)
})
test_that("estimate_contrasts - ratios", {
data(iris)
model <- lm(Petal.Width ~ Species, data = iris)
estim <- estimate_contrasts(
model,
"Species",
comparison = ratio ~ pairwise,
backend = "marginaleffects"
)
expect_equal(estim$Ratio, c(5.39024, 8.23577, 1.5279), tolerance = 1e-4)
expect_identical(dim(estim), c(3L, 9L))
estim2 <- marginaleffects::avg_predictions(
model,
by = "Species",
hypothesis = ratio ~ pairwise
)
expect_equal(estim$Ratio, estim2$estimate, tolerance = 1e-4, ignore_attr = TRUE)
})
test_that("estimate_contrasts - dfs", {
skip_on_cran()
skip_if_not_installed("lme4")
skip_if_not_installed("pbkrtest")
skip_if_not_installed("lmerTest")
data(iris)
data <- iris
data$Petal.Length_factor <- ifelse(data$Petal.Length < 4.2, "A", "B")
model <- lme4::lmer(Sepal.Width ~ Species + (1 | Petal.Length_factor), data = data)
estim1 <- suppressMessages(estimate_contrasts(
model,
lmer.df = "satterthwaite",
p_adjust = "holm",
backend = "emmeans"
))
estim2 <- suppressMessages(estimate_contrasts(
model,
lmer.df = "kenward-roger",
p_adjust = "holm",
backend = "emmeans"
))
expect_true(all(estim1$CI_low != estim2$CI_low))
expect_equal(estim1$CI_high, c(2.43, 2.25692, 2.89384), tolerance = 1e-4)
expect_equal(estim2$CI_high, c(2.62766, 2.53389, 2.98196), tolerance = 1e-4)
estim1 <- suppressMessages(estimate_contrasts(
model,
lmer.df = "satterthwaite",
backend = "emmeans"
))
estim2 <- suppressMessages(estimate_contrasts(
model,
lmer.df = "kenward-roger",
backend = "emmeans"
))
expect_true(all(estim1$CI_low != estim2$CI_low))
expect_equal(estim1$CI_high, c(0.22624, 0.33383, 1.0109), tolerance = 1e-4)
expect_equal(estim2$CI_high, c(0.29193, 0.4364, 1.04019), tolerance = 1e-4)
})
test_that("estimate_contrasts - marginaleffects, comparisons, validate against predict", {
skip_if_not_installed("Formula")
data(coffee_data, package = "modelbased")
m <- lm(alertness ~ time * coffee + sex, data = coffee_data)
expect_snapshot(print(
estimate_contrasts(
m,
c("time", "coffee"),
backend = "marginaleffects",
p_adjust = "none"
),
zap_small = TRUE,
table_width = Inf
))
expect_snapshot(print(
estimate_contrasts(
m,
c("time", "coffee"),
backend = "marginaleffects",
p_adjust = "none",
comparison = ratio ~ reference | coffee
),
zap_small = TRUE,
table_width = Inf
))
expect_snapshot(print(
estimate_contrasts(
m,
c("time", "coffee"),
backend = "marginaleffects",
p_adjust = "none",
comparison = "(b2-b1)=(b4-b3)"
),
zap_small = TRUE,
table_width = Inf
))
out1 <- estimate_contrasts(
m,
c("time", "coffee"),
backend = "marginaleffects",
p_adjust = "none",
comparison = "(b2-b1)=(b4-b3)"
)
out2 <- predict(m, newdata = insight::get_datagrid(m, c("time", "coffee")))
expect_equal(out1$Difference, 5.78298, tolerance = 1e-4)
expect_equal(
out1$Difference,
((out2[2] - out2[1]) - (out2[4] - out2[3])),
tolerance = 1e-4,
ignore_attr = TRUE
)
out1 <- estimate_contrasts(
m,
c("time", "coffee"),
backend = "marginaleffects",
p_adjust = "none",
comparison = "b5=b3"
)
expect_equal(out1$Difference, -1.927659, tolerance = 1e-4)
expect_equal(out1$Difference, (out2[5] - out2[3]), tolerance = 1e-4, ignore_attr = TRUE)
expect_snapshot(print(
estimate_contrasts(
m,
c("time", "coffee"),
backend = "marginaleffects",
p_adjust = "none",
comparison = "b5=b3"
),
zap_small = TRUE,
table_width = Inf
))
# validated against ggeffects::test_predictions()
data(efc, package = "modelbased")
efc <- datawizard::to_factor(efc, c("c161sex", "c172code", "e16sex", "e42dep"))
fit <- lm(neg_c_7 ~ c12hour + barthtot + c161sex + e42dep * c172code, data = efc)
expect_snapshot(estimate_contrasts(
fit,
c("e42dep", "c172code"),
comparison = "b6-b3=0",
backend = "marginaleffects"
))
out <- estimate_contrasts(
fit,
c("e42dep", "c172code"),
comparison = "b6-b3=0",
backend = "marginaleffects"
)
expect_equal(out$Difference, -0.3352769, tolerance = 1e-4)
})
test_that("estimate_contrasts - marginaleffects vs emmeans", {
data(iris)
dat <- iris
dat$y <- as.factor(ifelse(dat$Sepal.Width > 3, "A", "B"))
model <- glm(y ~ Species, family = "binomial", data = dat)
expect_message(
estimate_contrasts(model, backend = "emmeans"),
regex = "No variable was"
)
## emmeans backend works and has proper default
out1 <- suppressMessages(estimate_contrasts(model, backend = "emmeans"))
out2 <- suppressMessages(estimate_contrasts(
model,
predict = "response",
backend = "emmeans"
))
expect_equal(out1$Difference, out2$Difference, tolerance = 1e-4)
expect_equal(out1$Difference, c(0.68, 0.5, -0.18), tolerance = 1e-4)
## marginaleffects backend works and has proper default
out4 <- suppressMessages(estimate_contrasts(model, backend = "marginaleffects"))
out5 <- suppressMessages(estimate_contrasts(
model,
predict = "response",
backend = "marginaleffects"
))
expect_equal(out4$Difference, out5$Difference, tolerance = 1e-4)
# validate against emmeans
out_emm <- emmeans::emmeans(model, "Species", type = "response")
out_emm <- emmeans::regrid(out_emm)
out6 <- as.data.frame(emmeans::contrast(out_emm, method = "pairwise"))
expect_equal(out6$estimate, out1$Difference * -1, tolerance = 1e-3)
# validate against marginaleffects
out7 <- marginaleffects::avg_predictions(model, by = "Species", hypothesis = ~pairwise)
expect_equal(out7$estimate, out4$Difference, tolerance = 1e-3)
# test p-adjust
expect_snapshot(estimate_contrasts(model, backend = "emmeans"))
expect_snapshot(estimate_contrasts(model, backend = "marginaleffects"))
expect_snapshot(estimate_contrasts(model, backend = "emmeans", p_adjust = "holm"))
expect_snapshot(estimate_contrasts(
model,
backend = "marginaleffects",
p_adjust = "holm"
))
})
test_that("estimate_contrasts - on-the-fly factors", {
data(mtcars)
model <- lm(mpg ~ as.factor(cyl) + wt * hp, mtcars)
out1 <- estimate_contrasts(model, backend = "emmeans")
out2 <- estimate_contrasts(model, contrast = "cyl", backend = "marginaleffects")
expect_identical(nrow(out1), 3L)
expect_identical(nrow(out2), 3L)
expect_equal(out1$Difference, out2$Difference, tolerance = 1e-4) # swicthed sign
mtcars2 <- mtcars
mtcars2$cyl <- as.factor(mtcars2$cyl)
model <- lm(mpg ~ cyl + wt * hp, mtcars2)
out3 <- estimate_contrasts(model, backend = "emmeans")
out4 <- estimate_contrasts(model, contrast = "cyl", backend = "marginaleffects")
expect_identical(nrow(out3), 3L)
expect_identical(nrow(out4), 3L)
expect_equal(out3$Difference, out4$Difference, tolerance = 1e-4) # switched sign
})
test_that("estimate_contrasts - works with slopes", {
data(iris)
fit <- lm(Sepal.Width ~ Petal.Length * Species, data = iris)
out1 <- estimate_slopes(fit, trend = "Petal.Length", backend = "marginaleffects")
out2 <- suppressMessages(as.data.frame(emmeans::emtrends(
fit,
specs = ~Petal.Length,
var = "Petal.Length"
)))
expect_equal(out1$Slope, out2$Petal.Length.trend, tolerance = 1e-3)
out3 <- estimate_slopes(
fit,
trend = "Petal.Length",
by = "Species",
backend = "marginaleffects"
)
out4 <- estimate_contrasts(
fit,
contrast = "Petal.Length",
by = "Species",
backend = "marginaleffects"
)
out5 <- emmeans::emtrends(fit, specs = pairwise ~ Species, var = "Petal.Length")
expect_equal(
out3$Slope,
as.data.frame(out5$emtrends)$Petal.Length.trend,
tolerance = 1e-3
)
expect_equal(
out4$Difference * -1,
as.data.frame(out5$contrasts)$estimate,
tolerance = 1e-3
)
})
test_that("estimate_contrasts - different options for comparison", {
set.seed(123)
dat <- data.frame(y = rpois(100, 3), fa = gl(4, 20, 100))
dat_glm <- glm(y ~ fa, data = dat, family = poisson(link = "log"))
# emmeans
out <- estimate_contrasts(
dat_glm,
contrast = "fa",
comparison = "eff",
backend = "emmeans"
)
expect_named(out, c("Level", "Difference", "CI_low", "CI_high", "SE", "df", "z", "p"))
expect_equal(out$Difference, c(0.2, 0.55, -0.6, -0.15), tolerance = 1e-3)
out <- estimate_contrasts(
dat_glm,
contrast = "fa",
comparison = "poly",
backend = "emmeans"
)
expect_named(out, c("Level", "Difference", "CI_low", "CI_high", "SE", "df", "z", "p"))
expect_equal(out$Difference, c(3.1, -2.2, 0.1), tolerance = 1e-3)
# marginaleffects
out <- estimate_contrasts(
dat_glm,
contrast = "fa",
comparison = "pairwise",
backend = "marginaleffects"
)
expect_named(
out,
c("Level1", "Level2", "Difference", "SE", "CI_low", "CI_high", "z", "p")
)
expect_equal(out$Difference, c(0.35, -0.8, -0.35, -1.15, -0.7, 0.45), tolerance = 1e-3)
out <- estimate_contrasts(
dat_glm,
contrast = "fa",
comparison = "reference",
backend = "marginaleffects"
)
expect_named(
out,
c("Level1", "Level2", "Difference", "SE", "CI_low", "CI_high", "z", "p")
)
expect_equal(out$Difference, c(0.35, -0.8, -0.35), tolerance = 1e-3)
})
skip_on_os(c("mac", "linux"))
test_that("estimate_contrasts - filtering works", {
data(efc, package = "modelbased")
# make categorical
efc <- datawizard::to_factor(efc, c("c161sex", "c172code", "e16sex"))
levels(efc$c172code) <- c("low", "mid", "high")
fit <- lm(neg_c_7 ~ e16sex + c161sex + c172code, data = efc)
expect_snapshot(print(
estimate_contrasts(fit, "c172code", backend = "marginaleffects"),
table_width = Inf,
zap_small = TRUE
))
fit <- lm(neg_c_7 ~ e16sex + c161sex * c172code, data = efc)
expect_snapshot(print(
estimate_contrasts(fit, c("c161sex", "c172code"), backend = "marginaleffects"),
table_width = Inf,
zap_small = TRUE
))
expect_snapshot(print(
estimate_contrasts(fit, "c161sex", "c172code", backend = "marginaleffects"),
table_width = Inf,
zap_small = TRUE
))
fit <- lm(neg_c_7 ~ barthtot + c161sex + c172code, data = efc)
expect_snapshot(print(
estimate_slopes(fit, "barthtot", backend = "marginaleffects"),
table_width = Inf,
zap_small = TRUE
))
# error
expect_error(
estimate_contrasts(fit, "barthtot", backend = "marginaleffects"),
regex = "Please specify"
)
fit <- lm(neg_c_7 ~ e16sex + barthtot * c172code, data = efc)
expect_snapshot(print(
estimate_slopes(fit, "barthtot", by = "c172code", backend = "marginaleffects"),
table_width = Inf,
zap_small = TRUE
))
expect_snapshot(print(
estimate_contrasts(fit, "barthtot", "c172code", backend = "marginaleffects"),
table_width = Inf,
zap_small = TRUE
))
fit <- lm(neg_c_7 ~ e16sex * barthtot * c172code, data = efc)
expect_snapshot(print(
estimate_contrasts(
fit,
"barthtot",
c("c172code", "e16sex"),
backend = "marginaleffects"
),
table_width = Inf,
zap_small = TRUE
))
# error
expect_error(
estimate_contrasts(fit, c("barthtot", "c172code"), backend = "marginaleffects"),
regex = "Please specify"
)
})
test_that("estimate_contrasts - simple contrasts and with - in levels works", {
skip_if_not_installed("glmmTMB")
data(iris)
model <- lm(Sepal.Length ~ Species + Sepal.Width, data = iris)
expect_snapshot(print(
estimate_contrasts(model, "Species", backend = "marginaleffects"),
table_width = Inf
))
data(coffee_data, package = "modelbased")
m <- lm(alertness ~ time * coffee + sex, data = coffee_data)
expect_snapshot(print(
estimate_contrasts(m, c("time", "coffee"), backend = "marginaleffects"),
zap_small = TRUE,
table_width = Inf
))
expect_snapshot(print(
estimate_contrasts(m, contrast = "time", by = "coffee", backend = "marginaleffects"),
zap_small = TRUE,
table_width = Inf
))
data(Salamanders, package = "glmmTMB")
model <- glmmTMB::glmmTMB(
count ~ mined * spp + cover + (1 | site),
data = Salamanders,
family = "poisson"
)
expect_snapshot(print(
estimate_contrasts(model, contrast = c("mined", "spp"), backend = "marginaleffects"),
zap_small = TRUE,
table_width = Inf
))
expect_snapshot(print(
estimate_contrasts(
model,
contrast = "mined",
by = "spp",
backend = "marginaleffects"
),
zap_small = TRUE,
table_width = Inf
))
})
test_that("estimate_contrasts - contrasts for numeric by factor 1", {
data(iris)
model <- lm(Petal.Width ~ Petal.Length * Species, data = iris)
out1 <- estimate_contrasts(
model,
contrast = "Petal.Length",
by = "Species",
backend = "marginaleffects"
)
# validated against ggeffects::test_predictions()
expect_equal(out1$Difference, c(0.12981, -0.04095, -0.17076), tolerance = 1e-4)
out2 <- marginaleffects::avg_slopes(
model,
variables = "Petal.Length",
by = "Species",
newdata = insight::get_datagrid(model, by = c("Petal.Length", "Species")),
hypothesis = ~pairwise
)
expect_equal(out1$Difference, out2$estimate, tolerance = 1e-4)
})
test_that("estimate_contrasts - contrasts for numeric by factor 2", {
data(efc, package = "modelbased")
efc <- datawizard::to_factor(efc, c("c161sex", "c172code", "e16sex"))
levels(efc$c172code) <- c("low", "mid", "high")
fit <- lm(neg_c_7 ~ e16sex + c161sex * c172code, data = efc)
# all should return the same output
out1 <- estimate_contrasts(fit, "c161sex", by = "c172code", backend = "marginaleffects")
out2 <- estimate_contrasts(
fit,
c("c161sex", "c172code"),
comparison = ~ pairwise | c172code,
backend = "marginaleffects"
)
out3 <- estimate_contrasts(
fit,
"c161sex",
by = "c172code",
comparison = ~pairwise,
backend = "marginaleffects"
)
expect_named(
out1,
c(
"Level1",
"Level2",
"c172code",
"Difference",
"SE",
"CI_low",
"CI_high",
"t",
"df",
"p"
)
)
expect_named(
out2,
c(
"Level1",
"Level2",
"c172code",
"Difference",
"SE",
"CI_low",
"CI_high",
"t",
"df",
"p"
)
)
expect_named(
out3,
c(
"Level1",
"Level2",
"c172code",
"Difference",
"SE",
"CI_low",
"CI_high",
"t",
"df",
"p"
)
)
expect_identical(dim(out1), c(3L, 10L))
expect_identical(dim(out2), c(3L, 10L))
expect_identical(dim(out3), c(3L, 10L))
expect_equal(out1$Difference, c(1.04585, 0.56041, 0.95798), tolerance = 1e-4)
expect_equal(out2$Difference, c(1.04585, 0.56041, 0.95798), tolerance = 1e-4)
expect_equal(out3$Difference, c(1.04585, 0.56041, 0.95798), tolerance = 1e-4)
})
test_that("estimate_contrasts - by with _ in variable name works", {
data(efc, package = "modelbased")
efc <- datawizard::to_factor(efc, c("c161sex", "c172code", "e16sex"))
levels(efc$c172code) <- c("low", "mid", "high")
efc$edu_cation <- efc$c172code
m1 <- lm(neg_c_7 ~ e16sex + c161sex * edu_cation, data = efc)
m2 <- lm(neg_c_7 ~ e16sex + c161sex * c172code, data = efc)
out1 <- estimate_contrasts(
m1,
"c161sex",
by = "edu_cation",
backend = "marginaleffects"
)
out2 <- estimate_contrasts(m2, "c161sex", by = "c172code", backend = "marginaleffects")
expect_named(
out1,
c(
"Level1",
"Level2",
"edu_cation",
"Difference",
"SE",
"CI_low",
"CI_high",
"t",
"df",
"p"
)
)
expect_named(
out2,
c(
"Level1",
"Level2",
"c172code",
"Difference",
"SE",
"CI_low",
"CI_high",
"t",
"df",
"p"
)
)
expect_identical(dim(out1), dim(out2))
expect_equal(out1$Difference, out2$Difference, tolerance = 1e-4)
})
test_that("estimate_contrasts - row order in data grid doesn't matter", {
# see https://github.com/vincentarelbundock/marginaleffects/issues/1374
set.seed(123)
n <- 200
d <- data.frame(
score = rnorm(n),
grp = as.factor(sample(c("treatment", "control"), n, TRUE)),
time = as.factor(sample(1:3, n, TRUE))
)
model2 <- lm(score ~ grp * time, data = d)
out1 <- estimate_contrasts(model2, "grp", by = "time", backend = "marginaleffects")
out2 <- estimate_contrasts(model2, "time", by = "grp", backend = "marginaleffects")
expect_identical(dim(out1), c(3L, 10L))
expect_identical(dim(out2), c(6L, 10L))
expect_identical(as.character(out1$Level1), c("treatment", "treatment", "treatment"))
expect_identical(as.character(out2$Level1), c("2", "3", "3", "2", "3", "3"))
expect_equal(out1$Difference, c(-0.41835, -0.05537, -0.05027), tolerance = 1e-4)
expect_equal(
out2$Difference,
c(0.2036, -0.07087, -0.27447, 0.56658, 0.29721, -0.26937),
tolerance = 1e-4
)
})
test_that("estimate_contrasts - filtering in `by` works", {
data(efc, package = "modelbased")
efc <- datawizard::to_factor(efc, c("c161sex", "c172code", "e16sex", "e42dep"))
levels(efc$c172code) <- c("low", "mid", "high")
fit <- lm(neg_c_7 ~ c12hour + barthtot + c161sex + e42dep * c172code, data = efc)
out1 <- estimate_contrasts(fit, "c172code", by = "e42dep")
out2 <- estimate_contrasts(fit, "c172code", by = "e42dep='slightly dependent'")
expect_identical(dim(out1), c(12L, 10L))
expect_identical(dim(out2), c(3L, 10L))
expect_equal(out1$Difference[4:6], out2$Difference, tolerance = 1e-4)
})
test_that("estimate_contrasts - examples from docs work as intendec", {
model <- lm(Sepal.Width ~ Species * Petal.Width, data = iris)
expect_snapshot(print(
estimate_contrasts(model, contrast = "Petal.Width", by = "Species"),
zap_small = TRUE,
table_width = Inf
))
expect_snapshot(print(
estimate_contrasts(model, contrast = c("Species", "Petal.Width"), length = 2),
zap_small = TRUE,
table_width = Inf
))
expect_snapshot(print(
estimate_contrasts(model, contrast = c("Species", "Petal.Width=c(1, 2)")),
zap_small = TRUE,
table_width = Inf
))
expect_snapshot(print(
estimate_contrasts(model, by = "Petal.Width", length = 4),
zap_small = TRUE,
table_width = Inf
))
})
test_that("estimate_contrasts - test all combinations of contrast and by, with filtering", {
# see https://github.com/vincentarelbundock/marginaleffects/issues/1374
set.seed(123)
n <- 1000
d <- data.frame(
score = rnorm(n),
grp = as.factor(sample(c("treatment", "control"), n, TRUE)),
time = as.factor(sample(1:2, n, TRUE)),
x = as.factor(sample(letters[1:2], n, TRUE))
)
model2 <- lm(score ~ grp * time * x, data = d)
expect_snapshot(print(
estimate_contrasts(model2, c("grp", "time", "x")),
zap_small = TRUE,
table_width = Inf
))
expect_snapshot(print(
estimate_contrasts(model2, c("grp", "time"), by = "x"),
zap_small = TRUE,
table_width = Inf
))
expect_snapshot(print(
estimate_contrasts(model2, "grp", by = c("time", "x")),
zap_small = TRUE,
table_width = Inf
))
expect_snapshot(print(
estimate_contrasts(model2, "grp", by = "time"),
zap_small = TRUE,
table_width = Inf
))
expect_snapshot(print(
estimate_contrasts(model2, c("grp", "time", "x='a'")),
zap_small = TRUE,
table_width = Inf
))
expect_snapshot(print(
estimate_contrasts(model2, c("grp", "time=1"), by = "x"),
zap_small = TRUE,
table_width = Inf
))
expect_snapshot(print(
estimate_contrasts(model2, "grp", by = c("time", "x='a'")),
zap_small = TRUE,
table_width = Inf
))
set.seed(123)
n <- 1000
d <- data.frame(
score = rnorm(n),
grp = as.factor(sample(c("treatment", "control"), n, TRUE)),
time = as.factor(sample(1:3, n, TRUE))
)
model2 <- lm(score ~ grp * time, data = d)
expect_snapshot(print(
estimate_contrasts(model2, "time=c(1,2)", by = "grp"),
zap_small = TRUE,
table_width = Inf
))
expect_snapshot(print(
estimate_contrasts(model2, c("grp", "time=2")),
zap_small = TRUE,
table_width = Inf
))
})
test_that("estimate_contrast, full averaging", {
data(efc, package = "modelbased")
efc <- datawizard::to_factor(efc, c("c161sex", "c172code", "e16sex", "e42dep"))
levels(efc$c172code) <- c("low", "mid", "high")
m <- lm(neg_c_7 ~ c12hour + barthtot + e42dep + c161sex * c172code, data = efc)
out <- estimate_contrasts(m, "c161sex", by = "c172code", estimate = "average")
expect_equal(out$Difference, c(1.09591, 0.68736, 0.92224), tolerance = 1e-4)
})
test_that("estimate_contrast, slopes with emmeans", {
data(iris)
model <- lm(Petal.Width ~ Petal.Length * Species, data = iris)
out <- estimate_contrasts(
model,
contrast = "Petal.Length",
by = "Species",
backend = "emmeans"
)
expect_identical(dim(out), c(3L, 9L))
expect_equal(out$Difference, c(0.12981, -0.04095, -0.17076), tolerance = 1e-4)
expect_identical(as.character(out$Level2), c("setosa", "setosa", "versicolor"))
})
test_that("estimate_contrast, slopes with emmeans-2", {
set.seed(123)
dat <- data.frame(
outcome = rbinom(n = 100, size = 1, prob = 0.35),
var_binom = as.factor(rbinom(n = 100, size = 1, prob = 0.2)),
var_cont = rnorm(n = 100, mean = 10, sd = 7)
)
dat$var_cont <- datawizard::standardize(dat$var_cont)
m1 <- glm(outcome ~ var_binom + var_cont, data = dat, family = binomial(link = "logit"))
# range of values
out <- estimate_contrasts(
m1,
c("var_binom", "var_cont"),
predict = "link",
transform = "exp",
length = 3
)
expect_snapshot(print(out, table_width = Inf))
expect_identical(
as.character(out$Level1),
c(
"0, 0.725",
"0, 3.463",
"1, -2.012",
"1, 0.725",
"1, 3.463",
"0, 3.463",
"1, -2.012",
"1, 0.725",
"1, 3.463",
"1, -2.012",
"1, 0.725",
"1, 3.463",
"1, 0.725",
"1, 3.463",
"1, 3.463"
)
)
out <- estimate_contrasts(
m1,
c("var_binom", "var_cont=[sd]"),
predict = "link",
transform = "exp"
)
expect_identical(
as.character(out$Level1),
c(
"var_binom 0, var_cont 0",
"var_binom 0, var_cont 1",
"var_binom 1, var_cont -1",
"var_binom 1, var_cont 0",
"var_binom 1, var_cont 1",
"var_binom 0, var_cont 1",
"var_binom 1, var_cont -1",
"var_binom 1, var_cont 0",
"var_binom 1, var_cont 1",
"var_binom 1, var_cont -1",
"var_binom 1, var_cont 0",
"var_binom 1, var_cont 1",
"var_binom 1, var_cont 0",
"var_binom 1, var_cont 1",
"var_binom 1, var_cont 1"
)
)
})
test_that("estimate_contrast, filter by numeric values", {
skip_if_not_installed("lme4")
data(iris)
mod <- lm(Sepal.Length ~ Petal.Width * Species, data = iris)
out1 <- estimate_contrasts(
mod,
contrast = "Species=",
by = "Petal.Width=c(1,2,3)",
backend = "marginaleffects"
)
out2 <- estimate_contrasts(
mod,
contrast = "Species=",
by = "Petal.Width=c(1,2,3)",
backend = "emmeans"
)
expect_identical(dim(out1), c(9L, 10L))
expect_identical(dim(out2), c(9L, 10L))
expect_equal(
out1$Difference,
c(
-0.23635,
0.2129,
0.44924,
0.25985,
-0.06644,
-0.32629,
0.75604,
-0.34579,
-1.10183
),
tolerance = 1e-4
)
expect_equal(
out2$Difference,
c(
-0.23635,
0.25985,
0.75604,
0.2129,
-0.06644,
-0.34579,
0.44924,
-0.32629,
-1.10183
),
tolerance = 1e-4
)
out1 <- estimate_contrasts(
mod,
contrast = "Species=c('versicolor','setosa')",
by = "Petal.Width=c(1,2,3)",
backend = "marginaleffects"
)
out2 <- estimate_contrasts(
mod,
contrast = "Species=c('versicolor','setosa')",
by = "Petal.Width=c(1,2,3)",
backend = "emmeans"
)
expect_identical(dim(out1), c(3L, 10L))
expect_identical(dim(out2), c(3L, 10L))
expect_equal(out1$Difference, out2$Difference, tolerance = 1e-4)
data(CO2)
mod <- suppressWarnings(lme4::lmer(uptake ~ conc * Plant + (1 | Type), data = CO2))
out1 <- estimate_contrasts(
mod,
contrast = "Plant",
by = "conc=c(100,200)",
backend = "marginaleffects"
)
out2 <- estimate_contrasts(
mod,
contrast = "Plant",
by = "conc=c(100,200)",
backend = "emmeans"
)
expect_identical(dim(out1), c(132L, 10L))
expect_identical(dim(out2), c(132L, 10L))
out1 <- estimate_contrasts(
mod,
contrast = "Plant=c('Qn1','Qn2','Qn3')",
by = "conc=c(100,200)",
backend = "marginaleffects"
)
out2 <- estimate_contrasts(
mod,
contrast = "Plant=c('Qn1','Qn2','Qn3')",
by = "conc=c(100,200)",
backend = "emmeans"
)
expect_identical(dim(out1), c(6L, 10L))
expect_identical(dim(out2), c(6L, 10L))
expect_equal(out1$Difference[c(1, 6)], out2$Difference[c(1, 6)], tolerance = 1e-4)
out1 <- estimate_contrasts(
mod,
contrast = "Plant=c('Qn1','Qn2','Qn3')",
backend = "marginaleffects"
)
out2 <- estimate_contrasts(
mod,
contrast = "Plant=c('Qn1','Qn2','Qn3')",
comparison = "b1=b2",
backend = "marginaleffects"
)
expect_equal(out1$Difference[1], -1 * out2$Difference, tolerance = 1e-4)
out1 <- estimate_contrasts(mod, contrast = "conc", by = "Plant=c('Mc2','Mn1','Qn3')")
expect_equal(out1$Difference, c(0.01746, 0.01782, 0.00036), tolerance = 1e-3)
out <- estimate_contrasts(
mod,
contrast = "conc",
by = "Plant=c('Mc2','Mn1','Qn3')",
comparison = "b1=b2"
)
expect_equal(out$Difference, -0.01745914, tolerance = 1e-4)
})
test_that("estimate_contrast, filterin in `by` and `contrast`", {
data(efc, package = "modelbased")
efc <- datawizard::to_factor(efc, c("c161sex", "c172code", "e16sex", "e42dep"))
levels(efc$c172code) <- c("low", "mid", "high")
m <- lm(neg_c_7 ~ barthtot + c172code * e42dep + c161sex, data = efc)
out <- estimate_contrasts(m, c("e42dep", "c172code"))
expect_identical(dim(out), c(66L, 9L))
out <- estimate_contrasts(
m,
"e42dep=c('independent','slightly dependent','moderately dependent')",
by = "c172code"
)
expect_identical(dim(out), c(9L, 10L))
expect_equal(
out$Difference,
c(-0.77851, 0.12142, 0.89993, 0.87674, 1.97996, 1.10322, 2.69591, 2.59613, -0.09978),
tolerance = 1e-4
)
out <- estimate_contrasts(
m,
"e42dep=c('independent','slightly dependent','moderately dependent')",
by = "c172code",
comparison = "b1=b4"
)
expect_equal(out$Difference, 1.163197, tolerance = 1e-4)
out <- estimate_contrasts(m, "e42dep", by = "c172code=c('low','mid')")
expect_identical(dim(out), c(12L, 10L))
})
test_that("estimate_contrast, don't calculate slopes for integers", {
data(mtcars)
m <- lm(mpg ~ hp + gear, data = mtcars)
expect_message(
estimate_contrasts(m, "gear"),
regex = "Numeric variable appears to be ordinal"
)
out <- estimate_contrasts(m, "gear")
expect_identical(dim(out), c(3L, 9L))
expect_error(estimate_contrasts(m, "hp"), regex = "Please specify")
out <- estimate_contrasts(m, "hp", by = "gear")
expect_identical(dim(out), c(3L, 9L))
})
test_that("estimate_contrast, informative error when `by` and `contrast` are the same", {
data(iris)
m <- lm(Petal.Length ~ Species, data = iris)
expect_error(
estimate_contrasts(m, "Species = 'versicolor'", by = "Species = 'setosa'"),
regex = "You cannot"
)
})
test_that("estimate_contrast, works with aov (when no statistic is extracted)", {
skip_if(getRversion() < "4.5.0")
data(penguins, package = "datasets")
fit <- aov(formula = body_mass ~ species, data = penguins)
out1 <- marginaleffects::avg_predictions(fit, by = "species", hypothesis = ~pairwise)
out2 <- estimate_contrasts(
model = fit,
contrast = "species",
backend = "marginaleffects"
)
expect_equal(out1$estimate, out2$Difference, tolerance = 1e-4)
expect_identical(out2$df, c(339L, 339L, 339L))
out3 <- estimate_contrasts(
model = fit,
contrast = "species",
df = Inf,
backend = "marginaleffects"
)
expect_equal(out1$p.value, out3$p, tolerance = 1e-4)
})
test_that("estimate_contrast, slopes with different estimate options", {
skip_if(getRversion() < "4.5.0")
skip_if_not_installed("datawizard")
data(penguins, package = "datasets")
penguins$long_bill <- factor(
datawizard::categorize(penguins$bill_len),
labels = c("short", "long")
)
m <- glm(long_bill ~ species + island * bill_dep, data = penguins, family = "binomial")
out <- estimate_contrasts(m, "bill_dep", by = "island")
expect_equal(out$Difference, c(0.08507, -0.00071, -0.08578), tolerance = 1e-4)
out <- estimate_contrasts(m, "bill_dep", by = "island", estimate = "average")
expect_equal(out$Difference, c(-0.05295, -0.07655, -0.0236), tolerance = 1e-4)
})
test_that("estimate_contrast, comparison-options as strings", {
data(mtcars)
mtcars$cyl_helmert <- as.factor(mtcars$cyl)
contrasts(mtcars$cyl_helmert) <- matrix(
c(-0.5, 0.5, 0, -1 / 3, -1 / 3, 2 / 3),
ncol = 2,
dimnames = list(c("4", "6", "8"), c("6vs4", "8vs4&6"))
)
mod2 <- lm(mpg ~ cyl_helmert, data = mtcars)
out <- estimate_contrasts(mod2, contrast = "cyl_helmert", comparison = "helmert")
expect_equal(out$Difference, c(-6.92078, -16.20649), tolerance = 1e-4)
out <- estimate_contrasts(mod2, contrast = "cyl_helmert", comparison = "poly")
expect_equal(out$Difference, c(-8.17673, 0.92996), tolerance = 1e-4)
})
test_that("estimate_contrast, p-adjust tukey works for contrasting slopes", {
skip_if(getRversion() < "4.5.0")
skip_if_not_installed("emmeans")
data(penguins, package = "datasets")
m <- lm(flipper_len ~ body_mass * species, data = penguins)
out1 <- as.data.frame(pairs(emmeans::emtrends(m, ~species, var = "body_mass")))
out2 <- estimate_contrasts(
m,
contrast = "body_mass",
by = "species",
p_adjust = "tukey"
)
# Note: p-values from emmeans::emtrends() + pairs() and estimate_contrasts()
# can differ slightly due to different underlying calculation/adjustment
# methods, especially with Tukey p-adjustment. A tolerance of 1e-2 is used
# here to avoid fragile tests while still ensuring close agreement.
expect_equal(out1$p.value, out2$p, tolerance = 1e-2)
})
test_that("estimate_contrast, categorical/multinomial response models split off Response levels", {
skip_if_not_installed("nnet")
data(iris)
m <- nnet::multinom(Species ~ Sepal.Width, data = iris, trace = FALSE)
out <- estimate_contrasts(
m,
contrast = "Sepal.Width = c(2, 3)",
backend = "marginaleffects"
)
# Level1/Response1/Level2/Response2 columns, in that order
expect_named(
out,
c(
"Level1",
"Response1",
"Level2",
"Response2",
"Difference",
"SE",
"CI_low",
"CI_high",
"t",
"df",
"p"
)
)
# contrasted levels no longer contain the response category label
expect_true(all(as.character(out$Level1) %in% c("2", "3")))
expect_true(all(as.character(out$Level2) %in% c("2", "3")))
expect_true(all(as.character(out$Response1) %in% levels(iris$Species)))
expect_true(all(as.character(out$Response2) %in% levels(iris$Species)))
out2 <- marginaleffects::avg_predictions(
m,
by = "Sepal.Width",
newdata = data.frame(Sepal.Width = c(2, 3)),
hypothesis = ~pairwise
)
expect_identical(
paste0(
"(",
out$Response1,
" ",
out$Level1,
") - (",
out$Response2,
" ",
out$Level2,
")"
),
out2$hypothesis
)
expect_equal(out$Difference, out2$estimate, tolerance = 1e-4)
# contrasts within the same response category should match the difference
# between the corresponding marginal means for that category
means <- estimate_means(m, by = "Sepal.Width = c(2, 3)", backend = "marginaleffects")
for (resp in levels(iris$Species)) {
row <- out[
as.character(out$Level1) == "3" &
as.character(out$Level2) == "2" &
as.character(out$Response1) == resp &
as.character(out$Response2) == resp,
]
expect_identical(nrow(row), 1L)
mean_3 <- means$Probability[means$Sepal.Width == "3" & means$Response == resp]
mean_2 <- means$Probability[means$Sepal.Width == "2" & means$Response == resp]
expect_equal(row$Difference, mean_3 - mean_2, tolerance = 1e-4)
}
})
test_that("estimate_contrast, correctly preserve minus in factor levels", {
df <- data.frame(
x = rnorm(1000),
y = rep_len(c("A - High", "A - Low", "B - High", "B - Low"), 1000)
)
model <- lm(x ~ y, data = df)
out1 <- estimate_contrasts(model, contrast = "y", backend = "marginaleffects")
out2 <- estimate_contrasts(model, contrast = "y", backend = "emmeans")
expect_identical(
as.character(out1$Level1),
c("A - Low", "B - High", "B - Low", "B - High", "B - Low", "B - Low")
)
expect_identical(
as.character(out2$Level1),
c("A - Low", "B - High", "B - High", "B - Low", "B - Low", "B - Low")
)
expect_identical(
as.character(out1$Level2),
c("A - High", "A - High", "A - High", "A - Low", "A - Low", "B - High")
)
expect_identical(
as.character(out2$Level2),
c("A - High", "A - High", "A - Low", "A - High", "A - Low", "B - High")
)
})
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.