diff --git a/DESCRIPTION b/DESCRIPTION index f9b8eedfd..da55c658e 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,7 +1,7 @@ Type: Package Package: modelbased Title: Estimation of Model-Based Predictions, Contrasts and Means -Version: 0.14.0.11 +Version: 0.14.0.12 Authors@R: c(person(given = "Dominique", family = "Makowski", diff --git a/R/get_contexteffects.R b/R/get_contexteffects.R index b36037e19..d99c9fe4e 100644 --- a/R/get_contexteffects.R +++ b/R/get_contexteffects.R @@ -12,7 +12,7 @@ # if we have stratified by another group, we need the difference between # contrasts at each group level if (is.null(my_args$by)) { - comparison <- stats::as.formula("~I(diff(x))") + comparison <- stats::as.formula("~revpairwise") } else if (length(my_args$by) > 2) { # it is not possible to have more than two by-variables for now insight::format_error( @@ -20,7 +20,7 @@ ) } else { comparison <- stats::as.formula(paste( - "~I(diff(x)) |", + "~revpairwise |", paste(my_args$by, collapse = "+") )) } @@ -96,6 +96,9 @@ } } + # not needed + out$hypothesis <- NULL + # save some labels for printing attr(out, "by") <- attr(out, "hypothesis_by") <- my_args$by attr(out, "contrast") <- my_args$contrast diff --git a/tests/testthat/test-estimate_contrasts_context.R b/tests/testthat/test-estimate_contrasts_context.R index 3d05a5ab3..e389be9db 100644 --- a/tests/testthat/test-estimate_contrasts_context.R +++ b/tests/testthat/test-estimate_contrasts_context.R @@ -13,12 +13,12 @@ test_that("estimate_contrast, context effects, linear", { se <- coef(summary(m))[2:3, 2] out <- estimate_contrasts(m, c("bill_len_between", "bill_len_within")) - expect_equal(out$Difference, b[2] - b[1], tolerance = 1e-4, ignore_attr = TRUE) + expect_equal(out$Difference, b[1] - b[2], tolerance = 1e-4, ignore_attr = TRUE) expect_equal(out$SE, sqrt((se[1]^2 + se[2]^2)), tolerance = 1e-4, ignore_attr = TRUE) expect_true(!is.null(out$p)) output <- capture.output(out) - expect_identical(output[3], "Difference | SE | 95% CI | z | p") + expect_identical(output[3], "Difference | SE | 95% CI | z | p") expect_message( estimate_contrasts( @@ -34,16 +34,16 @@ test_that("estimate_contrast, context effects, linear", { expect_named(out, c("year", "Difference", "SE", "CI_low", "CI_high", "z", "p")) x1 <- estimate_slopes(m, "bill_len_within", by = "year") x2 <- estimate_slopes(m, "bill_len_between", by = "year") - expect_equal(out$Difference, x1$Slope - x2$Slope, tolerance = 1e-4) + expect_equal(out$Difference, x2$Slope - x1$Slope, tolerance = 1e-4) out <- estimate_contrasts(m, c("bill_len_between", "bill_len_within", "year")) expect_named( out, - c("Level1", "Level2", "Parameter", "Difference", "SE", "CI_low", "CI_high", "z", "p") + c("Level1", "Level2", "Difference", "SE", "CI_low", "CI_high", "z", "p") ) expect_equal( out$Difference, - c(-0.04317, -0.08635, -0.04317), + c(0.04317, 0.08635, 0.04317), tolerance = 1e-4, ignore_attr = TRUE ) @@ -60,14 +60,14 @@ test_that("estimate_contrast, context effects, linear", { c( "Marginal Contrasts Analysis", "", - "sex | year | Difference | SE | 95% CI | z | p", - "-----------------------------------------------------------------", - "female | 2007 | 0.28 | 0.08 | [ 0.12, 0.45] | 3.41 | < .001", - "female | 2008 | 0.26 | 0.06 | [ 0.15, 0.37] | 4.47 | < .001", - "female | 2009 | 0.24 | 0.10 | [ 0.05, 0.42] | 2.48 | 0.013", - "male | 2007 | 0.46 | 0.10 | [ 0.26, 0.65] | 4.60 | < .001", - "male | 2008 | 0.28 | 0.06 | [ 0.15, 0.40] | 4.41 | < .001", - "male | 2009 | 0.10 | 0.10 | [-0.11, 0.30] | 0.93 | 0.355", + "sex | year | Difference | SE | 95% CI | z | p", + "-------------------------------------------------------------------", + "female | 2007 | -0.28 | 0.08 | [-0.45, -0.12] | -3.41 | < .001", + "female | 2008 | -0.26 | 0.06 | [-0.37, -0.15] | -4.47 | < .001", + "female | 2009 | -0.24 | 0.10 | [-0.42, -0.05] | -2.48 | 0.013", + "male | 2007 | -0.46 | 0.10 | [-0.65, -0.26] | -4.60 | < .001", + "male | 2008 | -0.28 | 0.06 | [-0.40, -0.15] | -4.41 | < .001", + "male | 2009 | -0.10 | 0.10 | [-0.30, 0.11] | -0.93 | 0.355", "", "Variable predicted: bill_dep", "Predictors contrasted: bill_len_between, bill_len_within", @@ -86,9 +86,9 @@ test_that("estimate_contrast, context effects, linear", { "", "Level1 | Level2 | year | Difference | SE | 95% CI | z | p", "--------------------------------------------------------------------------", - "male | female | 2007 | 0.17 | 0.13 | [-0.08, 0.43] | 1.33 | 0.183", - "male | female | 2008 | 0.02 | 0.09 | [-0.15, 0.18] | 0.18 | 0.853", - "male | female | 2009 | -0.14 | 0.14 | [-0.42, 0.14] | -0.99 | 0.320", + "male | female | 2007 | -0.17 | 0.13 | [-0.43, 0.08] | -1.33 | 0.183", + "male | female | 2008 | -0.02 | 0.09 | [-0.18, 0.15] | -0.18 | 0.853", + "male | female | 2009 | 0.14 | 0.14 | [-0.14, 0.42] | 0.99 | 0.320", "", "Variable predicted: bill_dep", "Predictors contrasted: bill_len_between, bill_len_within", @@ -107,7 +107,7 @@ test_that("estimate_contrast, context effects, glm", { se <- coef(summary(m))[2:3, 2] out <- estimate_contrasts(m, c("bill_len_between", "bill_len_within")) - expect_equal(out$Odds_Ratio, exp(b[2] - b[1]), tolerance = 1e-4, ignore_attr = TRUE) + expect_equal(out$Odds_Ratio, exp(b[1] - b[2]), tolerance = 1e-4, ignore_attr = TRUE) expect_true(!is.null(out$p)) output <- capture.output(out) @@ -118,5 +118,5 @@ test_that("estimate_contrast, context effects, glm", { c("bill_len_between", "bill_len_within"), predict = "response" ) - expect_equal(out$Probability, -0.01784138, tolerance = 1e-4, ignore_attr = TRUE) + expect_equal(out$Probability, 0.01784138, tolerance = 1e-4, ignore_attr = TRUE) }) diff --git a/vignettes/practical_context_effect.Rmd b/vignettes/practical_context_effect.Rmd index 528553133..b8fcfe7f8 100644 --- a/vignettes/practical_context_effect.Rmd +++ b/vignettes/practical_context_effect.Rmd @@ -120,7 +120,7 @@ estimate_contrasts(mixed, c("phq4_within", "phq4_between")) |> display(format = "tt") ``` -The output shows a significant contrast of 2.41 between the within- and between-effects. Since the between-effect in our model (-6.13) is stronger (more negative) than the within-effect (-3.72), the context-effect (Between minus Within) is -2.41. +The output shows a significant contrast of -2.41 between the within- and between-effects. Since the between-effect in our model (-6.13) is stronger (more negative) than the within-effect (-3.72), the context-effect (Between minus Within) is -2.41. **What does this mean practically?** @@ -140,9 +140,9 @@ model_parameters(mixed, effects = "fixed") |> display(format = "tt") The results table now shows us whether time has a moderating influence on our effects. To see this, we look at the two interaction terms at the bottom of the table: -- Interaction `time × phq4_within`: The coefficient (0.33) is small and not statistically significant (p = 0.592). This means that the negative effect of individual, temporary fluctuations remains largely stable over time. When a patient's psychological burden acutely increases, their quality of life decreases to a very similar extent at any given time point. +- Interaction `time × phq4_within`: The coefficient (0.33) is small and not statistically significant ($p = 0.592$). This means that the negative effect of individual, temporary fluctuations remains largely stable over time. When a patient's psychological burden acutely increases, their quality of life decreases to a very similar extent at any given time point. -- Interaction `time × phq4_between`: This coefficient (-0.66) is also not statistically significant (p = 0.077). The negative sign suggests that the gap between patients potentially widens slightly over time. The "disadvantage" in quality of life experienced by patients with a generally high psychological baseline burden might further increase over the course of the study compared to less burdened patients. +- Interaction `time × phq4_between`: This coefficient (-0.66) is also not statistically significant ($p = 0.077$). The negative sign suggests that the gap between patients potentially widens slightly over time. The "disadvantage" in quality of life experienced by patients with a generally high psychological baseline burden might further increase over the course of the study compared to less burdened patients. These temporal dynamics can be best understood visually using Estimated Marginal Means. The generated plots confirm the statistical results from the table very clearly. @@ -186,9 +186,9 @@ estimate_contrasts( The contrast analysis reveals a clear and interesting trajectory: the context effect grows substantially stronger as time progresses. -- *At Time 1 (Baseline):* The difference between the within- and between-effect is relatively small (1.32) and not statistically significant (p = 0.188). This indicates that at the beginning of the observations, it does not matter much whether a patient's psychological burden is acute (a temporary spike) or chronic (a generally high baseline). The immediate impact on their Quality of Life is very similar. +- *At Time 1 (Baseline):* The difference between the within- and between-effect is relatively small (-1.32) and not statistically significant ($p = 0.188$). This indicates that at the beginning of the observations, it does not matter much whether a patient's psychological burden is acute (a temporary spike) or chronic (a generally high baseline). The immediate impact on their Quality of Life is very similar. -- *At Time 2 and Time 3:* As the study progresses, the contrast becomes highly significant and the gap widens (increasing to 2.31, then 3.29). +- *At Time 2 and Time 3:* As the study progresses, the contrast becomes highly significant and the gap widens (an absolute increase to 2.31, then 3.29). **What does this mean practically?** @@ -206,7 +206,7 @@ estimate_contrasts( display(format = "tt") ``` -This pairwise comparison table adds a crucial statistical caveat to our visual and descriptive observations. The Difference column here represents the mathematical change in the size of the context effect between two specific time points (e.g., the context effect grew by 0.99 points from Time 1 to Time 2). +This pairwise comparison table adds a crucial statistical caveat to our visual and descriptive observations. The Difference column here represents the mathematical change in the size of the context effect between two specific time points (e.g., the context effect decreased by 0.99 points from Time 1 to Time 2). However, looking at the statistics, you will notice that the estimated difference between any two adjacent time points is exactly identical, yielding the exact same standard error and p-value. @@ -221,7 +221,7 @@ estimate_contrasts(mixed, c("phq4_within", "phq4_between")) |> **What does this mean practically?** -The highly significant overall contrast (2.31, p < .001) confirms that a substantial context effect is at play throughout the entire observation period. +The highly significant overall contrast (-2.31, $p < .001$) confirms that a substantial context effect is at play throughout the entire observation period. In clinical terms, while an acute, temporary spike in psychological symptoms (the within-effect) definitely harms a patient's quality of life, carrying a chronically high baseline burden (the between-effect) takes a significantly heavier toll. A patient who generally suffers from high psychological distress faces an overarching "trait penalty" that consistently depresses their quality of life more severely than mere day-to-day fluctuations would suggest. @@ -246,9 +246,9 @@ estimate_contrasts( The marginal contrasts analysis yields nuanced results that add an important layer to our understanding of the context effect: -- *Low Education:* The contrast (1.69) is not statistically significant (p = 0.192). For these patients, there is no meaningful difference between an acute symptom spike and a chronically high baseline. Both states depress their quality of life similarly. -- *Mid Education:* The contrast (3.92) is large and highly significant (p < .001). This group actually drives the overall context effect we observed in the previous models. For middle-educated patients, a chronically high psychological burden carries a massive additional penalty compared to a temporary acute spike. -- *High Education:* Interestingly, the contrast reverses its sign (-1.76) but is not statistically significant (p = 0.337). This indicates that for highly educated patients, the context effect disappears entirely. +- *Low Education:* The contrast (-1.69) is not statistically significant ($p = 0.192$). For these patients, there is no meaningful difference between an acute symptom spike and a chronically high baseline. Both states depress their quality of life similarly. +- *Mid Education:* The contrast (-3.92) is large and highly significant ($p < .001$). This group actually drives the overall context effect we observed in the previous models. For middle-educated patients, a chronically high psychological burden carries a massive additional penalty compared to a temporary acute spike (their quality of life is decreasing by 3.92 points). +- *High Education:* Interestingly, the contrast reverses its sign (1.76) but is not statistically significant ($p = 0.337$). This indicates that for highly educated patients, the context effect disappears entirely. **What does this mean practically?** @@ -274,8 +274,8 @@ estimate_contrasts( The output now displays the mathematical difference in the size of the context effect between two specific groups. -- *Mid vs. Low (p = 0.154) & High vs. Low (p = 0.124):* The differences involving the low-education group are not statistically significant. The confidence intervals are quite wide, suggesting high variance or a smaller sample size within this specific intersection of the data. -- *High vs. Mid (Difference = -5.69, p = 0.005):* This is the crucial finding. The context effect for the highly educated group is significantly smaller (by 5.69 points) than for the middle-educated group. +- *Mid vs. Low ($p = 0.154$) & High vs. Low ($p = 0.124$):* The differences involving the low-education group are not statistically significant. The confidence intervals are quite wide, suggesting high variance or a smaller sample size within this specific intersection of the data. +- *High vs. Mid (Difference = 5.69, $p = 0.005$):* This is the crucial finding. The context effect for the highly educated group is significantly larger (by 5.69 points) than for the middle-educated group. **What does this mean practically?**