| Title: | Analyze Solomon Four-Group Designs |
|---|---|
| Description: | Tools for planning, analyzing, teaching, and reporting Solomon four-group experiments, introduced by Solomon (1949) <doi:10.1037/h0062958>. The historical analyses are reproduced and labeled as such, from Solomon's improvement scores to the Tests A-I sequence of Walton Braver and Braver (1988) <doi:10.1037/0033-2909.104.1.150> and its published revisions. Contemporary analyses include one generalized linear model for all the groups, of four-group designs and of designs with several treatments, with robust or cluster-robust standard errors, for continuous, binary, and count outcomes; randomization inference; full-information maximum likelihood, following van Engelenburg (1999) <https://eric.ed.gov/?id=ED435692>; observed- and latent-variable structural equation models with 'lavaan'; and equivalence tests of pretest sensitization. Also includes design checks, power and sample-size planning, simulated teaching data, published data sets, and reports in the style of the American Psychological Association, with method-specific references. |
| Authors: | Joshua Uhalt [aut, cre] |
| Maintainer: | Joshua Uhalt <[email protected]> |
| License: | GPL-3 |
| Version: | 0.8.2 |
| Built: | 2026-10-09 16:46:55 UTC |
| Source: | https://github.com/JUhalt/solomonR |
Writes an editable Markdown analysis plan, for preregistration or a
protocol, from a few choices and, optionally, a
plan_solomon() result.
The plan follows the three sections of van 't Veer and Giner-Sorolla's
(2016, Appendix A) preregistration template (hypotheses, methods, and
analysis plan) and names the SPIRIT 2013 item each part answers (Chan et
al., 2013). The Solomon-specific content comes from the package: the four
contrasts, the pretest adjustment in the pretested groups, how to claim
that sensitization is negligible, and how missing posttests are handled.
Text in square brackets is for the researcher to complete.
analysis_plan_solomon( plan = NULL, outcome = "[the primary outcome, measured at posttest]", treatment = "[the treatment, and the control condition]", direction = c("increase", "decrease", "two-sided"), sensitization = c("test", "equivalence", "larger_pretested", "smaller_pretested", "exploratory"), equivalence_bound = NULL, alpha = 0.05, occasions = 1, primary_occasion = NULL, tipping_groups = "treatment", title = "Analysis plan for a Solomon four-group study", file = NULL )analysis_plan_solomon( plan = NULL, outcome = "[the primary outcome, measured at posttest]", treatment = "[the treatment, and the control condition]", direction = c("increase", "decrease", "two-sided"), sensitization = c("test", "equivalence", "larger_pretested", "smaller_pretested", "exploratory"), equivalence_bound = NULL, alpha = 0.05, occasions = 1, primary_occasion = NULL, tipping_groups = "treatment", title = "Analysis plan for a Solomon four-group study", file = NULL )
plan |
Optional result of |
outcome |
Description of the primary outcome, measured at posttest. |
treatment |
Description of the treatment and of the control condition. |
direction |
Expected direction of the treatment effect: |
sensitization |
How the Pretest x Treatment contrast is treated:
|
equivalence_bound |
The smallest sensitization of interest, in
posttest units, for |
alpha |
Significance level of the confirmatory tests. Default 0.05. |
occasions |
Number of posttest occasions, or their labels. With more
than one, the primary analysis is |
primary_occasion |
The occasion whose contrasts are confirmatory, when there are several. Default: the last. |
tipping_groups |
Groups whose imputed posttests are shifted in the
tipping-point sensitivity analysis, as in |
title |
Title of the plan. |
file |
Optional path. When given, the plan is also written there as UTF-8 Markdown. |
What the plan covers.
Hypotheses (SPIRIT item 12). Numbered predictions for the treatment effect and for sensitization. For interactions, the template asks for "the expected shape" (van 't Veer & Giner-Sorolla, 2016, p. 10), so the sensitization hypothesis states which treatment effect is expected to be larger. A claim that sensitization is negligible needs an equivalence test against a smallest effect of interest fixed in advance (Lakens, 2017).
Methods (items 14 and 16a). Randomization to the four groups; the
pretest-posttest interval, since pretest effects can depend on it
(Entwisle, 1961); identical measurement in all groups (French et al.,
2021b, Recommendation 11); and the planned sample, from plan when
given, with its planning values.
Analysis plan (items 20a-c). The model, the confirmatory contrasts, the test of sensitization, the handling of missing posttests, with a tipping-point sensitivity analysis (White et al., 2011), and the checks run before the model.
Deviations (item 25). A section for recording departures from the plan, which are to be reported with the results (Nosek et al., 2018, p. 2602).
What it does not decide. The plan states the package's defaults; it does not choose the hypotheses, the sample size, or the smallest effect of interest, and every sentence can be edited. Prediction and postdiction must stay distinguishable (Nosek et al., 2018, p. 2602), so the plan should be registered before the outcomes are seen.
The design. The plan is for the four-group design: one treatment and a
control, each with and without a pretest. Plans for designs with several
treatments are not yet supported; see fit_solomon_glm() for their
analysis.
The round trip. The returned object records the confirmatory
contrasts. Passing it to report_solomon() as design = list(plan = )
makes the report state whether the sensitization analysis was
pre-specified, from the plan rather than by guessing.
An object of class solomon_analysis_plan: text (the Markdown
lines), settings (the choices, including confirmatory), and date.
Printing it shows the Markdown.
Chan, A.-W., Tetzlaff, J. M., Altman, D. G., Laupacis, A., Gøtzsche, P. C., Krleža-Jerić, K., Hróbjartsson, A., Mann, H., Dickersin, K., Berlin, J. A., Doré, C. J., Parulekar, W. R., Summerskill, W. S. M., Groves, T., Schulz, K. F., Sox, H. C., Rockhold, F. W., Rennie, D., & Moher, D. (2013). SPIRIT 2013 statement: Defining standard protocol items for clinical trials. Annals of Internal Medicine, 158(3), 200–207. https://doi.org/10.7326/0003-4819-158-3-201302050-00583
Entwisle, D. R. (1961). Interactive effects of pretesting. Educational and Psychological Measurement, 21(3), 607–620. https://doi.org/10.1177/001316446102100307
Fitzmaurice, G. M., Laird, N. M., & Ware, J. H. (2011). Applied longitudinal analysis (2nd ed.). Wiley. https://doi.org/10.1002/9781119513469
French, D. P., Miles, L. M., Elbourne, D., Farmer, A., Gulliford, M., Locock, L., Sutton, S., McCambridge, J., & MERIT Collaborative Group. (2021b). Reducing bias in trials from reactions to measurement: The MERIT study including developmental work and expert workshop. Health Technology Assessment, 25(55), 1–72. https://doi.org/10.3310/hta25550
Lakens, D. (2017). Equivalence tests: A practical primer for t tests, correlations, and meta-analyses. Social Psychological and Personality Science, 8(4), 355–362. https://doi.org/10.1177/1948550617697177
Mallinckrodt, C. H., Lane, P. W., Schnell, D., Peng, Y., & Mancuso, J. P. (2008). Recommendations for the primary analysis of continuous endpoints in longitudinal clinical trials. Drug Information Journal, 42(4), 303–319. https://doi.org/10.1177/009286150804200402
Nosek, B. A., Ebersole, C. R., DeHaven, A. C., & Mellor, D. T. (2018). The preregistration revolution. Proceedings of the National Academy of Sciences, 115(11), 2600–2606. https://doi.org/10.1073/pnas.1708274114
van 't Veer, A. E., & Giner-Sorolla, R. (2016). Pre-registration in social psychology—A discussion and suggested template. Journal of Experimental Social Psychology, 67, 2–12. https://doi.org/10.1016/j.jesp.2016.03.004
White, I. R., Horton, N. J., Carpenter, J., & Pocock, S. J. (2011). Strategy for intention to treat analysis in randomised trials with missing outcome data. BMJ, 342, Article d40. https://doi.org/10.1136/bmj.d40
plan_solomon() for the sample size, report_solomon() for the
results, and the R Markdown template "Solomon four-group study"
(rmarkdown::draft("study.Rmd", "solomon-study", package = "solomonR")),
which runs the planned analysis in order.
p <- plan_solomon(delta = 0.4, sens = 0, estimand = "ate") analysis_plan_solomon( plan = p, outcome = "reading comprehension (0-100)", treatment = "a six-week tutoring program, against the usual lessons", sensitization = "equivalence", equivalence_bound = 3 )p <- plan_solomon(delta = 0.4, sens = 0, estimand = "ate") analysis_plan_solomon( plan = p, outcome = "reading comprehension (0-100)", treatment = "a six-week tutoring program, against the usual lessons", sensitization = "equivalence", equivalence_bound = 3 )
Compares the pretest scores of the treated and control pretested groups:
the check of baseline equivalence that a Solomon design allows. It matters
most when groups were not formed by random assignment. In a design with
several treatments, each treatment's pretested group is compared with the
pretested control group.
baseline_solomon( y_pre = NULL, treat = NULL, pretested = NULL, n = NULL, mean = NULL, sd = NULL, conf_level = 0.95, control = NULL, data = NULL )baseline_solomon( y_pre = NULL, treat = NULL, pretested = NULL, n = NULL, mean = NULL, sd = NULL, conf_level = 0.95, control = NULL, data = NULL )
y_pre, treat, pretested
|
Individual data: pretest scores, treatment
indicator, and pretest indicator. Only pretested participants with a
pretest score are used. |
n, mean, sd
|
Alternatively, the pretest sample size, mean, and standard
deviation of the two pretested groups, treated first. With |
conf_level |
Confidence level. Default 0.95. |
control |
The control condition when |
data |
Optional data frame. When supplied, the other data arguments
are looked up in it first, as bare column names ( |
The comparison reports the pretest difference with a t interval (pooled variance) and the standardized difference, Hedges's g, with a confidence interval from the noncentral t distribution (Cumming & Finch, 2001; Kelley, 2007). No equivalence threshold is applied; the estimate and its interval are reported for the reader to judge.
Designs with several treatments: give treat as a factor or character
vector of conditions and name the control with control, or give n,
mean, and sd as vectors named by condition together with control.
Each treatment is then compared with the control, and each comparison
uses only the two groups it compares: their pooled SD, t test, and
Hedges's g are the same as in a four-group analysis of that treatment
and the control. The p-values are not adjusted for the number of
comparisons.
What the design cannot check. The unpretested arms form the posttest-only control group design, which relies on randomization rather than a pretest for the equivalence of its groups (Campbell & Stanley, 1963/1966, p. 25). Without random assignment they form a static-group comparison, for which there are "no formal means of certifying that the groups would have been equivalent" (p. 12). Selection bias in the unpretested comparison, which is the comparison that isolates pretest sensitization, therefore cannot be checked or adjusted for with the study's own data. Edmonds and Kennedy (2017) identify selection bias as the largest threat to internal validity in quasi-experimental research (p. 7) and, with instrumentation, as the threat most common in quasi-experimental Solomon designs (p. 94).
An object of class solomon_baseline with the group statistics,
the difference with its interval and t test, and Hedges's g with its
interval. For a design with several treatments, groups holds the
statistics of every pretested group, comparisons has one row for each
treatment against the control (comparison, difference, std.error,
conf.low, conf.high, statistic, df, p.value, g, g.low,
and g.high), and conditions names the control and the treatments.
Campbell, D. T., & Stanley, J. C. (1966). Experimental and quasi-experimental designs for research. Rand McNally. (Original work published 1963)
Cumming, G., & Finch, S. (2001). A primer on the understanding, use, and calculation of confidence intervals that are based on central and noncentral distributions. Educational and Psychological Measurement, 61(4), 532–574. https://doi.org/10.1177/00131640121971374
Edmonds, W. A., & Kennedy, T. D. (2017). An applied guide to research designs: Quantitative, qualitative, and mixed methods (2nd ed.). SAGE Publications. https://doi.org/10.4135/9781071802779
Kelley, K. (2007). Confidence intervals for standardized effect sizes: Theory, application, and implementation. Journal of Statistical Software, 20(8), 1–24. https://doi.org/10.18637/jss.v020.i08
Mai, N. N., Takahashi, Y., & Oo, M. M. (2020). Testing the effectiveness of transfer interventions using Solomon four-group designs. Education Sciences, 10(4), Article 92. https://doi.org/10.3390/educsci10040092
report_solomon() with design = list(assignment = "nonrandom").
# El Karkri et al. (2025a), Table 7: intact classes, one per condition. pre <- elkarkri2025a[elkarkri2025a$pretested == 1, ] baseline_solomon(n = pre$n, mean = pre$pre_mean, sd = pre$pre_sd) # Mai et al. (2020): two treatments, each compared with the control. baseline_solomon(pre_behavior, condition, pretested, control = "Control", data = mai2020)# El Karkri et al. (2025a), Table 7: intact classes, one per condition. pre <- elkarkri2025a[elkarkri2025a$pretested == 1, ] baseline_solomon(n = pre$n, mean = pre$pre_mean, sd = pre$pre_sd) # Mai et al. (2020): two treatments, each compared with the control. baseline_solomon(pre_behavior, condition, pretested, control = "Control", data = mai2020)
Reports Brown-Forsythe tests of equal posttest variance (Brown & Forsythe,
1974), Shapiro-Wilk normality tests within cells, and a test of
homogeneous pretest-posttest slopes among pretested participants with
complete scores.
check_solomon_assumptions( y_post, treat, pretested, y_pre, control = NULL, data = NULL )check_solomon_assumptions( y_post, treat, pretested, y_pre, control = NULL, data = NULL )
y_post |
numeric posttest |
treat |
0/1 (or logical) treatment indicator; or a factor or
character vector of conditions, with the control named by |
pretested |
0/1 (or logical) pretest indicator |
y_pre |
numeric pretest (NA for unpretested) |
control |
The control condition when |
data |
Optional data frame. When supplied, the other data arguments
are looked up in it first, as bare column names ( |
These results are descriptive. Choosing an analysis according to whether a preliminary assumption test is significant can distort Type I error rates (Zimmerman, 2004), so solomonR does not use them as gates: heteroskedasticity-consistent standard errors are a reasonable default for the unified GLM regardless of these results (Long & Ervin, 2000). A small slope-homogeneity p-value is substantively informative: it suggests that the treatment effect among pretested participants depends on the pretest score.
Designs with several treatments: give treat as a factor or character
vector of conditions and name the control with control. The tests then
cover all 2(k + 1) cells of a design with k treatments (Steyn, 2009): the
Brown-Forsythe tests compare all the posttest cells and the k + 1
unpretested groups, and the slope-homogeneity test is a test on k degrees
of freedom that the pretest-posttest slope is the same in the k + 1
pretested groups.
An object of class solomon_checks with the p-values
brown_forsythe_4cell_p (all four posttest cells),
brown_forsythe_unpre_p (the unpretested cells), shapiro_p_by_cell
(one p-value for each cell, named by the pretest indicator and the
treatment, such as 1.0), and ancova_slope_homogeneity_p. For a
design with several treatments, the test across all the posttest cells
is brown_forsythe_cells_p, the cells of shapiro_p_by_cell are named
by the pretest indicator and the condition, such as 1.RP, and
conditions names the control and the treatments.
Brown, M. B., & Forsythe, A. B. (1974). Robust tests for the equality of variances. Journal of the American Statistical Association, 69(346), 364–367. https://doi.org/10.1080/01621459.1974.10482955
Long, J. S., & Ervin, L. H. (2000). Using heteroscedasticity consistent standard errors in the linear regression model. The American Statistician, 54(3), 217–224. https://doi.org/10.1080/00031305.2000.10474549
Mai, N. N., Takahashi, Y., & Oo, M. M. (2020). Testing the effectiveness of transfer interventions using Solomon four-group designs. Education Sciences, 10(4), Article 92. https://doi.org/10.3390/educsci10040092
Steyn, R. (2009). Re-designing the Solomon four-group: Can we improve on this exemplary model? Design Principles and Practices: An International Journal—Annual Review, 3(1), 383–394. https://doi.org/10.18848/1833-1874/CGP/v03i01/37588
Zimmerman, D. W. (2004). A note on preliminary tests of equality of variances. British Journal of Mathematical and Statistical Psychology, 57(1), 173–181. https://doi.org/10.1348/000711004849222
with(solomon_example, check_solomon_assumptions(y_post, treat, pretested, y_pre)) # A six-group design: two treatments and a control (Mai et al., 2020). check_solomon_assumptions(post_behavior, condition, pretested, pre_behavior, control = "Control", data = mai2020)with(solomon_example, check_solomon_assumptions(y_post, treat, pretested, y_pre)) # A six-group design: two treatments and a control (Mai et al., 2020). check_solomon_assumptions(post_behavior, condition, pretested, pre_behavior, control = "Control", data = mai2020)
Classifies missing values in Solomon design data and explains the
supported response to each kind. Pretest scores are structurally absent
for participants assigned to the unpretested groups: withholding the
pretest is the experimental manipulation (Solomon, 1949), so those values
must never be imputed. Other missing values are incidental and are handled
according to the missing-data literature (Rubin, 1976; Little & Rubin,
2019).
check_solomon_missing( y_post, treat, pretested, y_pre = NULL, control = NULL, data = NULL )check_solomon_missing( y_post, treat, pretested, y_pre = NULL, control = NULL, data = NULL )
y_post |
Numeric posttest scores. |
treat |
Treatment indicator coded 0/1 (or logical); or a factor or
character vector of conditions, with the control named by |
pretested |
Pretest indicator coded 0/1 (or logical). |
y_pre |
Optional numeric pretest scores, missing by design for unpretested participants. |
control |
The control condition when |
data |
Optional data frame. When supplied, the other data arguments
are looked up in it first, as bare column names ( |
Categories:
Structural pretest absence: unpretested participants have no pretest. Unlike planned missing-data designs, in which unmeasured values exist and can be imputed (Graham et al., 2006), an imputed pretest here would describe a measurement that never occurred.
Incidental pretest missingness: pretested participants without a pretest score. solomonR analyses currently use complete cases and warn. Because treatment is randomized, deterministic mean imputation of the pretest (without using treatment or outcome), with a missingness indicator when pretests may not be missing completely at random, retains these participants without biasing the treatment effect (White & Thompson, 2005; Groenwold et al., 2012).
Incidental posttest missingness: missing outcomes. Complete-case analysis is unbiased when missingness is unrelated to the outcome given the variables in the model (Little & Rubin, 2019); attrition that differs across the groups should be reported.
Unexpected pretest scores: pretest values recorded for unpretested participants, which usually indicate a coding or assignment error. They are ignored by solomonR analyses.
Unassigned participants: missing treatment or pretest assignment.
Pretest categories are NA when y_pre is not supplied.
Designs with several treatments: give treat as a factor or character
vector of conditions and name the control with control. The counts are
then given for each of the 2(k + 1) groups of a design with k treatments
(Steyn, 2009): each treatment and the control, with and without a
pretest.
Not supported: this function does not test the missingness mechanism, perform imputation, or provide sensitivity analyses for outcome missingness that depends on unobserved values.
An object of class solomon_missing with by_cell (counts by
Solomon cell), counts (totals by category), pattern ("none",
"structural", "incidental", or "mixed"), and guidance (the
interpretation, supported response, and sources for each category
present). For a design with several treatments, by_cell has one row
for each of the 2(k + 1) groups, its treat column holds the
condition, and conditions names the control and the treatments.
Graham, J. W., Taylor, B. J., Olchowski, A. E., & Cumsille, P. E. (2006). Planned missing data designs in psychological research. Psychological Methods, 11(4), 323–343. https://doi.org/10.1037/1082-989X.11.4.323
Groenwold, R. H. H., White, I. R., Donders, A. R. T., Carpenter, J. R., Altman, D. G., & Moons, K. G. M. (2012). Missing covariate data in clinical research: When and when not to use the missing-indicator method for analysis. Canadian Medical Association Journal, 184(11), 1265–1269. https://doi.org/10.1503/cmaj.110977
Little, R. J. A., & Rubin, D. B. (2019). Statistical analysis with missing data (3rd ed.). Wiley. https://doi.org/10.1002/9781119482260
Mai, N. N., Takahashi, Y., & Oo, M. M. (2020). Testing the effectiveness of transfer interventions using Solomon four-group designs. Education Sciences, 10(4), Article 92. https://doi.org/10.3390/educsci10040092
Rubin, D. B. (1976). Inference and missing data. Biometrika, 63(3), 581–592. https://doi.org/10.1093/biomet/63.3.581
Solomon, R. L. (1949). An extension of control group design. Psychological Bulletin, 46(2), 137–150. https://doi.org/10.1037/h0062958
Steyn, R. (2009). Re-designing the Solomon four-group: Can we improve on this exemplary model? Design Principles and Practices: An International Journal—Annual Review, 3(1), 383–394. https://doi.org/10.18848/1833-1874/CGP/v03i01/37588
White, I. R., & Thompson, S. G. (2005). Adjusting for partially missing baseline measurements in randomized trials. Statistics in Medicine, 24(7), 993–1007. https://doi.org/10.1002/sim.1981
data(solomon_example) # Structural absence only: pretests are absent by design in Groups 3 and 4. with(solomon_example, check_solomon_missing(y_post, treat, pretested, y_pre)) # Mixed: add a lost pretest and a missing posttest. d <- solomon_example d$y_pre[which(d$pretested == 1)[1]] <- NA d$y_post[which(d$pretested == 0)[1]] <- NA with(d, check_solomon_missing(y_post, treat, pretested, y_pre)) # A six-group design: two treatments and a control (Mai et al., 2020). check_solomon_missing(post_behavior, condition, pretested, pre_behavior, control = "Control", data = mai2020)data(solomon_example) # Structural absence only: pretests are absent by design in Groups 3 and 4. with(solomon_example, check_solomon_missing(y_post, treat, pretested, y_pre)) # Mixed: add a lost pretest and a missing posttest. d <- solomon_example d$y_pre[which(d$pretested == 1)[1]] <- NA d$y_post[which(d$pretested == 0)[1]] <- NA with(d, check_solomon_missing(y_post, treat, pretested, y_pre)) # A six-group design: two treatments and a control (Mai et al., 2020). check_solomon_missing(post_behavior, condition, pretested, pre_behavior, control = "Control", data = mai2020)
Fits several Solomon analyses to the same data and lines up their estimates
of the four Solomon contrasts, so that differences in pretest adjustment,
variance assumptions, and reference distributions are visible side by side.
Stating the target quantity explicitly is what makes such comparisons
meaningful (Lundberg et al., 2021).
compare_solomon_methods( y_post, treat, pretested, y_pre = NULL, methods = c("glm", "ml", "classic", "sem"), conf_level = 0.95, data = NULL )compare_solomon_methods( y_post, treat, pretested, y_pre = NULL, methods = c("glm", "ml", "classic", "sem"), conf_level = 0.95, data = NULL )
y_post |
Numeric posttest scores (continuous). |
treat |
Treatment indicator coded 0/1 (or logical). Designs with
several treatments are not supported; see |
pretested |
Pretest indicator coded 0/1 (or logical). |
y_pre |
Optional numeric pretest scores. Maximum likelihood, the classic analyses, and the SEM ANCOVA require them. |
methods |
Analyses to include: any of |
conf_level |
Confidence level for intervals. Default is 0.95. |
data |
Optional data frame. When supplied, the other data arguments
are looked up in it first, as bare column names ( |
An object of class solomon_comparison with results (one row per
method and contrast, with the adjustment, variance assumption, reference
distribution, estimate, standard error, interval, and p-value),
estimands (definitions of the four contrasts), not_compared (analyses
excluded and why), and skipped (requested methods that could not be
fitted and why).
Every row estimates one of four population contrasts in posttest means (treatment minus control): the treatment effect among pretested participants, the treatment effect among unpretested participants, their difference (Pretest x Treatment, or sensitization), and their equal-weighted average. In a randomized Solomon experiment with a continuous outcome, all included estimators target these same contrasts. Pretest adjustment changes precision rather than the target (Lin, 2013), and the variance assumptions and reference distributions change the standard errors and intervals.
Some algebraic identities make this concrete. The unified GLM, maximum likelihood, classic Tests C and H, and the SEM mean structure give the same estimate of the treatment effect among unpretested participants. The unified GLM (with pretest scores), maximum likelihood, and classic Test E give the same pretest-adjusted estimate among pretested participants. Their uncertainty differs.
Analyses that do not estimate a raw-scale Solomon contrast are listed in
not_compared rather than aligned with the others:
perm_solomon() is a randomization test of no treatment effect, not an
interval estimator of the contrasts.
Test I (Walton Braver & Braver, 1988) combines one-tailed p-values.
fit_solomon_sem_latent() estimates contrasts on a latent-variable scale.
Hedges' g from fit_solomon_classic() is a standardized mean difference.
Unsupported: non-continuous outcomes, for which adjusted and unadjusted estimators can target different noncollapsible quantities (Daniel et al., 2021), and clustered designs.
Daniel, R., Zhang, J., & Farewell, D. (2021). Making apples from oranges: Comparing noncollapsible effect estimators and their standard errors after adjustment for different covariate sets. Biometrical Journal, 63(3), 528–557. https://doi.org/10.1002/bimj.201900297
Lin, W. (2013). Agnostic notes on regression adjustments to experimental data: Reexamining Freedman's critique. The Annals of Applied Statistics, 7(1), 295–318. https://doi.org/10.1214/12-AOAS583
Lundberg, I., Johnson, R., & Stewart, B. M. (2021). What is your estimand? Defining the target quantity connects statistical evidence to theory. American Sociological Review, 86(3), 532–565. https://doi.org/10.1177/00031224211004187
Walton Braver, M. C., & Braver, S. L. (1988). Statistical treatment of the Solomon four-group design: A meta-analytic approach. Psychological Bulletin, 104(1), 150–154. https://doi.org/10.1037/0033-2909.104.1.150
fit_solomon_glm(), fit_solomon_ml(), fit_solomon_classic(),
fit_solomon_sem()
data(solomon_example) with( solomon_example, compare_solomon_methods( y_post, treat, pretested, y_pre, methods = c("glm", "ml", "classic") ) )data(solomon_example) with( solomon_example, compare_solomon_methods( y_post, treat, pretested, y_pre, methods = c("glm", "ml", "classic") ) )
The posttest sample size, mean, and standard deviation of the four Solomon groups in a classroom study of the Cognitive Acceleration through Science Education programme (El Karkri et al., 2025a, Table 8, p. 11), and the pretest mean and standard deviation of the two pretested groups (Table 7, p. 10). Numbers reported in the publication are reused with citation.
elkarkri2025aelkarkri2025a
A data frame with 4 rows, one per Solomon group, and 8 variables:
The Solomon group.
Indicators (1 = yes).
Posttest sample size, mean, and standard deviation.
Pretest mean and standard deviation (pretested groups only; the pretest sample sizes equal the posttest ones).
Design and caveats. The authors describe the study as
quasi-experimental: each Solomon group was one intact class, so class and
condition are confounded, and differences between the groups can reflect
the classes as well as the treatment and the pretest. validate_solomon()
flags this design when class membership is supplied. The pretested classes
already differed at pretest (9.61 against 7.86), which
baseline_solomon() reports; the unpretested classes have no pretest.
The authors reported a significant Pretest x Treatment interaction.
Known result. solomon_from_summary() reproduces the published
two-way ANOVA from these numbers within rounding: interaction F(1, 84) =
11.46 against the published 11.482, treatment 6.78 against 6.794, and
pretest 0.18 against 0.186 (pp. 11-12).
El Karkri, M., Quesada, A., & Romero-Ariza, M. (2025a). The dual impact of pretest sensitisation and the cognitive acceleration through science education programme in the Solomon four-group design. Brain Sciences, 16(1), Article 64. https://doi.org/10.3390/brainsci16010064
solomon_from_summary(), baseline_solomon(), kvalem1996
with(elkarkri2025a, solomon_from_summary(n, mean, sd)) pre <- elkarkri2025a[elkarkri2025a$pretested == 1, ] baseline_solomon(n = pre$n, mean = pre$pre_mean, sd = pre$pre_sd)with(elkarkri2025a, solomon_from_summary(n, mean, sd)) pre <- elkarkri2025a[elkarkri2025a$pretested == 1, ] baseline_solomon(n = pre$n, mean = pre$pre_mean, sd = pre$pre_sd)
Tests whether a Solomon contrast, by default the Pretest x Treatment
(sensitization) contrast, is small enough to be considered negligible,
using the two one-sided tests (TOST) procedure (Schuirmann, 1987; Lakens,
2017). A nonsignificant sensitization test is not evidence that
sensitization is absent; an equivalence test against a prespecified
smallest effect size of interest (SESOI) can provide that evidence.
equivalence_solomon( fit, bounds, contrast = "Pretest x Treatment", alpha = 0.05, comparison = NULL, object = deprecated() )equivalence_solomon( fit, bounds, contrast = "Pretest x Treatment", alpha = 0.05, comparison = NULL, object = deprecated() )
fit |
A fit from |
bounds |
Equivalence bounds on the raw posttest scale: one positive
number |
contrast |
Solomon contrast to test. Default is
|
alpha |
Significance level for each one-sided test. Default is 0.05. |
comparison |
For a design with several treatments, the comparison to
test, one of the |
object |
An object of class solomon_equivalence containing the estimate,
standard error, degrees of freedom, both one-sided tests
(t_lower, p_lower, t_upper, p_upper), the equivalence p-value
(p_equivalence), the test against zero (statistic, p_zero), both
confidence intervals, the logical results equivalent, different, and
exceeds_bounds, the outcome, and a plain-language interpretation.
For a design with several treatments, it also holds the comparison,
its weights over the conditions, and the conditions of the fit.
The bounds define the smallest effect size of interest and should be set before the data are examined, for example in a preregistration (Lakens, 2017; Lakens et al., 2018). Justify them substantively, such as the smallest change in posttest scores that would alter a conclusion, or from prior research.
Bounds are on the raw posttest scale. To use a standardized SESOI (for example, d = 0.2), multiply it by a standard deviation fixed in advance, such as one reported in prior studies. Do not use the standard deviation of the current data: the same standardized bound then implies different raw bounds in different samples (Lakens, 2017).
Each one-sided test uses the estimate, standard error, and reference
distribution of the fitted model: t with the model's degrees of freedom for
fit_solomon_glm() (Satterthwaite degrees of freedom with CR2); for
fit_solomon_ml(), the normal distribution with its default Wald inference
or t with Welch-Satterthwaite degrees of freedom with
inference = "satterthwaite". The equivalence p-value is the
larger of the two one-sided p-values, and the matching interval has
confidence level 1 - 2 alpha (90\
The conventional two-sided test against zero is reported alongside, with
its 1 - alpha interval.
Combining the equivalence test with the test against zero gives four outcomes (Lakens, 2017):
"equivalent": statistically equivalent and not different from zero;
"trivial": different from zero but statistically equivalent, so smaller
than the smallest effect size of interest;
"different": different from zero and not statistically equivalent;
"inconclusive": neither different from zero nor statistically
equivalent.
exceeds_bounds is TRUE when the 1 - 2 alpha interval lies entirely
beyond one bound, which rejects effects no larger than the smallest effect
size of interest in that direction (a minimum-effect test; Murphy & Myors,
1999).
For a fit_solomon_glm() fit of a design with several treatments (class
solomon_ngroup), name the comparison to test with comparison, such
as "RP vs Control"; it may be left out only when the fit has a single
comparison. The test uses that comparison's estimate of the chosen
contrast and its standard error. It is not adjusted for the other
comparisons of the design.
Lakens, D. (2017). Equivalence tests: A practical primer for t tests, correlations, and meta-analyses. Social Psychological and Personality Science, 8(4), 355–362. https://doi.org/10.1177/1948550617697177
Lakens, D., Scheel, A. M., & Isager, P. M. (2018). Equivalence testing for psychological research: A tutorial. Advances in Methods and Practices in Psychological Science, 1(2), 259–269. https://doi.org/10.1177/2515245918770963
Murphy, K. R., & Myors, B. (1999). Testing the hypothesis that treatments have negligible effects: Minimum-effect tests in the general linear model. Journal of Applied Psychology, 84(2), 234–248. https://doi.org/10.1037/0021-9010.84.2.234
Schuirmann, D. J. (1987). A comparison of the two one-sided tests procedure and the power approach for assessing the equivalence of average bioavailability. Journal of Pharmacokinetics and Biopharmaceutics, 15(6), 657–680. https://doi.org/10.1007/BF01068419
data(solomon_example) fit <- with(solomon_example, fit_solomon_glm(y_post, treat, pretested, y_pre)) # Illustrative bounds only: half a standard deviation (5 points) on this # test. In a real study, justify the smallest effect size of interest and # fix the bounds before examining the data. equivalence_solomon(fit, bounds = 5) # A six-group design: test one comparison at a time. The bounds here are # again illustrative only. fit6 <- fit_solomon_glm(post_behavior, condition, pretested, pre_behavior, control = "Control", data = mai2020) equivalence_solomon(fit6, bounds = 0.3, comparison = "RP vs Control")data(solomon_example) fit <- with(solomon_example, fit_solomon_glm(y_post, treat, pretested, y_pre)) # Illustrative bounds only: half a standard deviation (5 points) on this # test. In a real study, justify the smallest effect size of interest and # fix the bounds before examining the data. equivalence_solomon(fit, bounds = 5) # A six-group design: test one comparison at a time. The bounds here are # again illustrative only. fit6 <- fit_solomon_glm(post_behavior, condition, pretested, pre_behavior, control = "Control", data = mai2020) equivalence_solomon(fit6, bounds = 0.3, comparison = "RP vs Control")
Reproduces the categorical path described by El Karkri et al. (2025b) for
qualitative outcomes: the treatment comparison is tested separately among
pretested and unpretested participants with Fisher's exact test (Pearson's
chi-square test is also reported), and pretest sensitization is "judged to
exist if a significant effect is observed for pre-tested groups but not for
non-pre-tested groups" (p. 7).
fisher_solomon( y_post, treat, pretested, alpha = 0.05, data = NULL, y = deprecated() )fisher_solomon( y_post, treat, pretested, alpha = 0.05, data = NULL, y = deprecated() )
y_post |
Binary posttest outcome coded 0/1 (or logical). |
treat |
Treatment indicator coded 0/1 (or logical). Designs with
several treatments are not supported; see |
pretested |
Pretest indicator coded 0/1 (or logical). |
alpha |
Significance level for the historical rule. Default 0.05. |
data |
Optional data frame. When supplied, the other data arguments
are looked up in it first, as bare column names ( |
y |
This is provided for teaching and replication. The rule compares
significance, not effects: when the treatment effect is the same in both
pretest conditions, it still declares sensitization whenever the pretested
comparison reaches significance and the unpretested one does not. As Gelman
and Stern (2006) put it, "even large changes in significance levels can
correspond to small, nonsignificant changes in the underlying quantities"
(p. 328). A test of sensitization compares the effects themselves; see
marginal_solomon().
An object of class solomon_fisher with tests (one row per pretest
condition and for both combined: counts, proportions, the uncorrected
Pearson chi-square, and Fisher's exact p-value) and sensitization (the
historical rule's verdict).
El Karkri, M., Quesada, A., & Romero-Ariza, M. (2025b). Methodological aspects of the Solomon four-group design: Detecting pre-test sensitisation and analysing qualitative and quantitative variables in education research. Review of Education, 13(1), Article e70050. https://doi.org/10.1002/rev3.70050
Gelman, A., & Stern, H. (2006). The difference between "significant" and "not significant" is not itself statistically significant. The American Statistician, 60(4), 328–331. https://doi.org/10.1198/000313006X152649
# Kvalem et al. (1996): condom use at most recent intercourse, 6 months. kvalem <- data.frame( treat = c(1, 1, 0, 0), pretested = c(1, 0, 1, 0), events = c(51, 21, 76, 69), n = c(73, 49, 148, 133) ) d <- kvalem[rep(1:4, kvalem$n), c("treat", "pretested")] d$y <- unlist(lapply(1:4, function(i) { rep(c(1, 0), c(kvalem$events[i], kvalem$n[i] - kvalem$events[i])) })) fisher_solomon(y, treat, pretested, data = d)# Kvalem et al. (1996): condom use at most recent intercourse, 6 months. kvalem <- data.frame( treat = c(1, 1, 0, 0), pretested = c(1, 0, 1, 0), events = c(51, 21, 76, 69), n = c(73, 49, 148, 133) ) d <- kvalem[rep(1:4, kvalem$n), c("treat", "pretested")] d$y <- unlist(lapply(1:4, function(i) { rep(c(1, 0), c(kvalem$events[i], kvalem$n[i] - kvalem$events[i])) })) fisher_solomon(y, treat, pretested, data = d)
Reproduces the analysis Solomon (1949) proposed with the design: an
inferred pretest mean for the unpretested groups, an improvement score
for each group, and an interaction term I. It is a historical procedure,
kept to document how the analysis of the design began; the recommended
analysis is
fit_solomon_glm().
fit_solomon_1949( y_post = NULL, treat = NULL, pretested = NULL, y_pre = NULL, post_mean = NULL, pre_mean = NULL, n = NULL, inferred_pretest = c("average", "pooled"), data = NULL )fit_solomon_1949( y_post = NULL, treat = NULL, pretested = NULL, y_pre = NULL, post_mean = NULL, pre_mean = NULL, n = NULL, inferred_pretest = c("average", "pooled"), data = NULL )
y_post, treat, pretested, y_pre
|
Individual data: posttest scores,
training (treatment) and pretest indicators coded 0/1, and pretest
scores, missing by design for unpretested participants. A design with no
participant who is neither pretested nor trained is analyzed as the
three-group design. Designs with several treatments are not supported;
see |
post_mean, pre_mean
|
Alternatively, group means: |
n |
Optional group sizes, in the order of |
inferred_pretest |
|
data |
Optional data frame. When supplied, the other data arguments
are looked up in it first, as bare column names ( |
The three-group design (Solomon, 1949, pp. 141–143, Table I). An experimental group and Control Group I are pretested; the experimental group and Control Group II are trained; all three are posttested. The pretest mean Control Group II would have had is inferred from the pretested groups, i = (a1 + a2) / 2, where a1 and a2 are their pretest means (Tables I–III). Each group's improvement is its posttest mean minus its observed or inferred pretest mean: d1 = b1 - a1, d2 = b2 - a2, and d3 = b3 - i. The interaction is I = d1 - (d2 + d3) (p. 143): the part of the experimental group's improvement not explained by the effect of the pretest alone (d2) and of training alone (d3).
The four-group design (p. 147, Table V). Control Group III, with neither pretest nor training, receives the same inferred pretest, its improvement d4 = b4 - i is attributed to outside events between the two occasions, and the interaction becomes I = d1 - (d2 + d3 - d4).
The inferred pretest. Solomon's text describes it as the grand mean
of the pooled pretested groups (p. 141), and his tables compute it as
(a1 + a2) / 2 (Tables I–III, V). The two agree when the pretested groups
are the same size. inferred_pretest = "average" (the default) follows the
tables; "pooled" weights the two means by their sample sizes, which
requires n or individual data.
No test. Solomon gave standard errors for the observed means but printed the error of d3 as "?" (Tables II–III), and judged the interaction from "an examination of the variabilities" (p. 144). This function therefore reports his point estimates only. With individual data it also reports the standard errors of the observed means, as his tables do.
Relation to the later analysis (a solomonR note, not Solomon's). In the four-group design the inferred pretest cancels, so I = (b1 - b2 - b3 + b4) - (a1 - a2): the posttest interaction contrast of the 2 x 2 analysis, less the pretest difference between the two pretested groups. With random assignment the pretest difference has expectation zero, so I estimates the same Pretest x Treatment interaction as the posttest contrast.
The later verdict. Campbell (1957, p. 303) first rejected the analysis
with an inferred pretest: it restricts the degrees of freedom, violates
independence, and leaves no legitimate test. He recommended the 2 x 2
analysis of variance of the four posttests instead (fit_solomon_classic(),
Test A). Campbell and Stanley (1963/1966, p. 25) repeated the
recommendation and judged Solomon's gain-score suggestions unacceptable.
Solomon and Lessac (1968, p. 147) still used the combined pretest mean of
the pretested groups as the best estimate for the unpretested groups, to
judge whether those groups improved or deteriorated in absolute terms.
An object of class solomon_1949 with design ("three-group"
or "four-group"), groups (a data frame with each group's pretest and
training, size, pretest mean and whether it was observed or inferred,
posttest mean, and improvement, plus standard errors of the observed
means when individual data are given), inferred_pretest, I, and, for
the four-group design, posttest_contrast and pretest_difference.
Campbell, D. T. (1957). Factors relevant to the validity of experiments in social settings. Psychological Bulletin, 54(4), 297–312. https://doi.org/10.1037/h0040950
Campbell, D. T., & Stanley, J. C. (1966). Experimental and quasi-experimental designs for research. Rand McNally. (Original work published 1963)
Solomon, R. L. (1949). An extension of control group design. Psychological Bulletin, 46(2), 137–150. https://doi.org/10.1037/h0062958
Solomon, R. L., & Lessac, M. S. (1968). A control group design for experimental studies of developmental processes. Psychological Bulletin, 70(3, Pt. 1), 145–150. https://doi.org/10.1037/h0026147
solomon1949 for Solomon's data, fit_solomon_classic() for the
later historical tests, and fit_solomon_glm() for the recommended
analysis.
# Solomon's fifth-grade spelling experiment (Table II, p. 144). g5 <- solomon1949[solomon1949$grade == 5, ] fit_solomon_1949(post_mean = g5$mean, pre_mean = g5$pre_mean[1:2], n = g5$n) # The four-group version, from individual data. with(solomon_example, fit_solomon_1949(y_post, treat, pretested, y_pre))# Solomon's fifth-grade spelling experiment (Table II, p. 144). g5 <- solomon1949[solomon1949$grade == 5, ] fit_solomon_1949(post_mean = g5$mean, pre_mean = g5$pre_mean[1:2], n = g5$n) # The four-group version, from individual data. with(solomon_example, fit_solomon_1949(y_post, treat, pretested, y_pre))
Implements the historical Test A-I framework associated with analysis of
the Solomon four-group design. All tests are calculated when possible,
while the historical decision pathway is stored separately.
fit_solomon_classic( y_post, treat, pretested, y_pre, alpha = 0.05, pretested_test = c("ancova", "gain", "repeated"), stouffer = TRUE, stouffer_direction = c("greater", "less"), conf_level = 0.95, flow = c("1988", "1990", "1995"), alpha_allocation = c("none", "method1_conservative", "method1_liberal", "method2_conservative", "method2_liberal"), data = NULL, combine_with_stouffer = deprecated() )fit_solomon_classic( y_post, treat, pretested, y_pre, alpha = 0.05, pretested_test = c("ancova", "gain", "repeated"), stouffer = TRUE, stouffer_direction = c("greater", "less"), conf_level = 0.95, flow = c("1988", "1990", "1995"), alpha_allocation = c("none", "method1_conservative", "method1_liberal", "method2_conservative", "method2_liberal"), data = NULL, combine_with_stouffer = deprecated() )
y_post |
Numeric posttest scores. |
treat |
Treatment indicator coded 0 = control and 1 = treatment.
Designs with several treatments are not supported; see
|
pretested |
Pretest indicator coded 0 = unpretested and 1 = pretested. |
y_pre |
Numeric pretest scores. Values should be missing for participants assigned to the unpretested groups. |
alpha |
Significance level used to reconstruct the historical decision pathway. Default is 0.05. |
pretested_test |
Which historical pretested-group analysis should be
followed in the decision pathway: |
stouffer |
Logical. If |
stouffer_direction |
Direction of the historical one-tailed treatment
hypothesis used for Test I: |
conf_level |
Confidence level for intervals. Default is 0.95. |
flow |
Which published version of the decision sequence to follow.
|
alpha_allocation |
Test-wise significance levels for the historical
sequence.
An allocation requires |
data |
Optional data frame. When supplied, the other data arguments
are looked up in it first, as bare column names ( |
combine_with_stouffer |
The historical sequence includes the four-group posttest factorial model, simple treatment effects, ANCOVA, gain-score analysis, the equivalent two-wave repeated-measures interaction, the posttest-only comparison, and the optional Stouffer meta-analytic combination.
Test I, the Walton Braver & Braver (1988) Stouffer meta-analytic combination, is
included for historical replication and teaching. It converts the
one-tailed p-values of the pretested-groups test and Test H, in the
direction of stouffer_direction, to z and combines them (p. 152). The
combined z is judged by its two-tailed p-value, as in their worked example
(p. 153: z = 2.05, p = .040); the one-tailed value is kept as
p_one_tailed. Later work (see
Sawilowsky et al., 1994) raised concerns about experiment-wise Type I
error when the procedure is used conditionally. Its presence in this function should not be interpreted
as a general contemporary recommendation.
An object of class solomon_classic. The tests
component contains Tests A-I, while path records the historical
decision sequence for the observed data under the chosen flow.
The history component holds the history/maturation comparisons.
The package's replication of the published Type I error rates (issue #51; normal data, 30 per group, 20,000 datasets per condition) found:
Tests A to H reached and rejected at the rates Sawilowsky et al. (1994, Table 2) and Sawilowsky (1996, Table 1) report.
Test I rejected far more often than published. With its two-tailed criterion, the experiment-wise error rates were .137 for the 1988 sequence and .135 for the 1995 sequence, against the published .137 and .125. A post hoc investigation reproduced the published Test I rates only when the two-sided p-values of Tests E and H were converted to z as if one-tailed, a reading that differs from Walton Braver and Braver's (1988, p. 152) definition.
The alpha allocations, with Test I as defined here, gave
experiment-wise error rates of .059, .079, .056, and .081 for
"method1_conservative", "method1_liberal", "method2_conservative",
and "method2_liberal", against Sawilowsky's .054, .072, .057, and .076.
All four exceed their limits of .055 and .075.
Until this version, Test I was judged by the one-tailed p of the combined z. It now follows Walton Braver and Braver's worked example (p. 153), which reports the two-tailed p.
See the article "Historical Tests: Replicating the Published Error Rates".
The history component compares the unpretested control posttest (O6)
with the pretests of the pretested groups (O1 and O3) by independent-samples
t tests, as Mai et al. (2020, p. 8) report. Neither group had received the
treatment when these scores were measured, so a difference estimates the
combined effect of history and maturation between the two occasions
(Campbell & Stanley, 1963/1966, p. 25), provided assignment was random and
the measure is comparable at both occasions. Solomon (1949, pp. 146–148)
introduced the fourth group for this purpose, attributing its change from
the pretest to outside events and the passage of time, and Campbell (1957,
p. 303) first proposed the t test, together with the 2 x 2 analysis of
variance of the posttests that Tests A–D carry out. It is reported as a
historical check, not a test of the treatment.
Tests A-H are t tests (equivalently, F tests with one numerator degree of
freedom) with residual degrees of freedom, and each result carries the
matching confidence interval (conf.low, conf.high). Test I combines
p-values and has no interval. The Groups 3-4 standardized mean difference
(g_post) reports Hedges' g with a noncentral t interval for the
population standardized mean difference (Cumming & Finch, 2001; Kelley,
2007).
Braver, S. L., & Walton Braver, M. C. (1990). Meta-analysis for Solomon four-group designs reconsidered: A reply to Sawilowsky and Markman. Perceptual and Motor Skills, 71(1), 321–322. https://doi.org/10.2466/pms.1990.71.1.321
Campbell, D. T. (1957). Factors relevant to the validity of experiments in social settings. Psychological Bulletin, 54(4), 297–312. https://doi.org/10.1037/h0040950
Campbell, D. T., & Stanley, J. C. (1966). Experimental and quasi-experimental designs for research. Rand McNally. (Original work published 1963)
Cumming, G., & Finch, S. (2001). A primer on the understanding, use, and calculation of confidence intervals that are based on central and noncentral distributions. Educational and Psychological Measurement, 61(4), 532–574. https://doi.org/10.1177/00131640121971374
Huck, S. W., & Sandler, H. M. (1973). A note on the Solomon 4-group design: Appropriate statistical analyses. The Journal of Experimental Education, 42(2), 54–55. https://doi.org/10.1080/00220973.1973.11011460
Kelley, K. (2007). Confidence intervals for standardized effect sizes: Theory, application, and implementation. Journal of Statistical Software, 20(8), 1–24. https://doi.org/10.18637/jss.v020.i08
Mai, N. N., Takahashi, Y., & Oo, M. M. (2020). Testing the effectiveness of transfer interventions using Solomon four-group designs. Education Sciences, 10(4), Article 92. https://doi.org/10.3390/educsci10040092
Sawilowsky, S. S. (1996, June 23). Controlling experiment-wise Type I error of meta-analysis in the Solomon four-group design [Paper presentation]. First International Conference on Multiple Comparisons, Tel Aviv, Israel. https://digitalcommons.wayne.edu/coe_tbf/29/
Sawilowsky, S. S., Kelley, D. L., Blair, R. C., & Markman, B. S. (1994). Meta-analysis and the Solomon four-group design. The Journal of Experimental Education, 62(4), 361–376. https://doi.org/10.1080/00220973.1994.9944140
Solomon, R. L. (1949). An extension of control group design. Psychological Bulletin, 46(2), 137–150. https://doi.org/10.1037/h0062958
Van Breukelen, G. J. P. (2006). ANCOVA versus change from baseline had more power in randomized studies and more bias in nonrandomized studies. Journal of Clinical Epidemiology, 59(9), 920–925. https://doi.org/10.1016/j.jclinepi.2006.02.007
Walton Braver, M. C., & Braver, S. L. (1988). Statistical treatment of the Solomon four-group design: A meta-analytic approach. Psychological Bulletin, 104(1), 150–154. https://doi.org/10.1037/0033-2909.104.1.150
classic <- with(solomon_example, fit_solomon_classic(y_post, treat, pretested, y_pre)) classic # The 1995 revision of the sequence, without Test D (Sawilowsky, 1996). with(solomon_example, fit_solomon_classic(y_post, treat, pretested, y_pre, flow = "1995"))classic <- with(solomon_example, fit_solomon_classic(y_post, treat, pretested, y_pre)) classic # The 1995 revision of the sequence, without Test D (Sawilowsky, 1996). with(solomon_example, fit_solomon_classic(y_post, treat, pretested, y_pre, flow = "1995"))
Fits one generalized linear model to all four Solomon groups and reports
four Solomon contrasts: the equal-weighted average treatment effect, the
Pretest x Treatment (sensitization) contrast, and the treatment effect
within each pretesting condition.
fit_solomon_glm( y_post, treat, pretested, y_pre = NULL, covariates = NULL, robust = c("HC3", "none", "CR2"), cluster = NULL, family = stats::gaussian(), conf_level = 0.95, exposure = NULL, control = NULL, contrasts = "control", adjust = c("holm", "bonferroni", "none"), data = NULL, y = deprecated(), pretest_score = deprecated() )fit_solomon_glm( y_post, treat, pretested, y_pre = NULL, covariates = NULL, robust = c("HC3", "none", "CR2"), cluster = NULL, family = stats::gaussian(), conf_level = 0.95, exposure = NULL, control = NULL, contrasts = "control", adjust = c("holm", "bonferroni", "none"), data = NULL, y = deprecated(), pretest_score = deprecated() )
y_post |
numeric posttest vector |
treat |
0/1 (or logical) treatment indicator (1 = treatment); or, for
a design with several treatments, a factor or character vector of
conditions, with the control named by |
pretested |
0/1 (or logical) pretest indicator (1 = group received pretest) |
y_pre |
numeric pretest vector: the pretest score for pretested
participants and |
covariates |
optional data frame of additional covariates, or, with
|
robust |
character: "HC3" (default), "none", or "CR2" (cluster-robust; requires |
cluster |
optional clustering id (e.g., class/site), one value per
participant. CR2 fits refuse designs in which a Solomon cell contains a
single cluster, because cluster and condition are then confounded; see
|
family |
model family (default gaussian()), given as a family object,
a family function, or its name; or |
conf_level |
confidence level for intervals (default 0.95) |
exposure |
optional positive exposure (for example, observation time)
for each participant, entered as a log offset; requires a log-link family
such as |
control |
the control condition, when |
contrasts |
for designs with several treatments: |
adjust |
for designs with several treatments: the adjustment of the
p-values of each contrast across the comparisons, |
data |
optional data frame. When supplied, the other data arguments
are looked up in it first: give them as bare column names
( |
y, pretest_score
|
When y_pre is supplied, it enters the model as pre_obs, equal
to the pretest score in the pretested groups and 0 in the unpretested
groups, so the structurally absent pretests do not remove Groups 3 and 4.
Regression adjustment for baseline covariates in randomized experiments,
and the case for pairing it with heteroskedasticity-robust standard errors,
is discussed by Lin (2013). Pretested participants with a missing pretest
score are excluded with a warning; incidental missingness is never imputed.
An object of class solomon_glm: a list with the fitted model,
coefficient and contrast tables (including degrees of freedom and
confidence limits conf.low and conf.high), the covariance matrix,
the Pearson dispersion statistic for binomial, Poisson, and
negative-binomial fits, theta (its estimate, standard error, and
) for negative-binomial fits, and the settings
used.
For a design with several treatments, an object of class
solomon_ngroup, with the same elements and these changes: effects
has a comparison column and the adjusted p-values p.adjusted;
omnibus holds the omnibus tests (statistic, df1, df2,
p.value, and reference, "F" or "chisq"); conditions names the
control and the treatments and their model terms; weights holds the
weights of each comparison; and adjust names the adjustment.
robust = "HC3" (default): heteroskedasticity-consistent covariance
(MacKinnon & White, 1985), recommended for routine use and particularly
below about 250 observations (Long & Ervin, 2000; Hayes & Cai, 2007).
Heteroskedasticity is expected in the unified Solomon model: when the
pretest predicts the posttest, adjusting for it reduces residual variance
only in the pretested groups.
robust = "none": conventional model-based covariance.
robust = "CR2": bias-reduced cluster-robust covariance (Bell &
McCaffrey, 2002) with Satterthwaite degrees of freedom (Pustejovsky &
Tipton, 2018), computed with the clubSandwich package. Use this when
participants are nested in clusters such as classrooms or sites. In the
package's simulation of cluster-randomized Solomon designs (issue #19),
CR2 tests exceeded the nominal level with four clusters per arm (Type I
error up to 0.068 with no effect in any cluster); with few clusters, the
cluster-level randomization test of perm_solomon() is preferred.
Tests and confidence intervals use the same reference distribution. For
"HC3" and "none" it is the t distribution with residual degrees of
freedom when the dispersion is estimated, as in Gaussian models, which is
the conventional choice when t approximations are used with robust
standard errors (Imbens & Kolesár, 2016; Rajh-Weber et al., 2025). Families
with a fixed dispersion (binomial, Poisson) use the normal distribution.
With a noncollapsible link (such as the logit) and y_pre, the
link-scale contrasts compare a treatment effect conditional on the pretest
among pretested participants with a marginal effect among unpretested
participants, who have no pretest. When the pretest predicts the outcome,
the Pretest x Treatment contrast is then nonzero even without
sensitization (Daniel et al., 2021): in the package's simulation study
(issue #43) it averaged 0.08 to 0.21 on the log-odds scale with no
sensitization present. Such fits give the classed warning
solomonR_noncollapsible_warning; for binary outcomes, estimate the
Solomon contrasts on a common scale with marginal_solomon(). It takes
the fit of a four-group design: for a design with several treatments,
subset the data to one treatment and the control and fit the subset.
Identity and log links are collapsible and are not affected.
Count outcomes: with family = poisson(), the default HC3 covariance gives
the robust (quasi-likelihood) inference that Cameron and Trivedi (2013)
describe. The Poisson estimator stays consistent when the counts are not
Poisson, provided the mean is correctly specified (p. 72), whereas
model-based standard errors should not be used under overdispersion. The
Pearson dispersion statistic is returned as dispersion for description;
values well above 1 indicate overdispersion. Log-link rate ratios are
collapsible, so the noncollapsibility caution above does not apply.
Use exposure for counts observed over different times or exposures, and
marginal_solomon() for rate differences. No published Solomon study with
a count outcome has been identified, so applying these count-data methods
to the Solomon contrasts is a solomonR extension; its simulation validation
is on issue #44.
family = "negative_binomial" fits the NB2 model, with variance
, by maximum likelihood using MASS::glm.nb()
(Venables & Ripley, 2002). Its coefficient estimates stay consistent when the
counts are not negative binomial, provided the mean is correctly specified,
but its model-based standard errors do not, so robust standard errors are
advised (Cameron & Trivedi, 2013, pp. 84–85); the default HC3 covariance
provides them. The estimated is returned as
theta. When the counts show little overdispersion, does not
converge and a classed warning (solomonR_theta_boundary_warning) is
given. Clustered (CR2) negative-binomial fits are not supported.
In the package's pre-registered simulation (issue #62), which reused the datasets of issue #44, the NB2 fit with HC3 met the coverage and Type I tolerances in 85% of the overdispersed contrasts with 50 or 100 participants per cell, against 82% for robust Poisson. That fell short of the 90% set in advance for recommending it, although its estimates were on average 3.5% more precise with strong overdispersion. Robust Poisson therefore remains the recommendation, and Poisson is preferred when there is no evidence of overdispersion. Model-based NB2 standard errors fell outside the coverage tolerance in 162 of 384 contrasts and should not be used.
The degrees of freedom are returned in the df columns (Inf for normal
reference distributions). Imbens and Kolesár (2016) further recommend
Bell-McCaffrey degrees of freedom for heteroskedasticity-robust intervals;
that refinement is under evaluation. For non-identity links, the contrasts
are on the link scale.
In the package's simulation validation (issues #10 and #22), HC3 intervals for the Solomon contrasts were conservative with 10 or fewer participants per cell (mean coverage of nominal 95% intervals was 0.961 with 6 per cell and 0.958 with 10, and the Pretest x Treatment test had a Type I error of 0.034 with 6 per cell) and close to nominal with 20 or more (mean coverage 0.951 to 0.954).
Confidence intervals for the Wald partial R-squared use the noncentral F method (Steiger, 2004) and are reported only for conventional Gaussian fits; no corresponding interval is available with robust covariance.
A Solomon N-group design crosses k treatments and a control with
pretesting, giving 2(k + 1) groups: six for two treatments and eight for
three (Steyn, 2009). Give treat as a factor or character vector of
conditions and name the control with control. One model is then fitted
to all the groups, with an indicator for each treatment, and the four
Solomon contrasts are estimated for each comparison:
each treatment against the control (contrasts = "control", the
default);
every pair of conditions (contrasts = "pairwise");
or comparisons given as weights over the conditions, such as the main
effects of two treatments crossed factorially:
contrasts = list(Lecture = c(Lecture = 0.5, Both = 0.5, Service = -0.5, None = -0.5)). The weights of each comparison must sum to zero.
Omnibus Wald tests ask whether the conditions differ on each contrast. The Pretest x Condition test asks whether pretesting changes the effect of any treatment.
The p-values of each contrast are adjusted across the comparisons, by
Holm's (1979) procedure by default. It controls the familywise error rate
"for any combination of true hypotheses" (p. 65). The confidence
intervals are not adjusted. The result has class solomon_ngroup.
Published studies with several treatments analyzed them as overlapping
four-group designs: one for each treatment against the control (McCarthy &
Tucker, 2002), or one for each pair of conditions (Mai et al., 2020). Those
analyses reuse the same groups, so their tests are dependent, and each
extra analysis adds to the chance of a false finding. The joint model asks
each question once. In Mai et al.'s (2020) six-group study, the Pretest x
Condition test of the posttests alone (without the pretest as a
covariate), with conventional covariance, gives F(2, 127) = 1.86,
p = .161. fit_solomon_steyn() carries out the sequence of tests Steyn
(2009) proposed for these designs.
The analysis of designs with several
treatments is experimental. In the package's simulation study (issue #45;
112 scenarios with two or three treatments and 10 to 50 participants per
group, 5,000 replications each):
the contrasts were unbiased, and coverage of their 95% intervals was 0.939 to 0.967;
the familywise error rates of the Holm-adjusted comparisons were at most 0.059;
the Pretest x Condition test and the test of the conditions averaged over pretest rejected a true null hypothesis in 0.036 to 0.055 of replications;
with three treatments and 10 participants per group, the omnibus tests of Condition | pretested and Condition | unpretested rejected in 0.055 to 0.069 of replications at the .05 level. The rule for error control set before the study was therefore not met, which is why the analysis is experimental. With groups that small, judge those two questions by the adjusted comparisons.
The study did not cover binary or count outcomes, clustered designs, or comparisons given as weights. It is reported in the article "Designs With Several Treatments: Validating the Joint Model".
Bell, R. M., & McCaffrey, D. F. (2002). Bias reduction in standard errors for linear regression with multi-stage samples. Survey Methodology, 28(2), 169–181.
Cameron, A. C., & Trivedi, P. K. (2013). Regression analysis of count data (2nd ed.). Cambridge University Press. https://doi.org/10.1017/CBO9781139013567
Daniel, R., Zhang, J., & Farewell, D. (2021). Making apples from oranges: Comparing noncollapsible effect estimators and their standard errors after adjustment for different covariate sets. Biometrical Journal, 63(3), 528–557. https://doi.org/10.1002/bimj.201900297
Hayes, A. F., & Cai, L. (2007). Using heteroskedasticity-consistent standard error estimators in OLS regression: An introduction and software implementation. Behavior Research Methods, 39(4), 709–722. https://doi.org/10.3758/BF03192961
Holm, S. (1979). A simple sequentially rejective multiple test procedure. Scandinavian Journal of Statistics, 6(2), 65–70. https://www.jstor.org/stable/4615733
Imbens, G. W., & Kolesár, M. (2016). Robust standard errors in small samples: Some practical advice. The Review of Economics and Statistics, 98(4), 701–712. https://doi.org/10.1162/REST_a_00552
Lin, W. (2013). Agnostic notes on regression adjustments to experimental data: Reexamining Freedman's critique. The Annals of Applied Statistics, 7(1), 295–318. https://doi.org/10.1214/12-AOAS583
Long, J. S., & Ervin, L. H. (2000). Using heteroscedasticity consistent standard errors in the linear regression model. The American Statistician, 54(3), 217–224. https://doi.org/10.1080/00031305.2000.10474549
MacKinnon, J. G., & White, H. (1985). Some heteroskedasticity-consistent covariance matrix estimators with improved finite sample properties. Journal of Econometrics, 29(3), 305–325. https://doi.org/10.1016/0304-4076(85)90158-7
Mai, N. N., Takahashi, Y., & Oo, M. M. (2020). Testing the effectiveness of transfer interventions using Solomon four-group designs. Education Sciences, 10(4), Article 92. https://doi.org/10.3390/educsci10040092
McCarthy, A. M., & Tucker, M. L. (2002). Encouraging community service through service learning. Journal of Management Education, 26(6), 629–647. https://doi.org/10.1177/1052562902238322
Pustejovsky, J. E., & Tipton, E. (2018). Small-sample methods for cluster-robust variance estimation and hypothesis testing in fixed effects models. Journal of Business & Economic Statistics, 36(4), 672–683. https://doi.org/10.1080/07350015.2016.1247004
Rajh-Weber, H., Huber, S. E., & Arendasy, M. (2025). A practice-oriented guide to statistical inference in linear modeling for non-normal or heteroskedastic error distributions. Behavior Research Methods, 57(12), Article 338. https://doi.org/10.3758/s13428-025-02801-4
Solomon, R. L. (1949). An extension of control group design. Psychological Bulletin, 46(2), 137–150. https://doi.org/10.1037/h0062958
Steiger, J. H. (2004). Beyond the F test: Effect size confidence intervals and tests of close fit in the analysis of variance and contrast analysis. Psychological Methods, 9(2), 164–182. https://doi.org/10.1037/1082-989X.9.2.164
Steyn, R. (2009). Re-designing the Solomon four-group: Can we improve on this exemplary model? Design Principles and Practices: An International Journal—Annual Review, 3(1), 383–394. https://doi.org/10.18848/1833-1874/CGP/v03i01/37588
Tipton, E. (2015). Small sample adjustments for robust variance estimation with meta-regression. Psychological Methods, 20(3), 375–393. https://doi.org/10.1037/met0000011
Venables, W. N., & Ripley, B. D. (2002). Modern applied statistics with S (4th ed.). Springer. https://doi.org/10.1007/978-0-387-21706-2
fit <- fit_solomon_glm(y_post, treat, pretested, y_pre, data = solomon_example) fit # The four Solomon contrasts as a data frame. fit$effects # A six-group design: two treatments and a control (Mai et al., 2020). fit6 <- fit_solomon_glm(post_behavior, condition, pretested, pre_behavior, control = "Control", data = mai2020) fit6fit <- fit_solomon_glm(y_post, treat, pretested, y_pre, data = solomon_example) fit # The four Solomon contrasts as a data frame. fit$effects # A six-group design: two treatments and a control (Mai et al., 2020). fit6 <- fit_solomon_glm(post_behavior, condition, pretested, pre_behavior, control = "Control", data = mai2020) fit6
Multiply imputes missing posttests, analyzes each completed data set with
fit_solomon_glm(), and combines the four Solomon contrasts with Rubin's
rules. With delta = 0 the imputations assume the posttests are missing
at random (MAR). A nonzero delta shifts the imputed posttests of each
group by a fixed amount, the delta-adjusted pattern-mixture sensitivity
analysis of Carpenter et al. (2023, section 10.3). tipping_point_solomon()
repeats it over a range of offsets.
fit_solomon_mi( y_post, treat, pretested, y_pre = NULL, delta = 0, m = 100, robust = c("HC3", "none"), conf_level = 0.95, seed = NULL, data = NULL )fit_solomon_mi( y_post, treat, pretested, y_pre = NULL, delta = 0, m = 100, robust = c("HC3", "none"), conf_level = 0.95, seed = NULL, data = NULL )
y_post |
Numeric posttest scores, with |
treat |
Treatment indicator coded 0/1 (or logical). Designs with
several treatments are not supported; see |
pretested |
Pretest indicator coded 0/1 (or logical). |
y_pre |
Optional numeric pretest scores, missing by design for unpretested participants. |
delta |
Offsets added to the imputed posttests, on the posttest scale: one number for all four groups, or four numbers for Groups 1-4 (pretested treatment, pretested control, unpretested treatment, unpretested control). The default, 0, is the MAR analysis. |
m |
Number of imputations. Default 100. |
robust |
Covariance for each completed-data analysis: |
conf_level |
Confidence level. Default 0.95. |
seed |
Optional random-number seed. The global random number state is restored afterwards. |
data |
Optional data frame. When supplied, the other data arguments
are looked up in it first, as bare column names ( |
An object of class solomon_mi with effects (the pooled Solomon
contrasts, with their degrees of freedom, fraction of missing
information fmi, and Monte Carlo standard error mc_se), delta,
m, missing (missing posttests by group), excluded, the
per-imputation estimates and std_errors, and the settings used.
Imputation model. A normal linear regression is fitted separately in each Solomon group to the participants with an observed posttest: on the pretest in the pretested groups, and on a constant in the unpretested groups, which have no pretest by design. The analysis contains the Treatment x Pretest interaction of two fully observed indicators, and imputing separately in the groups they define is the simplest approach to such interactions (Carpenter et al., 2023, section 6.3.5, p. 149).
Proper imputation. For each imputation the residual variance and the coefficients are drawn from their posterior distribution, and the missing posttests are then drawn from the model (Carpenter et al., 2023, pp. 81-83).
Offsets. Each imputed posttest in group j is shifted by
delta[j]: those with a missing posttest are assumed to differ from
those observed by an offset in each group, as in the pattern-mixture
analysis of Little et al. (2012, p. 1358), and "a clinically plausible
amount" is added to the imputed outcomes (White et al., 2011, "Perform
Sensitivity Analyses" section, para. 1).
Analysis and pooling. Each completed data set is analyzed with the
model of fit_solomon_glm() (computed directly, since the design is
the same in every completed data set), and the contrasts are combined
with Rubin's rules:
the mean estimate, with variance W + (1 + 1/m)B (Carpenter et al.,
2023, Eq. 2.16). Tests and intervals use t with the small-sample degrees
of freedom of Barnard and Rubin (1999, as cited in van Buuren, 2018,
Eqs. 2.30-2.32), taking the complete-data residual degrees of freedom
as their starting point.
With fixed offsets, multiple imputation with Rubin's variance is information-anchored: the sensitivity analysis neither adds nor removes information relative to the MAR analysis (Cro et al., 2019; Carpenter et al., 2023, p. 278).
Structural and incidental missingness. Pretests absent by design are
never imputed. Pretested participants with a missing pretest are excluded
with a warning, as in fit_solomon_glm(); check_solomon_missing()
describes the options for them.
Number of imputations. The default m = 100 follows Carpenter et al.
(2023, p. 56), who note that p-values accurate to about .005 need at
least 100 imputations and advise erring "towards too many imputations
rather than too few". With much missing information, more are needed: in
the worked example on mai2020, where the fraction of missing information
is about 0.4, p-values varied by about .01 from one seed to another with
100 imputations. The mc_se column gives the Monte Carlo standard error
of each estimate due to the finite number of imputations.
A simulation study under a protocol posted on issue #82 before any run (24 scenarios, 2,000 replications each; see the article "Missing Posttests: Validating the Sensitivity Analysis") found:
With 60 or more participants per group, coverage of 95% intervals from 0.9415 to 0.9595 and Type I error within 0.040 to 0.060, under missing at random and under the pattern-mixture departures studied when the offsets were right. Bias exceeded 2 Monte Carlo standard errors in 2 of 64 contrasts, by at most 0.011 SD.
With 30 per group, conservative intervals: coverage up to 0.967 and model standard errors 3.9% above the empirical ones on average.
Missing at random: agreement with the complete-case analysis, as theory predicts (Carpenter et al., 2023, p. 256).
Departures that differ between the pretested groups: the analyses that assume missing at random biased the sensitization contrast by 0.10 to 0.16 SD.
Experimental. The study's pre-specified rule for validation, every tolerance met in 90% of cells and in every cell with 60 or more per group, was not met: 84 of 96 cells and 62 of 64.
Carpenter, J. R., Bartlett, J. W., Morris, T. P., Wood, A. M., Quartagno, M., & Kenward, M. G. (2023). Multiple imputation and its application (2nd ed.). Wiley. https://doi.org/10.1002/9781119756118
Cro, S., Carpenter, J. R., & Kenward, M. G. (2019). Information-anchored sensitivity analysis: Theory and application. Journal of the Royal Statistical Society Series A: Statistics in Society, 182(2), 623–645. https://doi.org/10.1111/rssa.12423
Little, R. J., D'Agostino, R., Cohen, M. L., Dickersin, K., Emerson, S. S., Farrar, J. T., Frangakis, C., Hogan, J. W., Molenberghs, G., Murphy, S. A., Neaton, J. D., Rotnitzky, A., Scharfstein, D., Shih, W. J., Siegel, J. P., & Stern, H. (2012). The prevention and treatment of missing data in clinical trials. The New England Journal of Medicine, 367(14), 1355–1360. https://doi.org/10.1056/NEJMsr1203730
van Buuren, S. (2018). Flexible imputation of missing data (2nd ed.). CRC Press. https://doi.org/10.1201/9780429492259
White, I. R., Horton, N. J., Carpenter, J., & Pocock, S. J. (2011). Strategy for intention to treat analysis in randomised trials with missing outcome data. BMJ, 342, Article d40. https://doi.org/10.1136/bmj.d40
tipping_point_solomon(), check_solomon_missing()
d <- solomon_example set.seed(82) d$y_post[sample(nrow(d), 20)] <- NA # Missing at random. fit_solomon_mi(y_post, treat, pretested, y_pre, m = 20, seed = 1, data = d) # Missing posttests in the treatment groups 3 points lower than MAR predicts. fit_solomon_mi(y_post, treat, pretested, y_pre, delta = c(-3, 0, -3, 0), m = 20, seed = 1, data = d)d <- solomon_example set.seed(82) d$y_post[sample(nrow(d), 20)] <- NA # Missing at random. fit_solomon_mi(y_post, treat, pretested, y_pre, m = 20, seed = 1, data = d) # Missing posttests in the treatment groups 3 points lower than MAR predicts. fit_solomon_mi(y_post, treat, pretested, y_pre, delta = c(-3, 0, -3, 0), m = 20, seed = 1, data = d)
Fits the maximum-likelihood regression model described by van Engelenburg
(1999). Pretest information is incorporated for the pretested groups while
structurally missing pretests in the unpretested groups are handled through
a separate residual variance.
fit_solomon_ml( y_post, treat, pretested, y_pre, weights = c("equal"), control = list(), conf_level = 0.95, inference = c("wald", "satterthwaite"), data = NULL )fit_solomon_ml( y_post, treat, pretested, y_pre, weights = c("equal"), control = list(), conf_level = 0.95, inference = c("wald", "satterthwaite"), data = NULL )
y_post |
Numeric posttest scores. |
treat |
Treatment indicator coded 0 = control and 1 = treatment.
Designs with several treatments are not supported; see
|
pretested |
Pretest indicator coded 0 = unpretested and 1 = pretested. |
y_pre |
Numeric pretest scores. These should be missing by design for participants assigned to the unpretested groups. |
weights |
Character. How to define the average treatment effect across
pretest conditions. Currently |
control |
Optional list passed to |
conf_level |
Confidence level for intervals. Default is 0.95. |
inference |
How standard errors, tests, and intervals are computed:
|
data |
Optional data frame. When supplied, the other data arguments
are looked up in it first, as bare column names ( |
The model estimates the treatment effect, pretest effect, Treatment x Pretest interaction, pretest-posttest slope, and separate residual standard deviations for pretested and unpretested participants.
An object of class solomon_ml.
The point estimates are maximum-likelihood estimates, which coincide with separate regressions in the pretested and unpretested groups.
inference = "wald" (default) follows van Engelenburg (1999): standard
errors come from the observed information matrix, and tests and
intervals use a normal reference distribution, the usual large-sample
basis for maximum-likelihood inference.
inference = "satterthwaite" is a small-sample option. Standard errors
use unbiased residual variances within each pretest condition. Contrasts
within one condition use t tests with that condition's residual degrees
of freedom, and contrasts that combine the conditions (the ATE and
Pretest x Treatment) use Welch-Satterthwaite degrees of freedom
(Satterthwaite, 1946; Welch, 1947).
In the package's simulation validation (issues #10 and #22; 84 scenarios with 2,000 replications each, reported in the article "Validating fit_solomon_ml()" on the package website), both options recovered the Solomon contrasts without bias. Wald intervals were too narrow in small samples: mean coverage of nominal 95% intervals was 0.893 with 6 participants per cell, 0.920 with 10, 0.936 with 20, 0.941 with 30, and 0.948 with 100, and the Pretest x Treatment test rejected a true null hypothesis in 9.9% of samples with 6 per cell and 5.9% with 30. The small-sample option had mean coverage of 0.949 to 0.950 and Type I error of 0.050 to 0.053 at every cell size studied, from 6 to 100 per cell.
When the smallest cell has fewer than 40 participants and inference is
not supplied, fit_solomon_ml() issues a warning of class
solomonR_small_sample_warning that suggests the small-sample option.
Supplying inference = "wald" explicitly keeps the default without the
warning. The threshold follows a rule set before the validation results
were examined: 40 is the smallest cell size at which Wald inference had
mean coverage of at least 0.940 and Type I error of at most 0.060, with
equal and unequal residual variances, at that size and every larger size
studied.
Satterthwaite, F. E. (1946). An approximate distribution of estimates of variance components. Biometrics Bulletin, 2(6), 110–114. https://doi.org/10.2307/3002019
van Engelenburg, G. (1999). Statistical analysis for the Solomon four-group design (Research Report 99-06). University of Twente. ERIC. https://eric.ed.gov/?id=ED435692
Welch, B. L. (1947). The generalization of "Student's" problem when several different population variances are involved. Biometrika, 34(1–2), 28–35. https://doi.org/10.1093/biomet/34.1-2.28
# With fewer than 40 participants per cell, use the small-sample # (Satterthwaite) inference; see "Inference options". with(solomon_example, fit_solomon_ml(y_post, treat, pretested, y_pre, inference = "satterthwaite"))# With fewer than 40 participants per cell, use the small-sample # (Satterthwaite) inference; see "Inference options". with(solomon_example, fit_solomon_ml(y_post, treat, pretested, y_pre, inference = "satterthwaite"))
Analyzes a Solomon four-group design with several posttest occasions by
a mixed model for repeated measures (MMRM), and estimates the four
Solomon contrasts at each occasion and the change in pretest
sensitization from the first occasion to the last. The model is
likelihood-based, so it is valid when posttests are missing at random,
for example when participants drop out depending on their earlier
scores (Fitzmaurice et al., 2011, pp. 497, 505). Per-occasion analyses of
the participants still observed, and unweighted generalized estimating
equations, require the stronger assumption that the posttests are missing
completely at random (Liang & Zeger, 1986; Fitzmaurice et al., 2011, pp.
358, 498).
fit_solomon_mmrm( y_post, treat, pretested, id, occasion, y_pre = NULL, df = c("kenward-roger", "satterthwaite"), conf_level = 0.95, data = NULL )fit_solomon_mmrm( y_post, treat, pretested, id, occasion, y_pre = NULL, df = c("kenward-roger", "satterthwaite"), conf_level = 0.95, data = NULL )
y_post |
Numeric posttest scores, one per participant and occasion
(long format), with |
treat |
Treatment indicator coded 0/1 (or logical), the same in every
row of a participant. Designs with several treatments are not supported;
see |
pretested |
Pretest indicator coded 0/1 (or logical), the same in every row of a participant. |
id |
Participant identifier. |
occasion |
Posttest occasion. A factor keeps its level order; otherwise the sorted unique values are used. |
y_pre |
Optional pretest score, the same in every row of a participant and missing by design for unpretested participants. |
df |
Degrees of freedom for tests and intervals: |
conf_level |
Confidence level. Default 0.95. |
data |
Optional data frame. When supplied, the other data arguments
are looked up in it first, as bare column names ( |
An object of class solomon_mmrm with effects (the Solomon
contrasts at each occasion and the change in sensitization), model
(the mmrm fit), covariance (the structure used), observed
(observed posttests by group and occasion), and the settings used.
The specification follows the example of Mallinckrodt et al. (2008, p. 312), adapted to the Solomon design:
Fixed effects. Occasion x Treatment x Pretested, all categorical.
Pretest adjustment. The pretest enters as in fit_solomon_glm():
the score in the pretested groups and 0 in the unpretested groups, with
a separate slope at each occasion ("a full interaction of the covariate
with time", p. 312). Pretests absent by design are never imputed.
Covariance. Unstructured within participant, estimated by restricted maximum likelihood (Laird & Ware, 1982). With a pretest, it is estimated separately for pretested and unpretested participants: the pretest adjustment makes the residual covariance conditional on the pretest in the pretested groups only, so a single shared matrix would be misspecified.
Fallback. If the unstructured model does not converge, the heterogeneous Toeplitz, heterogeneous AR(1), and heterogeneous compound symmetry structures are fitted, and the converged one with the smallest AIC is used (Mallinckrodt et al., 2008, p. 312). The output names the structure used.
Inference. t tests and intervals with Kenward-Roger degrees of freedom and adjusted covariance (Kenward & Roger, 1997, as cited in Fitzmaurice et al., 2011, p. 101), as Mallinckrodt et al. (2008, p. 312) specify, or with Satterthwaite (1946) degrees of freedom. The Kenward-Roger adjustment depends on how the covariance is parameterized; it is computed with the matrix's own elements as the parameters, the form that reproduces SAS PROC MIXED (mmrm's "Kenward-Roger-Linear"; Sabanes Bove et al., 2026). Fitzmaurice et al. (2011, p. 101) note that the small-sample properties of both approximations in longitudinal models "have not been extensively studied"; the simulation study posted on issue #57 compares them in Solomon designs.
The model is fitted with the mmrm package (Sabanes Bove et al., 2026), which must be installed.
A simulation study under a protocol posted on issue #57 before any run (12 scenarios, 2,000 replications each; see the article "Longitudinal Designs: Validating the Repeated-Measures Analysis") generated monotone dropout that depended on the last posttest. With 30 to 120 participants per group:
Coverage and Type I error. With Kenward-Roger degrees of freedom, 95% intervals covered from 0.937 to 0.962 of the time, and Type I error where the true value was zero ranged from 0.041 to 0.0615. Satterthwaite degrees of freedom performed alike.
Bias. The contrasts were unbiased; the largest bias was 0.029 SD.
Normal reference distribution. It gave coverage as low as 0.935 at 30 per group.
Shared covariance. A covariance shared by all four groups misstated the standard errors by up to 12% for the unpretested contrasts and 17% for the pretested ones.
Complete-case analyses. Per-occasion analyses of the participants still observed were biased by up to 0.09 SD at the last occasion.
Experimental. The study's pre-specified rule for choosing the default degrees of freedom, every tolerance met in 90% of cells and in every cell with 60 or more per group, was not met by either approximation (145 of 156 cells each; 97 and 96 of 104), although Monte Carlo error alone makes the second part unlikely to be met even by a correctly calibrated method. Kenward-Roger remains the default, as Mallinckrodt et al. (2008) specify.
Fitzmaurice, G. M., Laird, N. M., & Ware, J. H. (2011). Applied longitudinal analysis (2nd ed.). Wiley. https://doi.org/10.1002/9781119513469
Laird, N. M., & Ware, J. H. (1982). Random-effects models for longitudinal data. Biometrics, 38(4), 963–974. https://doi.org/10.2307/2529876
Liang, K.-Y., & Zeger, S. L. (1986). Longitudinal data analysis using generalized linear models. Biometrika, 73(1), 13–22. https://doi.org/10.1093/biomet/73.1.13
Mallinckrodt, C. H., Lane, P. W., Schnell, D., Peng, Y., & Mancuso, J. P. (2008). Recommendations for the primary analysis of continuous endpoints in longitudinal clinical trials. Drug Information Journal, 42(4), 303–319. https://doi.org/10.1177/009286150804200402
Sabanes Bove, D., Li, L., Dedic, J., Kelkhoff, D., Kunzmann, K., Lang, B. M., Stock, C., Wang, Y., James, D., Sidi, J., Leibovitz, D., Sjoberg, D. D., Krieger, N. I., Panagos, A., & Jones, J. (2026). mmrm: Mixed models for repeated measures (Version 0.3.18) [R package]. https://doi.org/10.32614/CRAN.package.mmrm
Satterthwaite, F. E. (1946). An approximate distribution of estimates of variance components. Biometrics Bulletin, 2(6), 110–114. https://doi.org/10.2307/3002019
fit_solomon_glm() for a single posttest occasion; jordaan2014
and the article "Worked Example: Repeated Posttests" for a published
study with three posttest occasions.
if (requireNamespace("mmrm", quietly = TRUE)) { # Three posttest occasions for the example participants, with dropout. set.seed(57) d <- solomon_example d$id <- seq_len(nrow(d)) long <- do.call(rbind, lapply(1:3, function(t) { x <- d x$occasion <- t x$y_post <- d$y_post - 2 * (t - 1) + rnorm(nrow(d), 0, 4) x })) long$y_post[long$occasion == 3 & runif(nrow(long)) < 0.3] <- NA fit_solomon_mmrm(y_post, treat, pretested, id, occasion, y_pre, data = long) }if (requireNamespace("mmrm", quietly = TRUE)) { # Three posttest occasions for the example participants, with dropout. set.seed(57) d <- solomon_example d$id <- seq_len(nrow(d)) long <- do.call(rbind, lapply(1:3, function(t) { x <- d x$occasion <- t x$y_post <- d$y_post - 2 * (t - 1) + rnorm(nrow(d), 0, 4) x })) long$y_post[long$occasion == 3 & runif(nrow(long)) < 0.3] <- NA fit_solomon_mmrm(y_post, treat, pretested, id, occasion, y_pre, data = long) }
mean-structure (default): 4-group SEM estimating posttest means for P1, P0, U1, U0, and reporting ATE, Sens (Pretest×Treatment), Pre_Eff, Unpre_Eff.
ancova = TRUE: restricts to pretested groups (P1, P0) and fits y_post ~ beta*y_pre with group means; reports the pretested simple effect (Pre_Eff). This avoids structural missingness of y_pre in U1/U0 and matches Huck & Sandler.
fit_solomon_sem( y_post, treat, pretested, y_pre = NULL, equal_var = FALSE, ancova = FALSE, estimator = "MLR", conf_level = 0.95, data = NULL )fit_solomon_sem( y_post, treat, pretested, y_pre = NULL, equal_var = FALSE, ancova = FALSE, estimator = "MLR", conf_level = 0.95, data = NULL )
y_post |
numeric posttest |
treat |
0/1 (or logical) treatment indicator. Designs with several
treatments are not supported; see |
pretested |
0/1 (or logical) pretest indicator |
y_pre |
optional pretest score (required if ancova = TRUE) |
equal_var |
logical; if TRUE, constrain posttest variances equal across groups |
ancova |
logical; if TRUE, fit ANCOVA in pretested groups only (P1 vs P0) |
estimator |
lavaan estimator (default "MLR") |
conf_level |
confidence level for intervals (default 0.95) |
data |
Optional data frame. When supplied, the other data arguments
are looked up in it first, as bare column names ( |
The four-group mean-structure model is saturated, so its global fit indices are not diagnostic. Its contrasts are unadjusted posttest mean differences, whereas the ANCOVA mode adjusts for the pretest within the pretested groups.
Tests and confidence intervals for the contrasts are lavaan's Wald results, which use a large-sample normal reference distribution.
An object of class solomon_sem with mode ("mean" or
"ancova_pretested"), the lavaan fit, the contrasts in effects
(estimate, standard error, z, p value, and confidence interval), the
fitmeasures, and conf_level.
Experimental. Its tests rest on large-sample (MLR) theory, and no
simulation study in the package has yet checked their error rates at
Solomon sample sizes. fit_solomon_glm() is the validated analysis of an
observed outcome. The defaults may change after such a study.
Huck, S. W., & Sandler, H. M. (1973). A note on the Solomon 4-group design: Appropriate statistical analyses. The Journal of Experimental Education, 42(2), 54–55. https://doi.org/10.1080/00220973.1973.11011460
Rosseel, Y. (2012). lavaan: An R package for structural equation modeling. Journal of Statistical Software, 48(2), 1–36. https://doi.org/10.18637/jss.v048.i02
if (requireNamespace("lavaan", quietly = TRUE)) { with(solomon_example, fit_solomon_sem(y_post, treat, pretested, y_pre)) }if (requireNamespace("lavaan", quietly = TRUE)) { with(solomon_example, fit_solomon_sem(y_post, treat, pretested, y_pre)) }
This function provides a fully latent analysis path:
(A) A 4-group SEM that defines a latent POST factor from multiple
indicators and estimates group-specific latent means for
P1, P0, U1, and U0. From these we compute ATE, Sens (Pretest x Treat),
and simple effects on the latent outcome.
(B) Optionally, a 2-group SEM in pretested groups only (P1 vs P0)
with a latent PRE factor and latent POST factor, fitting a latent
ANCOVA (POST ~ PRE), and reporting the pretested simple effect.
fit_solomon_sem_latent( data, post_items, treat, pretested, pre_items = NULL, invariance_post = c("scalar", "metric", "configural"), ancova = FALSE, invariance_pre = c("scalar", "metric", "configural"), estimator = "MLR", std_lv = TRUE, conf_level = 0.95, partial_post = NULL, partial_pre = NULL, check_invariance = TRUE )fit_solomon_sem_latent( data, post_items, treat, pretested, pre_items = NULL, invariance_post = c("scalar", "metric", "configural"), ancova = FALSE, invariance_pre = c("scalar", "metric", "configural"), estimator = "MLR", std_lv = TRUE, conf_level = 0.95, partial_post = NULL, partial_pre = NULL, check_invariance = TRUE )
data |
data.frame containing all variables |
post_items |
character vector of posttest item names (required) |
treat |
0/1 (or logical) treatment indicator (length nrow(data)).
Designs with several treatments are not supported; see
|
pretested |
0/1 (or logical) pretest indicator (length nrow(data)) |
pre_items |
character vector of pretest item names (for ANCOVA branch) |
invariance_post |
measurement invariance for POST; must be "scalar" |
ancova |
logical; if TRUE, also fit latent ANCOVA in pretested groups |
invariance_pre |
measurement invariance for the pretested branch; must be "scalar" |
estimator |
lavaan estimator, default "MLR" (robust) |
std_lv |
logical; if TRUE (default), lavaan's |
conf_level |
confidence level for intervals (default 0.95) |
partial_post, partial_pre
|
Optional freed parameters of the POST or
PRE indicators for a partial-invariance model, in lavaan syntax (for
example, |
check_invariance |
If |
Latent mean contrasts require scalar measurement invariance (equal
loadings and intercepts) across groups (Meredith, 1993; Vandenberg &
Lance, 2000). invariance_post and invariance_pre therefore accept only
"scalar"; configural and metric models are rejected with an explanation.
invariance_solomon() tests invariance across the four groups. If only
some indicators are noninvariant, partial_post and partial_pre free
their parameters for a partial-invariance model, which permits latent mean
comparisons when enough indicators remain invariant (Byrne et al., 1989).
Freed parameters must be chosen on substantive grounds before the analysis
and involve only a minority of the indicators (Vandenberg & Lance, 2000,
p. 38).
Identification: with scalar invariance, the latent POST mean of the unpretested control group (U0) is fixed at 0 and the other latent means are estimated relative to it. In the pretested ANCOVA model, the pretested control group (P0) is the reference. The Solomon contrasts are differences between latent means, so they do not depend on the reference choice.
Tests and confidence intervals for the contrasts are lavaan's Wald results, which use a large-sample normal reference distribution.
An object of class solomon_sem_latent with:
fit_post: lavaan object for the 4-group POST model
effects_post: data.frame of ATE, Sens, Pre_Eff, Unpre_Eff on latent POST
fitmeasures_post: named vector (CFI, RMSEA, SRMR, df)
fit_pre (optional): lavaan object for pretested latent ANCOVA
effects_pre (optional): data.frame with Pre_Eff on latent POST (pretested)
fitmeasures_pre (optional)
invariance: the invariance_solomon() result, or NULL when
the check was not run, and invariance_status, a one-line summary
By default the function first runs invariance_solomon() on the POST
indicators, stores the result in invariance, and prints a one-line
summary. When the chi-square difference test or the change-in-fit
criterion does not support scalar (or, with partial_post, partial
scalar) invariance, it warns with class solomonR_invariance_warning. It
does not refuse the contrasts.
This follows a simulation study whose decision rules were posted on issue #55 before any run (see the article "Latent Contrasts: Validating the Invariance Check"). A criterion would have governed an automatic refusal only if it falsely rejected invariance at a rate of .060 or less in Solomon-sized groups, and none did. With six indicators and 60 participants per group, the false-rejection rates were:
.100 for the scaled chi-square difference test (Satorra & Bentler, 2001);
.178 for Chen's (2007) change-in-fit cutoffs;
.090 when both had to agree.
The warning is therefore a prompt to examine the invariance results, not a verdict. The study also found which kind of noninvariance matters for the Solomon contrasts:
A shift common to both pretested groups. When a pretest shifted an indicator's intercept equally in both pretested groups, the sensitization contrast stayed unbiased, because the shift cancels within the pretested condition.
A shift in one group only. A shift in the unpretested control group
alone biased it (by 0.07 to 0.16 latent standard deviations across the
scenarios studied), and freeing the shifted intercept with
partial_post removed the bias.
Experimental. The issue #55 study found no invariance criterion that holds its false-rejection rate in Solomon-sized groups (see the Invariance check section), so how the check decides may change as better small-sample criteria are published.
Byrne, B. M., Shavelson, R. J., & Muthén, B. (1989). Testing for the equivalence of factor covariance and mean structures: The issue of partial measurement invariance. Psychological Bulletin, 105(3), 456–466. https://doi.org/10.1037/0033-2909.105.3.456
Chen, F. F. (2007). Sensitivity of goodness of fit indexes to lack of measurement invariance. Structural Equation Modeling: A Multidisciplinary Journal, 14(3), 464–504. https://doi.org/10.1080/10705510701301834
Meredith, W. (1993). Measurement invariance, factor analysis and factorial invariance. Psychometrika, 58(4), 525–543. https://doi.org/10.1007/BF02294825
Rosseel, Y. (2012). lavaan: An R package for structural equation modeling. Journal of Statistical Software, 48(2), 1–36. https://doi.org/10.18637/jss.v048.i02
Satorra, A., & Bentler, P. M. (2001). A scaled difference chi-square test statistic for moment structure analysis. Psychometrika, 66(4), 507–514. https://doi.org/10.1007/BF02296192
Vandenberg, R. J., & Lance, C. E. (2000). A review and synthesis of the measurement invariance literature: Suggestions, practices, and recommendations for organizational research. Organizational Research Methods, 3(1), 4–70. https://doi.org/10.1177/109442810031002
if (requireNamespace("lavaan", quietly = TRUE)) { set.seed(55) g <- rep(1:4, each = 120) treat <- c(1, 0, 1, 0)[g] pretested <- c(1, 1, 0, 0)[g] f <- stats::rnorm(480, 0.4 * treat) items <- data.frame(y1 = f + stats::rnorm(480, 0, 0.6), y2 = 0.9 * f + stats::rnorm(480, 0, 0.6), y3 = 0.8 * f + stats::rnorm(480, 0, 0.6), y4 = 0.7 * f + stats::rnorm(480, 0, 0.6)) fit_solomon_sem_latent(items, c("y1", "y2", "y3", "y4"), treat, pretested) }if (requireNamespace("lavaan", quietly = TRUE)) { set.seed(55) g <- rep(1:4, each = 120) treat <- c(1, 0, 1, 0)[g] pretested <- c(1, 1, 0, 0)[g] f <- stats::rnorm(480, 0.4 * treat) items <- data.frame(y1 = f + stats::rnorm(480, 0, 0.6), y2 = 0.9 * f + stats::rnorm(480, 0, 0.6), y3 = 0.8 * f + stats::rnorm(480, 0, 0.6), y4 = 0.7 * f + stats::rnorm(480, 0, 0.6)) fit_solomon_sem_latent(items, c("y1", "y2", "y3", "y4"), treat, pretested) }
Carries out the sequence of tests Steyn (2009) proposed for the Solomon
four-group design and for its extension to several interventions, the
extended Solomon design: k interventions and a control, each with and
without a pretest, giving 2(k + 1) groups. The sequence checks the
threats to internal validity the design can detect (nonequivalent groups,
history and maturation, testing, the pretest-intervention interaction,
instrumentation, regression to the mean, and attrition) before it
compares the interventions. It is a published
proposal, kept for replication and teaching. The package's recommended
analysis is
fit_solomon_glm() with control =, which estimates the
Solomon contrasts of every intervention in one model.
fit_solomon_steyn( y_post, treat, pretested, y_pre = NULL, control = NULL, alpha = 0.05, include_unpretested_control = FALSE, posthoc = c("scheffe", "holm"), data = NULL )fit_solomon_steyn( y_post, treat, pretested, y_pre = NULL, control = NULL, alpha = 0.05, include_unpretested_control = FALSE, posthoc = c("scheffe", "holm"), data = NULL )
y_post |
Numeric posttest scores, with |
treat |
The condition: a 0/1 (or logical) indicator for one
intervention (1 = intervention), or a factor or character vector of
conditions, with the control named by |
pretested |
Pretest indicator coded 0/1 (or logical). |
y_pre |
Optional numeric pretest scores, |
control |
The control condition, when |
alpha |
Significance level of every test in the sequence. Default 0.05. |
include_unpretested_control |
Logical. If |
posthoc |
The post hoc tests of pairs of groups: |
data |
Optional data frame. When supplied, the other data arguments
are looked up in it first, as bare column names ( |
An object of class solomon_steyn, a list with:
equivalence, testing, reliability, regression: tables of
tests for steps 1, 3, 5, and 6. testing adds comparison, term
("Pretest", "Intervention", "Interaction"), and sum_sq;
regression adds var_pre, var_post, and direction.
history: tests, and pattern, the classification of step 2.
classic: summary (one row per intervention: Test A, the path,
and the conclusion) and fits, the fit_solomon_classic() results.
attrition: counts (randomized, observed, and missing posttests in
each group), dropouts (the two-by-two table of dropouts), and
tests.
effects: tests (E1 to E5), groups (for several interventions,
whether each intervention group differs from Od and from Of), and
highest (the intervention with the highest combined posttest mean
in E5, or NA; see the Operationalization section).
path: the steps of step 8 that Steyn's sequence acts on.
conclusions: one plain-language summary for each step.
notes: skipped steps and data notes.
n: counts of participants, posttests, and pretests in each group.
conditions: the control and the interventions.
settings: alpha, include_unpretested_control, posthoc, k,
and pretest (whether pretest scores were supplied).
The tables of tests share the columns step, test, groups (Steyn's
labels with the condition names), n, estimate (the first group's
mean minus the second's for a t test; the mean change for a paired t
test; r for a correlation; the variance ratio; or the difference in
dropout proportions), statistic, reference ("t", "F",
"chisq", or "z"), df1, df2, p.value, p.adjusted (the post
hoc p-value of a pair of groups: Scheffé's, or Holm-adjusted, as
posthoc sets; NA for the other tests), and interpretation
(Steyn's reading, where he gives one). For a post hoc test, statistic
and p.value are the pairwise t with a pooled SD and its unadjusted
p-value; the decisions of the sequence read p.adjusted.
Steyn labels the scores by group: Oa1, Ob1 are the pretest and
posttest of the pretested group of intervention 1 (EG1); Oc, Od the
pretest and posttest of the pretested control (CG1); Oe1 the posttest
of the unpretested group of intervention 1 (CG2.1); and Of the posttest
of the unpretested control (CG3). With one intervention the number is
dropped (Oa, Ob, Oe; EG, CG2). The steps below follow a
pre-publication draft of the article, dated March 2, 2009 (see Source).
In Steyn's order:
Equivalence after randomization. The pretests of the pretested
groups are compared: a t test for one intervention, a one-way ANOVA
otherwise. If they differ, Steyn advises post hoc tests to locate the
difference, an explanation, and reconsidering whether to continue.
With include_unpretested_control = TRUE, a further one-way ANOVA adds
Of, which Steyn suggests when the study is short or history and
maturation are believed negligible.
History and maturation. A paired t test of Oc and Od; a t test
of all the pretests (the Time 1 value for the unpretested control)
against Of; and a one-way ANOVA of Oc, Od, and Of. If Oc
differs from Od and Of, Steyn reads history or maturation; if Od
differs from Oc and Of, the pretest (a testing effect). Steyn
(2009) presents this reading of the three sets of scores (Oc, Od,
and Of) as new.
Testing effect. The pretest main effect in the two-way between-groups ANOVA of the four posttest groups of each intervention and the control.
Pretest-intervention interaction. The decision sequence of Walton
Braver and Braver (1988), fit_solomon_classic(), for each
intervention against the control.
Test-retest reliability and instrumentation. The correlation of
Oc and Od; the paired t test of Oc and Od; and a t test of Oc
and Of.
Regression to the mean. A chi-square test for the variance of
Od against that of Oc. Steyn reads an increase in variance as a
sign of regression to the mean, a threat when groups were selected
for extreme scores.
Attrition. A z test of the dropout proportions of the
intervention groups against the non-intervention groups (CG1 and CG3),
and Steyn's chi-square on the two-by-two table of dropouts,
intervention or not by pretested or not (df = 1). That chi-square asks
whether intervention and pretesting are associated among the dropouts:
whether the dropouts of the intervention groups were pretested more,
or less, often than the dropouts of the non-intervention groups. It
counts dropouts only, so it does not compare dropout rates, and it
depends on how many participants each group started with. To compare
dropout rates by group, see attrition$counts and
check_solomon_missing(), which counts the missing posttests in each
group.
Effects of the interventions. For one intervention: E1, a one-way
ANOVA of the four posttest groups, and E2, a t test of Ob plus Oe
against Od plus Of; Steyn (2009) credits these two comparisons to
his doctoral thesis (Steyn, 2001, as cited in Steyn, 2009). For
several:
E1, a one-way ANOVA of all 2(k + 1) posttest groups;
E2, post hoc tests of every pair of groups, summarized by whether
each intervention group differs from Od and from Of;
E3, a one-way ANOVA of the 2k intervention groups;
E4, for each intervention, a t test of Ob against Oe;
E5, when no E4 test is significant, a one-way ANOVA of the k interventions with their two groups combined, with post hoc tests, which Steyn uses to find which intervention had the greatest effect. When an E4 test is significant, Steyn cautions that internal validity is in question and the groups are not combined.
Every test is computed when the data allow it; path records the steps
Steyn's sequence acts on at alpha. Steps 1, 2, 4, 5, and 6 use the
pretest and are skipped, with a note, when y_pre is NULL.
Steyn's description leaves these choices open. solomonR made them as follows.
t tests. Independent-samples t tests are Student's pooled-variance tests, matching the equal-variance one-way ANOVAs.
Post hoc tests. Steyn (2009) names no post hoc test. In the study
the article describes, Steyn (2005, Table 5.61, p. 153) used Scheffé
tests after the one-way ANOVA of the eight posttest groups, so they are
the default (posthoc = "scheffe"). They are the method of Scheffé
(1953). For a pair of groups among G groups with N scores in all, the
Scheffé statistic is the squared pairwise t divided by G - 1, on G - 1
and N - G degrees of freedom, with the pooled error variance of the
groups in the ANOVA. The pair differs at alpha exactly when
Scheffé's criterion holds: |t| exceeds S, where S^2 is G - 1 times the
upper alpha point of F(G - 1, N - G) (Scheffé, 1953, pp. 87–89, 97).
Scheffé's procedure protects every contrast among the groups, not only
the pairs, so it is conservative when only pairs are compared; for
pairs of equally precise means (equal group sizes), Scheffé
recommended Tukey's method instead (pp. 89, 92–93, 96–97). Because the
F test rejects exactly when some contrast is significant (pp. 87,
95–96), no pair can differ unless the ANOVA of the same groups is
significant, and a significant ANOVA need not yield a pair that
differs; step 2 then reports a pattern Steyn's rule does not cover.
posthoc = "holm" gives pairwise t tests with the same pooled SD and
Holm's (1979) adjustment, the default of stats::pairwise.t.test(),
which covers the pairwise comparisons only. In step 1 the post hoc
tests follow a significant ANOVA of more than two groups; in step 2,
and in step 8 with several interventions (E2 and E5), they are always
computed.
Two-way ANOVA. Type III sums of squares, with effect coding, one analysis for each intervention against the control.
History classification. Two sets "differ" when their post hoc
p-value (Scheffé's, or Holm-adjusted) is below alpha. A
nonsignificant ANOVA gives "no evidence of history, maturation, or a
testing effect"; Oc differing from Od and from Of, which do not
differ, gives "history or maturation"; Od differing from Oc and
from Of, which do not differ, gives "the pretest (a testing effect)";
any other pattern is reported as one Steyn's rule does not cover.
Scores used. The one-way ANOVA of Oc, Od, and Of and the t
test of Oc and Of use every available score in each set. The paired
t test, the correlation, and the variance test use the pretested
controls with both scores.
Variance test. The statistic is (n - 1) times the variance of Od
divided by the variance of Oc, on n - 1 degrees of freedom, with a
two-sided p-value (twice the smaller tail).
Attrition. A participant with a missing posttest is a dropout. "Intervention" means any intervention. The z test pools the two proportions; neither test has a continuity correction. The chi-square is computed on the dropout counts, as Steyn describes; a note is recorded when an expected count is below 5.
"Differs from both control groups" (E2). An intervention group
differs from both when its post hoc p-values against Od and against
Of are both below alpha. The sequence continues to E3 when at least
one intervention group does.
"Greatest effect" (E5). Steyn does not say how the intervention
with the greatest effect is identified. solomonR reports the
intervention with the highest combined posttest mean (highest) and
the post hoc tests of every pair. The highest mean is the greatest
effect only when the interventions raise the scores; when they lower
them, as in Steyn (2005), the greatest effect is the lowest mean.
Read highest with the direction of the outcome and the post hoc
tests. In the English report of that study, Steyn and Mynhardt (2008,
pp. 569–570) ranked the treatments by the difference between treated
and untreated means and by d, from separate 2 x 2 analyses, without a
test of the differences between treatments.
Missing scores. Participants with a missing posttest stay in the data for the attrition step and are left out of the posttest analyses. The pretest analyses use the pretested participants with a pretest.
Tests that cannot be computed. A test of groups that are empty,
too small, or without variation is left out, with a note in notes.
Step 4 uses fit_solomon_classic(flow = "1988") with its defaults
(ANCOVA as the pretested-groups test, and Test I).
Steyn notes that multiple ANOVAs capitalize on chance. The sequence
runs many tests, each at alpha, with no control of the error rate
across them.
A nonsignificant test is not evidence that groups are equivalent, or that a threat is absent.
The one-way ANOVA of Oc, Od, and Of, and its post hoc tests,
treat the paired scores of Oc and Od, which come from the same
participants, as independent. Scheffé's (1953, p. 87) tests take the
covariances of the group means as known; here that of Oc and Od is
taken to be zero.
The chi-square test for the variance treats the variance of Oc as a
known value and ignores the pairing of Oc and Od.
A difference between Ob and Oe (E4) mixes a pretest main effect
with pretest sensitization. Step 4 tests the interaction for each
intervention separately; the joint model (fit_solomon_glm()) tests it
for all the interventions in one model, with adjusted p-values for the
comparisons.
The package's recommended analysis is fit_solomon_glm(control = ).
This function follows a pre-publication draft of Steyn's (2009) article, dated March 2, 2009, which the author provided (R. Steyn, personal communication, September 30, 2026). The published article was not available for comparison. The draft has no page numbers, so none are cited.
We thank Renier Steyn for providing the draft of his article, and for noting that his model is intended for situations with a large amount of data and ample time (R. Steyn, personal communication, September 30, 2026).
Holm, S. (1979). A simple sequentially rejective multiple test procedure. Scandinavian Journal of Statistics, 6(2), 65–70. https://www.jstor.org/stable/4615733
Scheffé, H. (1953). A method for judging all contrasts in the analysis of variance. Biometrika, 40(1–2), 87–104. https://doi.org/10.1093/biomet/40.1-2.87
Steyn, R. (2005). Self-evaluasie en die vorming van selfdoeltreffendheidspersepsies [Self-evaluation and the forming of self-efficacy perceptions] [Doctoral thesis, University of South Africa]. Unisa Institutional Repository. https://hdl.handle.net/10500/1745
Steyn, R. (2009). Re-designing the Solomon four-group: Can we improve on this exemplary model? Design Principles and Practices: An International Journal—Annual Review, 3(1), 383–394. https://doi.org/10.18848/1833-1874/CGP/v03i01/37588
Steyn, R., & Mynhardt, J. (2008). Factors that influence the forming of self-evaluation and self-efficacy perceptions. South African Journal of Psychology, 38(3), 563–573. https://doi.org/10.1177/008124630803800310
Walton Braver, M. C., & Braver, S. L. (1988). Statistical treatment of the Solomon four-group design: A meta-analytic approach. Psychological Bulletin, 104(1), 150–154. https://doi.org/10.1037/0033-2909.104.1.150
fit_solomon_glm() for the recommended analysis,
fit_solomon_classic(), check_solomon_missing(),
report_solomon() for APA 7 text of the results, and steyn2005 for
the summary statistics of Steyn's (2005) eight-group study.
# Six groups: two interventions and a control. fit <- fit_solomon_steyn(post_behavior, condition, pretested, pre_behavior, control = "Control", data = mai2020) fit # Pairwise t tests with Holm's adjustment as the post hoc tests. fit_solomon_steyn(post_behavior, condition, pretested, pre_behavior, control = "Control", posthoc = "holm", data = mai2020) # The four-group design: one intervention. fit_solomon_steyn(y_post, treat, pretested, y_pre, data = solomon_example)# Six groups: two interventions and a control. fit <- fit_solomon_steyn(post_behavior, condition, pretested, pre_behavior, control = "Control", data = mai2020) fit # Pairwise t tests with Holm's adjustment as the post hoc tests. fit_solomon_steyn(post_behavior, condition, pretested, pre_behavior, control = "Control", posthoc = "holm", data = mai2020) # The four-group design: one intervention. fit_solomon_steyn(y_post, treat, pretested, y_pre, data = solomon_example)
Tests whether a set of indicators measures the same construct in the same
way in the four Solomon groups, the condition latent mean contrasts
require (Meredith, 1993). It fits the configural, metric (equal loadings),
and scalar (equal loadings and intercepts) models in the sequence
Vandenberg and Lance (2000, pp. 56–57) recommend and compares each with
the one before it.
invariance_solomon( data, items, treat, pretested, estimator = "MLR", partial = NULL, alpha = 0.05 )invariance_solomon( data, items, treat, pretested, estimator = "MLR", partial = NULL, alpha = 0.05 )
data |
A data frame with the indicators. |
items |
Names of at least three indicators. |
treat, pretested
|
Treatment and pretest indicators (0/1). Designs with
several treatments are not supported; see |
estimator |
lavaan estimator, default |
partial |
Optional character vector of freed parameters (see Partial invariance). |
alpha |
Significance level of the chi-square difference test. Default 0.05. |
An object of class solomon_invariance: the three fits, the fit
indexes in models, the step tests with the decision under each
criterion, the most constrained level supported under each
("configural", "metric", "scalar", or "partial scalar"), and the
cutoffs applied.
Each step compares the more constrained model with the one before it in two ways, and the output gives the decision under each.
Chi-square difference test (noninvariant_chisq): noninvariance
when the difference test rejects at alpha. For the robust estimators
MLR, MLM, and MLMV the difference is scaled (Satorra & Bentler, 2001).
Vandenberg and Lance (2000, p. 46) recommend this test as the primary
criterion, with the change in CFI as a supplement.
Change in fit (noninvariant_chen): noninvariance when CFI drops by
at least .005 and, in addition, RMSEA rises by at least .010 or SRMR by
at least .025 (loadings) or .005 (intercepts), the cutoffs Chen (2007,
pp. 501–502) gives for a total N of 300 or less with unequal group
sizes. For a total N above 300 with equal group sizes they are .010,
.015, and .030 or .010. Chen does not cover the two mixed cases, for
which solomonR uses the small-sample values. Reading "a change in CFI,
supplemented by a change in RMSEA or SRMR" as requiring both is
solomonR's; Chen chose CFI as the main criterion (p. 502). Cheung and
Rensvold (2002, pp. 234–235) favor such changes over the chi-square
difference, which depends on sample size.
The criteria can disagree, and both rest on simulations with two groups
and maximum likelihood estimation of multivariate normal data (Cheung &
Rensvold, 2002, p. 251; Chen, 2007). Chen (2007, p. 502) notes that RMSEA
and SRMR tend to over-reject invariant models when samples are small, as
Solomon groups often are. A simulation study under a protocol posted on
issue #55 found that neither criterion, nor the two together, kept false
rejections of invariance at or below .060 in Solomon-sized groups (see
the article "Latent Contrasts: Validating the Invariance Check"). This
function therefore reports both and decides nothing for the user, and
fit_solomon_sem_latent() runs it and warns, rather than refuses, when a
criterion flags noninvariance. The fit indexes are those of the maximum
likelihood fit, whose estimates MLR shares.
When scalar invariance fails, latent means can still be compared if the
noninvariant parameters are freed and enough indicators stay invariant
(Byrne et al., 1989, p. 458). partial names the freed parameters in
lavaan syntax (for example, "item3 ~ 1" for an intercept). They must be
chosen on substantive grounds, not by searching the data (Byrne et al.,
1989, p. 465), and must involve only a minority of the indicators
(Vandenberg & Lance, 2000, p. 38); at least two indicators must stay
fully invariant. The function never chooses them.
Experimental. The issue #55 study found no criterion that holds its false-rejection rate in Solomon-sized groups (see Two published criteria), so the criteria reported may change as better small-sample criteria are published.
Byrne, B. M., Shavelson, R. J., & Muthén, B. (1989). Testing for the equivalence of factor covariance and mean structures: The issue of partial measurement invariance. Psychological Bulletin, 105(3), 456–466. https://doi.org/10.1037/0033-2909.105.3.456
Chen, F. F. (2007). Sensitivity of goodness of fit indexes to lack of measurement invariance. Structural Equation Modeling: A Multidisciplinary Journal, 14(3), 464–504. https://doi.org/10.1080/10705510701301834
Cheung, G. W., & Rensvold, R. B. (2002). Evaluating goodness-of-fit indexes for testing measurement invariance. Structural Equation Modeling: A Multidisciplinary Journal, 9(2), 233–255. https://doi.org/10.1207/S15328007SEM0902_5
Meredith, W. (1993). Measurement invariance, factor analysis and factorial invariance. Psychometrika, 58(4), 525–543. https://doi.org/10.1007/BF02294825
Satorra, A., & Bentler, P. M. (2001). A scaled difference chi-square test statistic for moment structure analysis. Psychometrika, 66(4), 507–514. https://doi.org/10.1007/BF02296192
Vandenberg, R. J., & Lance, C. E. (2000). A review and synthesis of the measurement invariance literature: Suggestions, practices, and recommendations for organizational research. Organizational Research Methods, 3(1), 4–70. https://doi.org/10.1177/109442810031002
if (requireNamespace("lavaan", quietly = TRUE)) { set.seed(55) g <- rep(1:4, each = 80) treat <- c(1, 0, 1, 0)[g] pretested <- c(1, 1, 0, 0)[g] f <- stats::rnorm(320, 0.4 * treat) items <- data.frame(y1 = f + stats::rnorm(320, 0, 0.6), y2 = 0.9 * f + stats::rnorm(320, 0, 0.6), y3 = 0.8 * f + stats::rnorm(320, 0, 0.6), y4 = 0.7 * f + stats::rnorm(320, 0, 0.6)) invariance_solomon(items, c("y1", "y2", "y3", "y4"), treat, pretested) }if (requireNamespace("lavaan", quietly = TRUE)) { set.seed(55) g <- rep(1:4, each = 80) treat <- c(1, 0, 1, 0)[g] pretested <- c(1, 1, 0, 0)[g] f <- stats::rnorm(320, 0.4 * treat) items <- data.frame(y1 = f + stats::rnorm(320, 0, 0.6), y2 = 0.9 * f + stats::rnorm(320, 0, 0.6), y3 = 0.8 * f + stats::rnorm(320, 0, 0.6), y4 = 0.7 * f + stats::rnorm(320, 0, 0.6)) invariance_solomon(items, c("y1", "y2", "y3", "y4"), treat, pretested) }
The sample sizes, means, and standard deviations of a Solomon four-group design measured on three posttest occasions: an evaluation of a life skills program for young adult male offenders (Jordaan, 2014, Table 7.3, p. 112). The outcomes are the three subscales of the Coping Strategy Indicator. Numbers reported in the publication are reused with citation.
jordaan2014jordaan2014
A data frame with 42 rows, one per subscale, group, and occasion, and 8 variables:
Social support, Problem solving, or Avoidance.
The group's number in the thesis: 1 = program with pretest, 2 = program without pretest, 3 = control with pretest, 4 = control without pretest.
1 for the program groups, 0 for the control groups.
1 if the group was pretested, 0 if not.
Pretest (groups 1 and 3 only), Posttest (after the
program), Follow-up 1 (3 months later), or Follow-up 2 (6 months
later).
Sample size.
Mean and standard deviation.
Design. 120 offenders aged 21 to 25 with long sentences were selected by systematic random sampling in a maximum-security correctional center and assigned at random to the program or the control condition. Half of each condition was assigned at random to be pretested (pp. 86–87). The program ran for six months; the control group followed the center's normal daily activities (p. 87). All groups were tested after the program and again 3 and 6 months later (p. 98).
Attrition. Transfers removed 17 offenders from the program groups and 7 from the control groups, leaving 96 (p. 109). Those 96 completed every posttest: every analysis in the thesis has 92 error degrees of freedom. Because more were lost from the program groups, the groups analyzed are not guaranteed to be comparable, even though they were randomized.
Measures. Each subscale of the Coping Strategy Indicator has 11 items scored from 1 (not at all) to 3 (a lot), so scores range from 11 to 33. High scores on problem solving and on seeking social support, and low scores on avoidance, indicate better coping (p. 92).
Known results. These statistics reproduce, within rounding, the 2 x 2 analyses of variance of the posttests on each occasion (Tables 7.4–7.19, pp. 113–127). The Pretest x Treatment interaction F values are:
Social support: 9.678 (p = .002) after the program, 0.266 at 3 months, and 2.306 at 6 months.
Problem solving: 0.819, 0.563, and 5.556 (p = .021).
Avoidance: 0.373, 0.688, and 0.327.
The thesis followed the decision sequence of Walton Braver and Braver
(1988) on each occasion separately (fit_solomon_classic()). The
correlations between occasions are not reported, so analyses of change
across occasions cannot be reproduced; see the article "Worked Example:
Repeated Posttests".
Jordaan, J. (2014). The development and evaluation of a life skills programme for young adult prisoners [Doctoral thesis, University of the Free State]. KovsieScholar. https://hdl.handle.net/11660/832
Walton Braver, M. C., & Braver, S. L. (1988). Statistical treatment of the Solomon four-group design: A meta-analytic approach. Psychological Bulletin, 104(1), 150–154. https://doi.org/10.1037/0033-2909.104.1.150
solomon_from_summary(), fit_solomon_mmrm(), steyn2005
# Problem solving, 6 months after the program (Table 7.13, p. 121). ps6 <- subset(jordaan2014, subscale == "Problem solving" & occasion == "Follow-up 2") with(ps6, solomon_from_summary(n, mean, sd, treat = treat, pretested = pretested))# Problem solving, 6 months after the program (Table 7.13, p. 121). ps6 <- subset(jordaan2014, subscale == "Problem solving" & occasion == "Follow-up 2") with(ps6, solomon_from_summary(n, mean, sd, treat = treat, pretested = pretested))
The number of students who used condoms at their most recent intercourse, at the 6-month posttest, among students who had had intercourse before the intervention, in each Solomon group of a school-based sex-education trial (Kvalem et al., 1996, p. 42). Numbers reported in the publication are reused with citation.
kvalem1996kvalem1996
A data frame with 4 rows, one per Solomon group, and 5 variables:
The Solomon group.
Indicators (1 = yes).
Students who used condoms at their most recent intercourse.
Students in the group with intercourse before the intervention who answered the 6-month posttest.
Design and caveats. Whole classes were randomized: 30 classes to the
intervention, 15 of them pretested, and 94 to control, 47 of them
pretested (p. 38). The authors analyzed individuals rather than classes
because class sizes varied too much for a class-level analysis (p. 39).
These counts are therefore individual-level, and analyses of them ignore
the clustering; see perm_solomon() for cluster-level inference when
class membership is available.
Known result. Fisher's exact and chi-square comparisons by
fisher_solomon() reproduce the reported pattern: 70% (51/73) against
51% (76/148) among pretested students, chi-square = 6.85, and 43% (21/49)
against 52% (69/133) among unpretested students, chi-square = 1.17
(p. 42).
Kvalem, I. L., Sundet, J. M., Rivø, K. I., Eilertsen, D. E., & Bakketeig, L. S. (1996). The effect of sex education on adolescents' use of condoms: Applying the Solomon four-group design. Health Education Quarterly, 23(1), 34–47. https://doi.org/10.1177/109019819602300103
fisher_solomon(), marginal_solomon(), elkarkri2025a
# One row per student. students <- kvalem1996[rep(seq_len(4), kvalem1996$n), c("pretested", "treat")] students$used <- unlist(Map(function(e, n) rep(1:0, c(e, n - e)), kvalem1996$events, kvalem1996$n)) with(students, fisher_solomon(used, treat, pretested))# One row per student. students <- kvalem1996[rep(seq_len(4), kvalem1996$n), c("pretested", "treat")] students$used <- unlist(Map(function(e, n) rep(1:0, c(e, n - e)), kvalem1996$events, kvalem1996$n)) with(students, fisher_solomon(used, treat, pretested))
The sample size, posttest mean, and standard deviation of the four Solomon groups in one of the first experiments built on the Solomon design: a recorded pro-vivisection talk and a 10-item vivisection questionnaire given to introductory psychology classes (Lana, 1959, Table 2, p. 297). Numbers reported in the publication are reused with citation.
lana1959lana1959
A data frame with 4 rows, one per Solomon group, and 7 variables:
The Solomon group.
Lana's group label (I to IV).
Indicators (1 = yes); treat is the recorded
talk.
Posttest sample size, mean, and standard deviation.
Design. Five classes (156 students) were randomly assigned to five conditions (p. 295). Four form a Solomon design:
Group I. Pretest, then the talk 12 days later, then the posttest.
Group IV. Pretest, then the posttest 12 days later.
Group II. The talk, then the posttest.
Group III. The posttest only.
A fifth group, with a delayed posttest, is not part of the four-group design and is not included. Because whole classes were assigned, class and condition are confounded, as in elkarkri2025a.
Known result. Lana analyzed the posttest means as a two-by-two
analysis of variance (Table 3, p. 297). The treatment effect was
significant, F = 5.35, and the pretest and the interaction were not.
solomon_from_summary() reproduces it within rounding (treatment
F = 5.36 on 1 and 152 df). Lana's sums of squares are on the scale of the
cell means (an unweighted-means analysis). Dividing the package's sums of
squares by the harmonic mean of the cell sizes recovers them, and the F
tests are the same.
Historical note. Lana concluded that the pretest did not sensitize participants to the talk (p. 298), the opposite of Solomon's (1949) spelling result. Together they begin the record that Willson and Putnam (1982) later pooled.
Lana, R. E. (1959). Pretest-treatment interaction effects in attitudinal studies. Psychological Bulletin, 56(4), 293–300. https://doi.org/10.1037/h0044646
solomon_from_summary(), solomon1949, elkarkri2025a
lana1959 with(lana1959, solomon_from_summary(n, mean, sd))lana1959 with(lana1959, solomon_from_summary(n, mean, sd))
Individual-level data from a Solomon six-group study of interventions to support the transfer of time-management training: pretesting crossed with relapse prevention, proximal plus distal goal setting, and a control condition (Mai et al., 2020). The data were published as the article's supplementary material and are redistributed under its Creative Commons Attribution 4.0 license (see License).
mai2020mai2020
A data frame with 211 rows, one per participant, and 6 variables:
Row number in the published file.
Female or Male.
1 if assigned to be pretested, 0 if not.
RP (relapse prevention), GS (proximal plus distal
goal setting), or Control.
Self-reported time-management behavior before the workshop (pretested groups only).
Self-reported time-management behavior after the workshop (see Details for the timing); missing for participants who did not answer.
Design. Final-year students at a management college took a three-hour time-management workshop.
Pretesting. Before the workshop, they were "randomly assigned into either the pretested or unpretested groups based on their roll numbers" (p. 5). The article does not say how roll numbers were used.
Interventions. After it, they were randomly assigned to relapse prevention (RP), goal setting (GS), or control (p. 6).
Measures. Self-reported time-management behavior was measured before the workshop in the pretested groups and 10 weeks after it in all groups (p. 7; the note to Table 3 on p. 8 says eight weeks).
Every pair of conditions forms a Solomon four-group design. The authors
analyzed three such pairs, reusing groups across them. fit_solomon_glm()
with control = "Control" fits one model to all six groups (see the
examples and the article "Designs With Several Treatments").
Sample and attrition. The file has 211 participants, and the article reports 210 (p. 5). 133 answered the posttest, with attrition that differed by group (see the example). The unpretested groups have no pretest by design.
Scale. pre_behavior and post_behavior are the authors' scale
scores for the 30 self-report items. The article describes the response
scale as running from 1 (always) to 5 (never) (p. 7). The value labels in
the data file run from 1 (never) to 5 (always). The scores are not the
simple means of the 30 items in the file, so the items are not included.
Known results. The two-by-two ANOVAs of the posttest scores reproduce the authors' Table 4 (p. 8). For relapse prevention against control, the Pretest x Treatment sum of squares is 0.508, the error sum of squares 13.347, and F = 3.461. The history checks of their Table 5 (p. 8) and the ANCOVAs of the first two comparisons in their Table 7 (p. 9) are reproduced as well. The third ANCOVA, relapse prevention against goal setting, gives the published difference of -0.219 with p = .044 against the published .046. The published cell statistics of their Table 6 do not match the data (see issue #53). The article "Worked Example: A Published Solomon Study" carries the relapse-prevention comparison through the package's analyses.
We thank Nu Nu Mai, Yoshi Takahashi, and Mon Mon Oo for making their data publicly available with their article. For the study's design, measures, and findings, read the published article (Mai et al., 2020, cited under Source).
The data are © 2020 by the authors (Nu Nu Mai, Yoshi Takahashi, and Mon Mon
Oo) and are published with the
article under the Creative Commons Attribution 4.0 International license
(https://creativecommons.org/licenses/by/4.0/). MDPI's open access
policy (https://www.mdpi.com/openaccess) states that its articles,
"including their data, graphics, and
supplementary material", may be reused with attribution. Changes made in
solomonR: 6 of the 117 variables in the published file are kept, renamed,
and recoded to factors or 0/1 indicators, and an id column is added. The
original file and the script that builds this data set are in the
package's data-raw folder on GitHub. See also inst/COPYRIGHTS.
Mai, N. N., Takahashi, Y., & Oo, M. M. (2020). Testing the effectiveness of transfer interventions using Solomon four-group designs. Education Sciences, 10(4), Article 92. https://doi.org/10.3390/educsci10040092 (supplementary material, Table S1: dataset.sav)
baseline_solomon(), fit_solomon_glm(), elkarkri2025a,
kvalem1996
# Posttest completion by group. with(mai2020, table(pretested, condition, posttest = !is.na(post_behavior))) # Relapse prevention against control, as a Solomon four-group design. rp <- subset(mai2020, condition %in% c("RP", "Control")) with(rp, fit_solomon_glm(post_behavior, treat = as.integer(condition == "RP"), pretested = pretested, pretest_score = pre_behavior)) # One model for all six groups. fit_solomon_glm(post_behavior, condition, pretested, pre_behavior, control = "Control", data = mai2020)# Posttest completion by group. with(mai2020, table(pretested, condition, posttest = !is.na(post_behavior))) # Relapse prevention against control, as a Solomon four-group design. rp <- subset(mai2020, condition %in% c("RP", "Control")) with(rp, fit_solomon_glm(post_behavior, treat = as.integer(condition == "RP"), pretested = pretested, pretest_score = pre_behavior)) # One model for all six groups. fit_solomon_glm(post_behavior, condition, pretested, pre_behavior, control = "Control", data = mai2020)
Estimates the Solomon contrasts for a binary outcome as risk differences,
risk ratios, or odds ratios, and for a count outcome as rate differences or
rate ratios, comparing marginal risks or rates in every cell.
marginal_solomon( fit, scale = c("difference", "ratio", "odds_ratio"), method = c("bootstrap", "delta", "cluster_summary"), R = 999, seed = NULL, conf_level = fit$conf_level )marginal_solomon( fit, scale = c("difference", "ratio", "odds_ratio"), method = c("bootstrap", "delta", "cluster_summary"), R = 999, seed = NULL, conf_level = fit$conf_level )
fit |
A fit from |
scale |
One or more of |
method |
|
R |
Number of bootstrap resamples (at least 99). Default 999. |
seed |
Optional integer seed for the bootstrap. The global random number state is restored afterwards. |
conf_level |
Confidence level. Defaults to the fit's. |
A logistic model that adjusts for the pretest estimates, among pretested
participants, a treatment effect conditional on the pretest, but among
unpretested participants a marginal effect, because they have no pretest.
Odds ratios are noncollapsible: when the pretest predicts the outcome, a
conditional and a marginal odds ratio differ even without confounding
(Daniel et al., 2021). The logit-scale Pretest x Treatment contrast of
fit_solomon_glm() can therefore be nonzero when there is no
sensitization. This function compares like with like.
Marginal risks are estimated by standardization (Daniel et al., 2021; Localio et al., 2007). In the pretested cells, each pretested participant's risk is predicted under treatment and under control from the fitted logistic model and averaged over all pretested participants. In the unpretested cells the same is done over the unpretested participants; without covariates, these are the observed cell proportions. The contrasts are then:
Treatment | pretested and Treatment | unpretested: the treatment
effect within each pretest condition;
Pretest x Treatment: their difference on the chosen scale (a difference
of risk differences, or a ratio of risk ratios or of odds ratios);
ATE (avg over pretest): the effect in a population with equal numbers
of pretested and unpretested participants, computed from the averaged
risks.
Sensitization depends on the scale: an effect can be modified on the risk-difference scale and not on the ratio scale, or the reverse. Report the scale with every result.
Intervals use a nonparametric bootstrap by default, resampling participants
within each of the four Solomon cells and reporting percentile intervals;
Daniel et al. (2021) and Localio et al. (2007) found the bootstrap performed
better than the delta method, which is available as method = "delta"
(using the fit's covariance matrix, with covariates held fixed). p-values
use the bootstrap or delta-method standard error on the analysis scale:
risk differences, log risk ratios, or log odds ratios. Bootstrap resamples
in which the logistic fit fails (no convergence, a Solomon cell with only
events or only non-events, or a fitted probability within 1e-8 of 0 or 1)
are excluded and counted; when more than 10% fail, intervals are not
reported.
Count outcomes: for a fit with family = poisson() or
family = "negative_binomial", rates per unit of
exposure are standardized in the same way and compared as rate differences
or rate ratios. Log-link rate ratios are collapsible (Daniel et al., 2021),
so they agree with the fitted model's coefficients when there are no other
covariates; rate differences depend on the covariate distribution. For
counts, intervals use the delta method with the fit's (by default robust
HC3) covariance, which Cameron and Trivedi (2013) recommend under
overdispersion; a bootstrap for counts has not been evaluated and is not
offered. The fit's Pearson dispersion statistic, and for negative-binomial
fits the estimated theta, are printed for description. No published
Solomon study with a count outcome has been identified, so this use of
count-data methods is a solomonR extension.
Clustered fits: for binary outcomes fitted with robust = "CR2", the
delta-method standard errors use the CR2 cluster-robust covariance (Bell &
McCaffrey, 2002), and intervals
and tests use the t distribution with Satterthwaite degrees of freedom for
the delta method's linear approximation (Pustejovsky & Tipton, 2018).
Applying those degrees of freedom to the linearized contrast is a solomonR
extension. Only the delta method is offered, because the bootstrap
resamples participants rather than clusters, and a classed warning flags
degrees of freedom below 4 (Tipton, 2015).
In the package's simulation of cluster-randomized Solomon designs (issue #64; 4 to 47 clusters per cell or arm, intracluster correlations of 0.02 and 0.10), these intervals met the coverage and Type I error tolerances for risk differences in 140 of 144 scenario-contrasts and for odds ratios in 137 of 144. The four risk-difference shortfalls, with coverage from 0.935 to 0.961, all had an intracluster correlation of 0.10: 4 or 10 clusters per arm with pretesting assigned within clusters, 15 and 47 clusters per arm with pretesting within clusters, and 15, 15, 47, and 47 clusters per cell. Risk-ratio intervals met the tolerances in 111 of 144 and were conservative with 4 clusters per cell or arm (coverage up to 0.973). A normal reference distribution undercovered (coverage down to 0.880), so it is not used for clustered fits.
In the three shortfalls with pretesting assigned within clusters, the
unweighted comparison of cluster-level summaries (Hayes & Moulton, 2017,
pp. 211–215) met the tolerances, so a cluster-level analysis is the
recommended alternative for risk differences in such designs when
clustering is strong. method = "cluster_summary" computes it, as the
study did: the unweighted mean of the cluster proportions in each arm,
compared with a t interval that uses separate variances and Satterthwaite
degrees of freedom. With pretesting assigned within clusters, each cluster
contributes its pretested and unpretested proportions, and treated and
control clusters are compared. It warns when an arm has fewer than four
clusters, the minimum Hayes and Moulton (2017, p. 128) recommend. The differences were small, and the cluster-level comparison met
the tolerances less often across all scenarios (119 of 144), mostly by
covering more than 96% of the time with 4 clusters per cell or arm.
perm_solomon() gives a cluster-level randomization test. Clustered count
fits have not been validated and are refused; for them, the log rate-ratio
contrasts of fit_solomon_glm() with CR2 covariance and perm_solomon()
account for clustering.
The package's simulation validation of this function is described on issue #43 (binary outcomes), issue #44 (count outcomes), issue #62 (negative-binomial fits), and issue #64 (clustered fits).
An object of class solomon_marginal with effects (one row per
scale and contrast: estimate and interval on the reporting scale, standard
error on the analysis scale, p-value), risks (binary) or rates
(counts, per unit of exposure) for the four cells, and the settings,
including the number of failed bootstrap resamples.
Bell, R. M., & McCaffrey, D. F. (2002). Bias reduction in standard errors for linear regression with multi-stage samples. Survey Methodology, 28(2), 169–181.
Cameron, A. C., & Trivedi, P. K. (2013). Regression analysis of count data (2nd ed.). Cambridge University Press. https://doi.org/10.1017/CBO9781139013567
Daniel, R., Zhang, J., & Farewell, D. (2021). Making apples from oranges: Comparing noncollapsible effect estimators and their standard errors after adjustment for different covariate sets. Biometrical Journal, 63(3), 528–557. https://doi.org/10.1002/bimj.201900297
Hayes, R. J., & Moulton, L. H. (2017). Cluster randomised trials (2nd ed.). Chapman and Hall/CRC. https://doi.org/10.4324/9781315370286
Localio, A. R., Margolis, D. J., & Berlin, J. A. (2007). Relative risks and confidence intervals were easily computed indirectly from multivariable logistic regression. Journal of Clinical Epidemiology, 60(9), 874–882. https://doi.org/10.1016/j.jclinepi.2006.12.001
Pustejovsky, J. E., & Tipton, E. (2018). Small-sample methods for cluster-robust variance estimation and hypothesis testing in fixed effects models. Journal of Business & Economic Statistics, 36(4), 672–683. https://doi.org/10.1080/07350015.2016.1247004
Tipton, E. (2015). Small sample adjustments for robust variance estimation with meta-regression. Psychological Methods, 20(3), 375–393. https://doi.org/10.1037/met0000011
fit_solomon_glm(), fisher_solomon()
d <- solomon_example d$passed <- as.integer(d$y_post > 55) fit <- with(d, fit_solomon_glm(passed, treat, pretested, y_pre, family = binomial())) marginal_solomon(fit, method = "delta") marginal_solomon(fit, R = 499, seed = 1) # A count outcome observed over different exposure times. set.seed(2) d$days <- runif(nrow(d), 5, 15) d$visits <- rpois(nrow(d), d$days * exp(-1.5 + 0.3 * d$treat)) counts <- with(d, fit_solomon_glm(visits, treat, pretested, y_pre, family = poisson(), exposure = days)) marginal_solomon(counts)d <- solomon_example d$passed <- as.integer(d$y_post > 55) fit <- with(d, fit_solomon_glm(passed, treat, pretested, y_pre, family = binomial())) marginal_solomon(fit, method = "delta") marginal_solomon(fit, R = 499, seed = 1) # A count outcome observed over different exposure times. set.seed(2) d$days <- runif(nrow(d), 5, 15) d$visits <- rpois(nrow(d), d$days * exp(-1.5 + 0.3 * d$treat)) counts <- with(d, fit_solomon_glm(visits, treat, pretested, y_pre, family = poisson(), exposure = days)) marginal_solomon(counts)
p_to_z(p)p_to_z(p)
p |
numeric vector of p-values assumed one-tailed and aligned in the same direction |
numeric Z-scores
Stouffer, S. A., Suchman, E. A., DeVinney, L. C., Star, S. A., & Williams, R. M., Jr. (1949). The American soldier: Adjustment during army life (Vol. 1). Princeton University Press.
p_to_z(c(0.05, 0.025, 0.5))p_to_z(c(0.05, 0.025, 0.5))
Performs a randomization-based test by permuting treatment assignment
within pretest strata. This preserves the Solomon four-group design while
generating the null distribution for a selected treatment contrast.
Participants are permuted in unclustered designs and whole clusters in
clustered ones.
perm_solomon( fit, contrast = "ATE (avg over pretest)", reps = 5000L, seed = NULL, return_dist = FALSE, statistic = c("studentized", "difference"), object = deprecated() )perm_solomon( fit, contrast = "ATE (avg over pretest)", reps = 5000L, seed = NULL, return_dist = FALSE, statistic = c("studentized", "difference"), object = deprecated() )
fit |
An object returned by |
contrast |
Character string identifying the contrast to test. One of
|
reps |
Number of permutations. Default is 5000. In clustered designs
with at most |
seed |
Optional random-number seed for reproducibility. The global random-number state is restored when the function exits. |
return_dist |
Logical. If |
statistic |
|
object |
Unclustered designs. Treatment labels of participants are permuted
within pretest strata and the model is refitted for each permutation. The
default statistic is the HC3-studentized contrast. The permutation
p-value is a valid test of the sharp null hypothesis that treatment has no
effect for any participant; the +1 correction keeps the Monte Carlo
p-value from being zero (Phipson & Smyth, 2010). That result is for the
count of permuted statistics at least as extreme as the observed one, so
a permutation whose statistic equals the observed one is counted. Such
ties occur when a permutation repeats the observed assignment or swaps
arms of equal size, and often when scores are tied, as with binary
outcomes, counts, and ratings. So that rounding error does not decide,
statistics that differ by less than a small relative tolerance are
treated as equal: 1e-10 for a linear model and 1e-6 for models fitted by
iteration. The tolerance is relative to the observed statistic or, when
that is smaller, to 1 for the studentized statistic and to the largest
permuted difference for the difference statistic. In a model fitted by
iteration, equal fits usually agree to about 1e-7; with a covariate they
can differ by more, most with a link other than the canonical one, and
such a tie can still be missed (issue #134). Studentizing the
statistic makes permutation tests asymptotically robust when only an
average effect is hypothesized to be zero (DiCiccio & Romano, 2017;
Wu & Ding, 2021); for the Pretest x Treatment contrast that robustness
should be regarded as approximate.
Clustered designs. Randomization inference must permute the unit that
was randomized, so for fits with a cluster variable the treatment labels
of whole clusters are permuted. Two assignment mechanisms are supported:
whole clusters assigned to the four Solomon conditions, as in Kvalem et al. (1996), where treatment labels are permuted among clusters within each pretest condition; and
treatment assigned to clusters and pretesting to participants within clusters, where treatment labels are permuted among all clusters and every cluster must contain pretested and unpretested participants.
Designs that assign treatment to participants within clusters are refused, and stratified or restricted randomization of clusters is not supported.
The statistic is built from cluster-level summaries (Gail et al., 1996; Hayes & Moulton, 2017, ch. 10). A Stage 1 model with every term of the fit except treatment (the pretest indicator, the pretest score, covariates and any exposure offset) gives each cluster a covariate-adjusted difference residual: observed minus expected, divided by the number of participants or, for counts, by the total exposure (Hayes & Moulton, 2017, pp. 221–224, following Bennett et al., 2002). Because Stage 1 ignores treatment, the test remains exact under the sharp null hypothesis. When pretesting is assigned within clusters, each cluster has a pretested and an unpretested residual, and each contrast compares treated and control clusters on one combination of the two.
The contrast is estimated from unweighted means of the cluster residuals,
so each cluster counts once (Hayes & Moulton, 2017, pp. 202–205). It
therefore estimates the average effect across clusters, which can differ
from the participant-weighted contrast of fit_solomon_glm() when cluster
sizes vary and effects depend on cluster size. The studentized statistic
divides the contrast by its separate-variances standard error (Hayes &
Moulton, 2017, p. 212), which is the studentization Wu and Ding (2021)
use for weak null hypotheses, applied here with clusters as the units.
Gail et al. (1996, p. 1079) showed that the unstudentized difference can
exceed the nominal level under the weak null hypothesis when the arms have
unequal numbers of clusters and unequal variances.
When the number of possible allocations is at most reps, all of them are
enumerated and the p-value is exact; the smallest attainable p-value is
then reported. Hayes and Moulton (2017, p. 239) note that at least four
clusters per arm are needed for a two-sided p below .05.
Simulation evidence. In the package's pre-registered simulation study (issue #19; 96 scenarios, 2,000 replications each):
Under the sharp null hypothesis, both statistics had Type I errors of at most 0.063, consistent with the exactness of randomization tests. With four clusters per arm, few allocations exist and the test is conservative: the attainable level at .05 is 2/70, about 0.03.
When treatment made treated clusters four times as variable as control
clusters, so that only the average effect was zero, the studentized
statistic's Type I error reached 0.065 with equal numbers of treated and
control clusters, 0.0685 with 15 treated and 47 control clusters per
pretest condition, and 0.0805 with 4 and 8. The difference statistic
reached 0.158 with 15 and 47, as Gail et al. (1996) found for unbalanced
designs. A classed warning (solomonR_unbalanced_clusters_warning) is
therefore given whenever treated and control clusters differ in number.
The CR2 tests of fit_solomon_glm() reached 0.068 with four clusters per
arm even under the sharp null, where this test is exact, so the
permutation test is preferred for designs with few clusters.
A list of class solomon_perm containing the contrast, the
statistic type, the level permuted ("participant" or "cluster"), the
estimated contrast (estimate), the observed statistic (z_obs;
the contrast itself when statistic = "difference"), the permutation
p-value (p_perm), the number of permutations, and whether the
p-value is exact. Clustered fits also return the design, the number of
possible allocations, the smallest attainable p-value when exact, and the
numbers of treated and control clusters. If
return_dist = TRUE, the permutation distribution
(z_perm) is also returned.
Bennett, S., Parpia, T., Hayes, R., & Cousens, S. (2002). Methods for the analysis of incidence rates in cluster randomized trials. International Journal of Epidemiology, 31(4), 839–846. https://doi.org/10.1093/ije/31.4.839
DiCiccio, C. J., & Romano, J. P. (2017). Robust permutation tests for correlation and regression coefficients. Journal of the American Statistical Association, 112(519), 1211–1220. https://doi.org/10.1080/01621459.2016.1202117
Gail, M. H., Mark, S. D., Carroll, R. J., Green, S. B., & Pee, D. (1996). On design considerations and randomization-based inference for community intervention trials. Statistics in Medicine, 15(11), 1069–1092. https://doi.org/10.1002/(SICI)1097-0258(19960615)15:11%3C1069::AID-SIM220%3E3.0.CO;2-Q
Hayes, R. J., & Moulton, L. H. (2017). Cluster randomised trials (2nd ed.). Chapman and Hall/CRC. https://doi.org/10.4324/9781315370286
Kvalem, I. L., Sundet, J. M., Rivø, K. I., Eilertsen, D. E., & Bakketeig, L. S. (1996). The effect of sex education on adolescents' use of condoms: Applying the Solomon four-group design. Health Education Quarterly, 23(1), 34–47. https://doi.org/10.1177/109019819602300103
Phipson, B., & Smyth, G. K. (2010). Permutation p-values should never be zero: Calculating exact p-values when permutations are randomly drawn. Statistical Applications in Genetics and Molecular Biology, 9(1), Article 39. https://doi.org/10.2202/1544-6115.1585
Wu, J., & Ding, P. (2021). Randomization tests for weak null hypotheses in randomized experiments. Journal of the American Statistical Association, 116(536), 1898–1913. https://doi.org/10.1080/01621459.2020.1750415
fit <- with(solomon_example, fit_solomon_glm(y_post, treat, pretested, y_pre)) # Few permutations keep the example fast; use the default for analyses. perm_solomon(fit, reps = 199, seed = 1)fit <- with(solomon_example, fit_solomon_glm(y_post, treat, pretested, y_pre)) # Few permutations keep the example fast; use the default for analyses. perm_solomon(fit, reps = 199, seed = 1)
Finds the smallest Solomon four-group design, at a fixed allocation across
the four cells, whose power for each Solomon estimand reaches a target.
power_solomon() answers the forward question, the power of a given
design; plan_solomon() answers the inverse.
plan_solomon( power = 0.8, delta, sens = 0, rho = 0.5, sigma = 1, alpha = 0.05, estimand = c("ate", "sensitization", "pretested", "unpretested"), allocation = c(1, 1, 1, 1), method = c("analytic", "simulation"), sims = 1000, seed = NULL, max_n = 10000 )plan_solomon( power = 0.8, delta, sens = 0, rho = 0.5, sigma = 1, alpha = 0.05, estimand = c("ate", "sensitization", "pretested", "unpretested"), allocation = c(1, 1, 1, 1), method = c("analytic", "simulation"), sims = 1000, seed = NULL, max_n = 10000 )
power |
Target power, between |
delta |
Treatment effect among unpretested participants, on the posttest scale. |
sens |
Sensitization: the additional treatment effect among pretested participants. Default is 0. |
rho |
Pretest-posttest correlation among pretested participants. |
sigma |
Posttest residual standard deviation in all cells. |
alpha |
Two-sided significance level. Default is 0.05. |
estimand |
Which estimands to plan for: any of |
allocation |
Relative cell sizes for |
method |
|
sims |
Monte Carlo replications per evaluation when
|
seed |
Optional integer seed for |
max_n |
Largest size considered for the smallest cell. |
The data-generating model is the one power_solomon() uses and validates:
normally distributed posttests with residual standard deviation sigma in
every cell, a pretest-posttest correlation of rho among pretested
participants, a treatment effect of delta among unpretested participants,
and delta + sens among pretested participants.
A data frame with one row per estimand: the estimand, its true
effect, the four cell sizes, the total sample size, the achieved power,
the basis ("analytic" or "simulation"), the Monte Carlo standard
error (NA for analytic rows), the target power, alpha, and a note.
Estimands whose true effect is zero, or whose target is not reached by
max_n, return NA sizes with an explanatory note. The planning values
are kept in the attribute settings, which analysis_plan_solomon()
reads.
The sensitization contrast (Pretest x Treatment) is the difference between the two simple treatment effects, and the equal-weighted average treatment effect is their average. The sensitization contrast therefore has exactly four times the sampling variance of the average treatment effect, for any pretest correlation and any allocation. Detecting sensitization as large as the average treatment effect needs about four times as many participants, and detecting sensitization half as large needs about sixteen times as many. A Solomon study powered only for the average treatment effect is usually underpowered for the question the design exists to answer.
method = "analytic" (default) uses normal-theory power: a two-sample t
test for the unpretested effect, an ANCOVA comparison whose residual
variance is reduced by the squared pretest-posttest correlation for the
pretested effect, and Welch-Satterthwaite degrees of freedom for the
contrasts that combine pretest conditions. The search is exact: at the
returned design power reaches the target, and with one fewer participant
in the smallest cell it does not.
method = "simulation" starts from the analytic design and increases it
until the rejection rate of the package's own GLM test, estimated with
power_solomon(), reaches the target. It reports the Monte Carlo standard
error of the achieved power. The validation of power_solomon() found the
default HC3 standard errors conservative with 20 or fewer participants
per cell, so for small designs the simulated answer can be larger than
the analytic one; from about 30 per cell the two agree closely.
Binary and count outcomes, clustered assignment, and longitudinal follow-ups are not supported; the calculations assume independent, normally distributed posttests and no missing data. Designs with several treatments are not supported; plan each treatment-control comparison as a four-group design.
Morris, T. P., White, I. R., & Crowther, M. J. (2019). Using simulation studies to evaluate statistical methods. Statistics in Medicine, 38(11), 2074–2102. https://doi.org/10.1002/sim.8086
Satterthwaite, F. E. (1946). An approximate distribution of estimates of variance components. Biometrics Bulletin, 2(6), 110–114. https://doi.org/10.2307/3002019
Welch, B. L. (1947). The generalization of "Student's" problem when several different population variances are involved. Biometrika, 34(1–2), 28–35. https://doi.org/10.1093/biomet/34.1-2.28
power_solomon() for the power of a given design, and
analysis_plan_solomon() for an analysis plan built on the result.
# Equal allocation, a treatment effect of 0.4 SD, and sensitization of 0.2 SD plan_solomon(power = 0.80, delta = 0.4, sens = 0.2, rho = 0.5) # Pretesting is expensive: half as many participants in the pretested cells plan_solomon(power = 0.80, delta = 0.4, sens = 0.2, rho = 0.5, estimand = "ate", allocation = c(1, 1, 2, 2))# Equal allocation, a treatment effect of 0.4 SD, and sensitization of 0.2 SD plan_solomon(power = 0.80, delta = 0.4, sens = 0.2, rho = 0.5) # Pretesting is expensive: half as many participants in the pretested cells plan_solomon(power = 0.80, delta = 0.4, sens = 0.2, rho = 0.5, estimand = "ate", allocation = c(1, 1, 2, 2))
Draws the conditional Tests A-I sequence implemented in
fit_solomon_classic() as a decision tree. Test A (the Pretest x Treatment
interaction) decides the branch. If it is significant, Tests B and C
examine the treatment effect within each pretest condition. If not, Test D
examines the treatment main effect, followed if necessary by the selected
pretested-groups test (E, F, or G), Test H, and finally Test I, the
Walton Braver and Braver (1988) Stouffer combination. In the original
1988 sequence each of these is reached only if the one before it is
nonsignificant; in the 1990 amendment (Braver & Walton Braver, 1990), all
of them are run once Test D is nonsignificant. The 1995 revision removed
Test D (Walton Braver & Braver, 1995, as cited in Sawilowsky, 1996, p. 2).
plot_classic_flow(fit = NULL, flow = c("1988", "1990", "1995"))plot_classic_flow(fit = NULL, flow = c("1988", "1990", "1995"))
fit |
Optional fit from |
flow |
Version of the sequence to draw when |
Given a fitted classic analysis, the tests it visited are highlighted with their p-values, following the fit's recorded path exactly, and the caption gives its conclusion.
The figure is a teaching and replication aid, not a recommended workflow.
Sawilowsky et al. (1994) found that the conditional sequence ending in
Test I has an experiment-wise Type I error rate well above its nominal
level; see vignette("solomon-methods").
A ggplot object.
Braver, S. L., & Walton Braver, M. C. (1990). Meta-analysis for Solomon four-group designs reconsidered: A reply to Sawilowsky and Markman. Perceptual and Motor Skills, 71(1), 321–322. https://doi.org/10.2466/pms.1990.71.1.321
Sawilowsky, S. S. (1996, June 23). Controlling experiment-wise Type I error of meta-analysis in the Solomon four-group design [Paper presentation]. First International Conference on Multiple Comparisons, Tel Aviv, Israel. https://digitalcommons.wayne.edu/coe_tbf/29/
Sawilowsky, S. S., Kelley, D. L., Blair, R. C., & Markman, B. S. (1994). Meta-analysis and the Solomon four-group design. The Journal of Experimental Education, 62(4), 361–376. https://doi.org/10.1080/00220973.1994.9944140
Walton Braver, M. C., & Braver, S. L. (1988). Statistical treatment of the Solomon four-group design: A meta-analytic approach. Psychological Bulletin, 104(1), 150–154. https://doi.org/10.1037/0033-2909.104.1.150
plot_classic_flow() classic <- with(solomon_example, fit_solomon_classic(y_post, treat, pretested, y_pre)) plot_classic_flow(classic) plot_classic_flow(flow = "1990") plot_classic_flow(flow = "1995")plot_classic_flow() classic <- with(solomon_example, fit_solomon_classic(y_post, treat, pretested, y_pre)) plot_classic_flow(classic) plot_classic_flow(flow = "1990") plot_classic_flow(flow = "1995")
Draws the permutation distribution of the test statistic with the
observed value marked. The subtitle reports the same p-value as
perm_solomon(), and says whether it came from every possible allocation
or from sampled permutations.
plot_perm(perm)plot_perm(perm)
perm |
An object returned by |
A ggplot object
fit <- with(solomon_example, fit_solomon_glm(y_post, treat, pretested, y_pre)) perm <- perm_solomon(fit, reps = 199, seed = 1, return_dist = TRUE) plot_perm(perm)fit <- with(solomon_example, fit_solomon_glm(y_post, treat, pretested, y_pre)) perm <- perm_solomon(fit, reps = 199, seed = 1, return_dist = TRUE) plot_perm(perm)
Draws power against sample size for each Solomon estimand, so the effect of
cell size, effect size, pretest-posttest correlation, and sensitization on
a planned study can be seen rather than read from a table. A horizontal
line marks the target power, and each curve is annotated with the design
plan_solomon() returns for that target.
plot_power_solomon( n = seq(10, 150, by = 10), delta = 0.3, sens = 0, rho = 0.5, sigma = 1, alpha = 0.05, estimand = c("ate", "sensitization", "pretested", "unpretested"), allocation = c(1, 1, 1, 1), target = 0.8, method = c("analytic", "simulation"), sims = 500, seed = NULL )plot_power_solomon( n = seq(10, 150, by = 10), delta = 0.3, sens = 0, rho = 0.5, sigma = 1, alpha = 0.05, estimand = c("ate", "sensitization", "pretested", "unpretested"), allocation = c(1, 1, 1, 1), target = 0.8, method = c("analytic", "simulation"), sims = 500, seed = NULL )
n |
Sizes of the smallest cell to plot. Other cells follow
|
delta, sens, rho
|
Treatment effect among unpretested participants,
sensitization, and pretest-posttest correlation, as in |
sigma |
Posttest residual standard deviation in all cells. |
alpha |
Two-sided significance level. Default is 0.05. |
estimand |
Estimands to plot: any of |
allocation |
Relative cell sizes for |
target |
Target power marked on the figure. Default is 0.80. Use
|
method |
|
sims |
Replications per point when |
seed |
Optional seed for |
Curves use the normal-theory power calculations validated for
power_solomon() by default. With method = "simulation", each point is
the rejection rate of the package's own GLM test from power_solomon(),
shown with a band of two Monte Carlo standard errors.
Power differs sharply between estimands: the sensitization contrast has four times the sampling variance of the average treatment effect, so its curve rises far more slowly. The figure is faceted by estimand to keep that difference visible.
A ggplot object.
power_solomon(), plan_solomon()
plot_power_solomon(n = seq(10, 200, by = 10), delta = 0.4, sens = 0.2) plot_power_solomon(n = seq(10, 200, by = 10), delta = 0.4, rho = c(0, 0.5, 0.8), estimand = c("ate", "pretested"))plot_power_solomon(n = seq(10, 200, by = 10), delta = 0.4, sens = 0.2) plot_power_solomon(n = seq(10, 200, by = 10), delta = 0.4, rho = c(0, 0.5, 0.8), estimand = c("ate", "pretested"))
Draws the Pretest x Treatment interaction that the Solomon design exists to
test: model-adjusted posttest means for the four groups, with confidence
intervals, joined within each pretest condition so that sensitization
appears as lines that are not parallel.
plot_sensitization(fit, bounds = NULL, alpha = 0.05, show_observed = TRUE)plot_sensitization(fit, bounds = NULL, alpha = 0.05, show_observed = TRUE)
fit |
A fit from |
bounds |
Optional equivalence bounds for the sensitization contrast,
as one positive number or |
alpha |
Significance level for the equivalence test when |
show_observed |
Logical; if |
The treatment effect among pretested participants is adjusted for the
pretest, so the sensitization contrast reported by fit_solomon_glm() or
fit_solomon_ml() is not the difference of differences among raw cell
means. The figure therefore draws model-adjusted means: pretested groups
are evaluated at the mean pretest score among pretested participants (the
usual ANCOVA adjusted mean), unpretested groups without a pretest, and any
covariates at their sample means. Because neither model has a
treatment-by-pretest-score term, the difference of differences among these
adjusted means equals the fitted Pretest x Treatment estimate exactly.
Observed cell means are shown as hollow points for comparison.
Intervals for the adjusted means use the fit's own covariance matrix and reference distribution:
for fit_solomon_glm(), t with residual degrees of freedom, Satterthwaite
t for CR2, or the normal distribution for binomial and Poisson models,
whose means are shown on the link scale;
for fit_solomon_ml(), the normal distribution under the default Wald
inference (van Engelenburg, 1999), or Welch-Satterthwaite t under
inference = "satterthwaite".
The sensitization estimate and interval in the subtitle are taken unchanged from the fit.
A ggplot object.
For a fit from fit_solomon_glm() with several treatments and a control,
the figure shows the model-adjusted mean of every condition with and
without a pretest, adjusted as above, with one line for each condition,
the control first. Pretest sensitization appears as a treatment line that
is not parallel to the control line: for each treatment, the difference of
differences between its means and the control's equals its fitted
Pretest x Treatment estimate. The subtitle reports the omnibus
Pretest x Condition test of the fit, which asks whether pretesting changes
the effect of any treatment. bounds is not available for these fits; test
equivalence one comparison at a time with equivalence_solomon().
van Engelenburg, G. (1999). Statistical analysis for the Solomon four-group design (Research Report 99-06). University of Twente. ERIC. https://eric.ed.gov/?id=ED435692
equivalence_solomon(), plot_solomon_effects()
fit <- with(solomon_example, fit_solomon_glm(y_post, treat, pretested, y_pre)) plot_sensitization(fit) plot_sensitization(fit, bounds = 5) ml <- with(solomon_example, fit_solomon_ml(y_post, treat, pretested, y_pre, inference = "satterthwaite")) plot_sensitization(ml) # A six-group design: two treatments and a control. fit6 <- fit_solomon_glm(post_behavior, condition, pretested, pre_behavior, control = "Control", data = mai2020) plot_sensitization(fit6)fit <- with(solomon_example, fit_solomon_glm(y_post, treat, pretested, y_pre)) plot_sensitization(fit) plot_sensitization(fit, bounds = 5) ml <- with(solomon_example, fit_solomon_ml(y_post, treat, pretested, y_pre, inference = "satterthwaite")) plot_sensitization(ml) # A six-group design: two treatments and a control. fit6 <- fit_solomon_glm(post_behavior, condition, pretested, pre_behavior, control = "Control", data = mai2020) plot_sensitization(fit6)
plot_solomon() is replaced by plot_solomon_means(), which draws the
same means and intervals with ggplot2, as every other plot in the package
does. plot_solomon() still works, with a deprecation warning, and still
draws in base graphics and returns the cell summaries invisibly.
plot_solomon(y, treat, pretested)plot_solomon(y, treat, pretested)
y |
Numeric vector of posttest scores. |
treat |
Treatment indicator coded 0 = control and 1 = treatment. |
pretested |
Pretest indicator coded 0 = not pretested and 1 = pretested. |
plot_solomon() draws the four-group design only. For a design with
several treatments, use plot_solomon_means() with control.
Invisibly returns a data frame containing cell summaries.
# Use plot_solomon_means() instead: plot_solomon_means(y_post, treat, pretested, data = solomon_example)# Use plot_solomon_means() instead: plot_solomon_means(y_post, treat, pretested, data = solomon_example)
Draws mean pretest and posttest scores for the two pretested groups,
joined to show change, alongside posttest means for the two unpretested
groups. The unpretested groups appear at posttest only: their missing
pretest is the experimental manipulation (Solomon, 1949), not missing data,
and the figure labels it that way.
plot_solomon_change( y_post, treat, pretested, y_pre, show_individuals = FALSE, conf_level = 0.95, control = NULL, data = NULL )plot_solomon_change( y_post, treat, pretested, y_pre, show_individuals = FALSE, conf_level = 0.95, control = NULL, data = NULL )
y_post |
Numeric posttest scores. |
treat |
Treatment indicator coded 0 = control and 1 = treatment; or,
for a design with several treatments, a factor or character vector of
conditions, with the control named by |
pretested |
Pretest indicator coded 0 = unpretested and 1 = pretested. |
y_pre |
Numeric pretest scores, missing by design for unpretested participants. |
show_individuals |
Logical; if |
conf_level |
Confidence level for the intervals, which use the t distribution with n - 1 degrees of freedom. Default is 0.95. |
control |
The control condition, when |
data |
Optional data frame. When supplied, the other data arguments
are looked up in it first, as bare column names ( |
Trajectories use pretested participants with both scores observed.
Pretested participants whose pretest is incidentally missing are left out
of the trajectories and counted in the caption, and are never imputed; see
check_solomon_missing().
A change reading of this figure applies only to the pretested groups. The
Solomon contrasts the package reports compare posttests, adjusting for the
pretest where one exists; see compare_solomon_methods() for the estimand
behind each analysis.
A ggplot object.
For a Solomon N-group design, with k treatments and a control each with
and without a pretest (Steyn, 2009), give treat as a factor or character
vector of conditions and name the control with control. The figure then
shows all 2(k + 1) groups: color marks the condition, the control first as
in plot_sensitization(), and the point shape marks whether the group was
pretested.
Solomon, R. L. (1949). An extension of control group design. Psychological Bulletin, 46(2), 137–150. https://doi.org/10.1037/h0062958
Steyn, R. (2009). Re-designing the Solomon four-group: Can we improve on this exemplary model? Design Principles and Practices: An International Journal—Annual Review, 3(1), 383–394. https://doi.org/10.18848/1833-1874/CGP/v03i01/37588
with(solomon_example, plot_solomon_change(y_post, treat, pretested, y_pre)) # A six-group design: two treatments and a control. plot_solomon_change(post_behavior, condition, pretested, pre_behavior, control = "Control", data = mai2020)with(solomon_example, plot_solomon_change(y_post, treat, pretested, y_pre)) # A six-group design: two treatments and a control. plot_solomon_change(post_behavior, condition, pretested, pre_behavior, control = "Control", data = mai2020)
Draws the Solomon (1949) four-group design in the notation of Campbell and
Stanley (1963/1966, p. 6): each row is a randomized group (R), O marks an observation
(pretest or posttest), and X marks the treatment. Groups 1 and 2 are
pretested; Groups 3 and 4 are not, by design, so their missing pretest is
part of the experiment rather than missing data.
plot_solomon_design( y_post = NULL, treat = NULL, pretested = NULL, fit = NULL, control = NULL, treatments = NULL, data = NULL, x = deprecated() )plot_solomon_design( y_post = NULL, treat = NULL, pretested = NULL, fit = NULL, control = NULL, treatments = NULL, data = NULL, x = deprecated() )
y_post |
Optional numeric posttest scores, with |
treat |
Treatment indicator coded 0 = control and 1 = treatment, when
|
pretested |
Pretest indicator coded 0 = unpretested and 1 = pretested,
when |
fit |
Optional fit from |
control |
The control condition, when |
treatments |
For the teaching schematic without data: the number of
treatments, or a character vector of treatment labels. |
data |
Optional data frame. When supplied, the other data arguments
are looked up in it first, as bare column names ( |
x |
Called with no data, the function draws the generic schematic used for
teaching. Given data or a fitted model, it labels each group with its size
and posttest mean. Groups with no participants, or with fewer than two
observed posttest scores, are flagged, using the same rule as
validate_solomon().
A ggplot object.
A Solomon N-group design crosses k treatments and a control with pretesting, giving 2(k + 1) groups: six for two treatments and eight for three (Steyn, 2009). The rows run in the order solomonR uses for these designs: the pretested treatment groups, the pretested control group, then the unpretested groups in the same order. With two or more treatments, X1, X2, and so on mark the treatments, and the subtitle gives the key.
To draw such a design, give a fit from fit_solomon_glm() with several
treatments, or data with treat as a factor or character vector of
conditions and the control named by control. For the teaching schematic
without data, give treatments: the number of treatments
(treatments = 2) or their labels (treatments = c("RP", "GS")).
Campbell, D. T., & Stanley, J. C. (1966). Experimental and quasi-experimental designs for research. Rand McNally. (Original work published 1963)
Solomon, R. L. (1949). An extension of control group design. Psychological Bulletin, 46(2), 137–150. https://doi.org/10.1037/h0062958
Steyn, R. (2009). Re-designing the Solomon four-group: Can we improve on this exemplary model? Design Principles and Practices: An International Journal—Annual Review, 3(1), 383–394. https://doi.org/10.18848/1833-1874/CGP/v03i01/37588
plot_solomon_design() plot_solomon_design(y_post, treat, pretested, data = solomon_example) # A six-group design: two treatments and a control. plot_solomon_design(treatments = 2) plot_solomon_design(post_behavior, condition, pretested, control = "Control", data = mai2020)plot_solomon_design() plot_solomon_design(y_post, treat, pretested, data = solomon_example) # A six-group design: two treatments and a control. plot_solomon_design(treatments = 2) plot_solomon_design(post_behavior, condition, pretested, control = "Control", data = mai2020)
Plots the four Solomon contrasts from a fitted model: the average
treatment effect across pretest conditions, the Pretest x Treatment
sensitization contrast, and the treatment effects among pretested and
unpretested participants, each with its confidence interval and a
reference line at zero.
plot_solomon_effects(fit, bounds = NULL)plot_solomon_effects(fit, bounds = NULL)
fit |
A fit from |
bounds |
Optional equivalence bounds for the sensitization contrast,
as one positive number or |
Estimates and intervals are taken unchanged from the fitted object, so the figure agrees with its printed output, and the caption states the confidence level and the reference distribution the model used. Contrasts a model does not estimate are omitted and named in the caption rather than drawn as zero.
A ggplot object.
For a fit from fit_solomon_glm() with several treatments and a control,
the figure has one panel for each of the four contrasts and one row in
each panel for each comparison, such as "RP vs Control", in the order of
the fit. The intervals are the unadjusted ones the fit reports. The
caption names the adjustment the fit applied to its p-values, by default
Holm's (1979) procedure, and says that the intervals are not adjusted.
With bounds, the band is drawn on every Pretest x Treatment row.
Holm, S. (1979). A simple sequentially rejective multiple test procedure. Scandinavian Journal of Statistics, 6(2), 65–70. https://www.jstor.org/stable/4615733
fit <- with(solomon_example, fit_solomon_glm(y_post, treat, pretested, y_pre)) plot_solomon_effects(fit) plot_solomon_effects(fit, bounds = 5) # A six-group design: two treatments and a control. fit6 <- fit_solomon_glm(post_behavior, condition, pretested, pre_behavior, control = "Control", data = mai2020) plot_solomon_effects(fit6)fit <- with(solomon_example, fit_solomon_glm(y_post, treat, pretested, y_pre)) plot_solomon_effects(fit) plot_solomon_effects(fit, bounds = 5) # A six-group design: two treatments and a control. fit6 <- fit_solomon_glm(post_behavior, condition, pretested, pre_behavior, control = "Control", data = mai2020) plot_solomon_effects(fit6)
plot_solomon_gg() was renamed plot_solomon_means() in solomonR 0.8.0,
so that each plot in the package is named for what it shows. It still
works, with a deprecation warning, and returns the plot that
plot_solomon_means() draws.
plot_solomon_gg(y, treat, pretested)plot_solomon_gg(y, treat, pretested)
y |
Numeric vector of posttest scores. |
treat |
Treatment indicator coded 0 = control and 1 = treatment. |
pretested |
Pretest indicator coded 0 = not pretested and 1 = pretested. |
A ggplot object.
# Use plot_solomon_means() instead: plot_solomon_means(y_post, treat, pretested, data = solomon_example)# Use plot_solomon_means() instead: plot_solomon_means(y_post, treat, pretested, data = solomon_example)
Displays the posttest mean of each of the four Solomon groups with its
confidence interval, with the pretested and unpretested groups side by
side. Intervals use the t distribution with n - 1 degrees of freedom
within each group. For the model-adjusted means behind the sensitization
contrast, see
plot_sensitization(); for pretest-to-posttest change, see
plot_solomon_change().
plot_solomon_means( y_post, treat, pretested, conf_level = 0.95, control = NULL, data = NULL )plot_solomon_means( y_post, treat, pretested, conf_level = 0.95, control = NULL, data = NULL )
y_post |
Numeric posttest scores. |
treat |
Treatment indicator coded 0 = control and 1 = treatment; or,
for a design with several treatments, a factor or character vector of
conditions, with the control named by |
pretested |
Pretest indicator coded 0 = not pretested and 1 = pretested. |
conf_level |
Confidence level for the intervals. Default is 0.95. |
control |
The control condition, when |
data |
Optional data frame. When supplied, the other data arguments
are looked up in it first, as bare column names ( |
A ggplot object. Its data element holds the group summaries:
n, mean, sd, se, and the interval limits lo and hi. Its
treat column is 0/1 for a four-group design and holds the condition
for a design with several treatments.
For a Solomon N-group design, with k treatments and a control each with
and without a pretest (Steyn, 2009), give treat as a factor or character
vector of conditions and name the control with control. Each panel then
shows the k + 1 conditions, the control first, as with the four-group
design.
Steyn, R. (2009). Re-designing the Solomon four-group: Can we improve on this exemplary model? Design Principles and Practices: An International Journal—Annual Review, 3(1), 383–394. https://doi.org/10.18848/1833-1874/CGP/v03i01/37588
plot_solomon_change(), plot_sensitization()
plot_solomon_means(y_post, treat, pretested, data = solomon_example) # A six-group design: two treatments and a control. plot_solomon_means(post_behavior, condition, pretested, control = "Control", data = mai2020)plot_solomon_means(y_post, treat, pretested, data = solomon_example) # A six-group design: two treatments and a control. plot_solomon_means(post_behavior, condition, pretested, control = "Control", data = mai2020)
Plots the pooled estimate of a Solomon contrast, with its confidence
interval, against the offset added to the imputed posttests, from
tipping_point_solomon(). Dashed lines mark the offsets at which the
conclusion changes.
plot_tipping_point(tipping)plot_tipping_point(tipping)
tipping |
A result from |
A ggplot object.
d <- solomon_example set.seed(82) d$y_post[sample(nrow(d), 20)] <- NA tp <- tipping_point_solomon(y_post, treat, pretested, y_pre, groups = "treatment", deltas = seq(-10, 10, by = 2.5), m = 10, seed = 1, data = d) plot_tipping_point(tp)d <- solomon_example set.seed(82) d$y_post[sample(nrow(d), 20)] <- NA tp <- tipping_point_solomon(y_post, treat, pretested, y_pre, groups = "treatment", deltas = seq(-10, 10, by = 2.5), m = 10, seed = 1, data = d) plot_tipping_point(tp)
Simulates normally distributed Solomon four-group data and reports the
rejection rate of each Solomon test at the chosen
alpha, with its Monte
Carlo standard error.
power_solomon( n = 50, delta = 0.3, sens = 0, rho = 0.5, sigma = 1, alpha = 0.05, sims = 2000, stouffer = TRUE, seed = NULL )power_solomon( n = 50, delta = 0.3, sens = 0, rho = 0.5, sigma = 1, alpha = 0.05, sims = 2000, stouffer = TRUE, seed = NULL )
n |
Cell sizes: a single number used for all four cells, or four
sizes given as a list or vector with elements |
delta |
Treatment effect among unpretested participants, on the posttest scale. |
sens |
Sensitization: the additional treatment effect among pretested participants (0 = none). |
rho |
Pretest-posttest correlation among pretested participants. |
sigma |
Posttest residual standard deviation in all cells. |
alpha |
Significance level. Default is 0.05. |
sims |
Number of Monte Carlo replications. |
stouffer |
Logical; if |
seed |
Optional integer seed. The global random number state is restored afterwards. |
Every participant has a latent baseline drawn from a standard normal
distribution, which only pretested participants observe, so structural
pretest absence is part of the design rather than missing data. The
posttest residual standard deviation is sigma in every cell, and the
pretest-posttest correlation among pretested participants is rho. The
treatment effect is delta among unpretested participants and
delta + sens among pretested participants, so the equal-weighted average
treatment effect is delta + sens / 2.
The reported power is a rejection rate: when true_effect is zero it
estimates the Type I error rather than power.
Tests are computed from the same functions users would call, so reported
power reflects the package's default inference: fit_solomon_glm() with
HC3 standard errors and t reference distributions, the 2x2 ANOVA
interaction, and the historical Test I (Walton Braver & Braver, 1988).
A data frame with one row per test, giving the estimand, the test
used, the true effect, the rejection rate and its Monte Carlo standard
error, the replications that produced a usable fit, the number of
failures, and alpha. Test I rows report NA for true_effect, because
the combination targets a directional hypothesis rather than a single
contrast, and all Test I values are NA when stouffer = FALSE.
A pre-specified simulation study of 126 scenarios and 315,000 replications checked this function against normal-theory benchmarks. The protocol and its amendment were posted to issue #18 before any results were examined, and the article "Validating power_solomon()" on the package website reports the study in full.
The 2x2 ANOVA interaction agreed with its analytic benchmark in every scenario, with mean differences of 0.002 or less.
Test I held its nominal size under the complete null, rejecting between 4.4% and 5.6% of the time at alpha = .05.
Rejection rates were invariant to the residual scale, and no fit failed.
Rejection rates from the unified GLM are conservative in small samples, because the HC3 standard errors the package uses by default are conservative there. Type I error averaged 0.041 with 10 participants per cell and 0.049 with 100, and simulated power fell below the normal-theory benchmark by 0.030 on average with 10 per cell (up to 0.083 in one scenario), 0.017 with 20, and 0.003 with 100.
With 20 or fewer participants per cell, treat GLM-based power as a conservative figure rather than an exact one.
Only continuous outcomes are simulated. Binary and count outcomes are not
supported; for binary outcomes see marginal_solomon() and its simulation
validation on issue #43. Designs with several treatments are not
supported; compute power for each treatment-control comparison as a
four-group design.
The arguments follow the order of plan_solomon() and
plot_power_solomon(): n, delta, sens, rho, sigma, alpha.
Before solomonR 0.8.0, rho came before sens and alpha came last, so
a call that passes these by position gets a warning that it was read in
the new order. Naming the arguments avoids the ambiguity.
Morris, T. P., White, I. R., & Crowther, M. J. (2019). Using simulation studies to evaluate statistical methods. Statistics in Medicine, 38(11), 2074–2102. https://doi.org/10.1002/sim.8086
Walton Braver, M. C., & Braver, S. L. (1988). Statistical treatment of the Solomon four-group design: A meta-analytic approach. Psychological Bulletin, 104(1), 150–154. https://doi.org/10.1037/0033-2909.104.1.150
power_solomon(n = 30, delta = 0.5, sens = 0.2, sims = 50, seed = 1)power_solomon(n = 30, delta = 0.5, sens = 0.2, sims = 50, seed = 1)
Turns a fitted Solomon analysis into APA 7 results sentences, a short
design statement, and the references for exactly the methods that analysis
used.
report_solomon(fit, design = NULL, digits = 2, format = c("text", "markdown"))report_solomon(fit, design = NULL, digits = 2, format = c("text", "markdown"))
fit |
A fitted Solomon analysis (see Details). |
design |
Optional list describing the design: |
digits |
Decimal places for estimates and statistics. Default 2. |
format |
|
Supported objects come from fit_solomon_glm(), fit_solomon_ml(),
fit_solomon_classic(), perm_solomon(), marginal_solomon(),
equivalence_solomon(), fisher_solomon(), solomon_from_summary(),
fit_solomon_sem(), fit_solomon_sem_latent(), baseline_solomon(),
fit_solomon_mi(), tipping_point_solomon(), fit_solomon_mmrm(), and
fit_solomon_steyn().
The references depend
on the options the fit used: for example, a CR2 fit cites Bell and
McCaffrey (2002) and Pustejovsky and Tipton (2018), and the 1990 flow of
the classic analysis adds Braver and Walton Braver (1990). Every reference
matches the package's canonical APA 7 bibliography.
The design statement follows the MERIT recommendations on reporting
measurement in trials (French et al., 2021b): the numbers analyzed in each
group, attrition by group when design$randomized is given, whether the
sensitization analysis was pre-specified, and the measurement procedure
in each group (Recommendation 11 is to use identical measurement protocols
in all arms, p. 34).
Designs with several treatments. For a fit_solomon_glm() fit with
control and three or more conditions (class solomon_ngroup), the
design statement names the treatments, the control, and the 2(k + 1)
groups of the design (Steyn, 2009), with the numbers analyzed in each.
The results give the omnibus tests of the Pretest x Condition interaction
and of the conditions averaged over pretest conditions, then the Solomon
contrasts of each comparison. Their p-values are adjusted within each
contrast across the comparisons, by Holm's (1979) procedure unless the
fit chose another adjustment; the confidence intervals are not adjusted.
Comparisons defined by weights are reported with their weights. An
equivalence_solomon() test of one comparison and the
baseline_solomon() comparisons of such a design are reported with the
same design statement. solomonR follows a pre-publication draft of Steyn
(2009), which the author provided; see fit_solomon_steyn().
Nonrandomized designs. With design$assignment = "nonrandom", the
results describe differences between groups rather than treatment
effects, and the design statement names the threats that random
assignment would otherwise control: selection bias, the largest threat to
internal validity in quasi-experimental research (Edmonds & Kennedy, 2017,
p. 7), and instrumentation, which with selection bias Edmonds and Kennedy
name as the threats most common in quasi-experimental Solomon designs
(p. 94). It adds that baseline differences can be examined only in the
pretested arms (baseline_solomon()): without random assignment the
unpretested arms form a static-group comparison, whose groups cannot be
shown to have been equivalent (Campbell & Stanley, 1963/1966, pp. 12,
25).
What the report does not decide. It states results; it does not interpret them. Whether the analysis was pre-specified must be supplied, never inferred, and the choice of analysis, the reading of the results, and the conclusions remain the researcher's responsibility.
An object of class solomon_report with method, results, and
design (character vectors of sentences), table (the estimates), and
references (APA 7 reference entries, in APA order).
Campbell, D. T., & Stanley, J. C. (1966). Experimental and quasi-experimental designs for research. Rand McNally. (Original work published 1963)
Edmonds, W. A., & Kennedy, T. D. (2017). An applied guide to research designs: Quantitative, qualitative, and mixed methods (2nd ed.). SAGE Publications. https://doi.org/10.4135/9781071802779
French, D. P., Miles, L. M., Elbourne, D., Farmer, A., Gulliford, M., Locock, L., Sutton, S., McCambridge, J., & MERIT Collaborative Group. (2021b). Reducing bias in trials from reactions to measurement: The MERIT study including developmental work and expert workshop. Health Technology Assessment, 25(55), 1–72. https://doi.org/10.3310/hta25550
Holm, S. (1979). A simple sequentially rejective multiple test procedure. Scandinavian Journal of Statistics, 6(2), 65–70. https://www.jstor.org/stable/4615733
Steyn, R. (2009). Re-designing the Solomon four-group: Can we improve on this exemplary model? Design Principles and Practices: An International Journal—Annual Review, 3(1), 383–394. https://doi.org/10.18848/1833-1874/CGP/v03i01/37588
fit <- with(solomon_example, fit_solomon_glm(y_post, treat, pretested, y_pre)) report_solomon(fit, design = list(prespecified = TRUE)) # A six-group design: two treatments and a control (Mai et al., 2020). fit6 <- fit_solomon_glm(post_behavior, condition, pretested, pre_behavior, control = "Control", data = mai2020) report_solomon(fit6)fit <- with(solomon_example, fit_solomon_glm(y_post, treat, pretested, y_pre)) report_solomon(fit, design = list(prespecified = TRUE)) # A six-group design: two treatments and a control (Mai et al., 2020). fit6 <- fit_solomon_glm(post_behavior, condition, pretested, pre_behavior, control = "Control", data = mai2020) report_solomon(fit6)
Generates individual data for a randomized Solomon four-group study with
chosen treatment, pretest, and sensitization effects, and attaches the
true value of every Solomon estimand. It is a solomonR teaching tool:
instructors can show that each analysis recovers the effects that were
built in, and researchers can check an analysis plan on data whose answer
is known. With several treatment effects it simulates a Solomon N-group
design (see "Designs with several treatments").
simulate_solomon( n = 30, delta = 0, sens = 0, pretest_effect = 0, rho = 0.5, sigma = 1, mean = 0, digits = NULL, limits = NULL, seed = NULL )simulate_solomon( n = 30, delta = 0, sens = 0, pretest_effect = 0, rho = 0.5, sigma = 1, mean = 0, digits = NULL, limits = NULL, seed = NULL )
n |
Participants per group: one number for all groups, or one number per group. For the four-group design, four numbers in the order pretested treatment, pretested control, unpretested treatment, unpretested control. For k treatments, 2(k + 1) numbers in the order given in "Designs with several treatments". Default 30 per group. |
delta |
Treatment effect among unpretested participants. For a design with several treatments, one effect per treatment, named by treatment. Default 0. |
sens |
Pretest x Treatment interaction (sensitization): the extra treatment effect among pretested participants. For a design with several treatments, one number for every treatment or one per treatment. Default 0. |
pretest_effect |
Effect of taking the pretest on the posttest, among controls. Default 0. |
rho |
Pretest-posttest correlation within the pretested groups. Default 0.5. |
sigma |
Standard deviation of the scores within each group. Default 1. |
mean |
Mean pretest and control-group posttest score. Default 0. |
digits |
Optional number of decimal places to round scores to. |
limits |
Optional lower and upper limits for scores, applied after rounding. |
seed |
Optional integer seed. The global random number state is left unchanged. |
Data-generating model. It is the model of power_solomon(), whose
rebuild was validated under a protocol posted on issue #18, with a
pretesting main effect and a location added. Every participant has a
latent baseline A from a standard normal distribution. Participants in the
pretested groups have a pretest score of mean + sigma * A. Every
participant's posttest score is
mean + delta * treat + pretest_effect * pretested + sens * treat * pretested + sigma * (rho * A + sqrt(1 - rho^2) * e),
where e is independent standard normal error. So rho is the
pretest-posttest correlation within each pretested group, and sigma is
the standard deviation of both scores within each group. The four groups
are generated in the package's order (pretested treatment, pretested
control, unpretested treatment, unpretested control), and the baselines
are drawn before the errors.
Relation to the package's other simulations. With mean = 0,
sigma = 1, and pretest_effect = 0, the data are the first data set
that power_solomon() simulates with the same seed. With n = 30, delta = 5,
pretest_effect = 2, rho = 0.6, sigma = 10, mean = 50,
seed = 20260915, digits = 0, and limits = c(0, 100), they are the
bundled solomon_example data.
True values. The "truth" attribute gives each estimand:
the treatment effect among unpretested participants, delta;
among pretested participants, delta + sens;
the Pretest x Treatment interaction, sens;
the equal-weighted average treatment effect, delta + sens / 2;
the pretest effect among controls, pretest_effect.
Rounding and limits (digits, limits) make the scores look like test
scores, but they shift the true values slightly, and more so when many
scores reach a limit.
Choosing values. Willson and Putnam (1982) found an average pretest effect of about a fifth of a standard deviation in randomized studies; the article "Planning a Solomon Study" discusses planning values.
A data frame with y_post, treat, pretested, and y_pre
(missing by design in the unpretested groups), in the form the analysis
functions take. treat is 0/1 for the four-group design and a factor of
conditions for a design with several treatments. Its "truth" attribute
is a data frame of the true estimands, and its "settings" attribute
holds the arguments, with the group sizes named by group.
A Solomon N-group design crosses k treatments and a control with
pretesting, giving 2(k + 1) groups: six for two treatments and eight for
three (Edmonds & Kennedy, 2017; Steyn, 2009). Give delta one effect per
treatment, named by treatment, for example delta = c(A = 0.5, B = 0.2).
Without names the treatments are called "T1", "T2", and so on; the
control is "Control". sens is one number for every treatment or one
per treatment, in the order of delta; a named sens is matched to the
treatments by name.
The model is the one above, with the effects delta[j] and sens[j] of
treatment j: each treatment differs from the control only by its own
effects. n is one size for every group, or 2(k + 1) sizes in this order:
the pretested treatments (in the order of delta), the pretested control,
the unpretested treatments, and the unpretested control. Sizes named by
group, as in the "settings" attribute (such as "Pretested, A"), or
named n1, n2, and so on for the groups in that order, may be given in
any order. Other names are refused. The groups are generated in the order
above, and the baselines are drawn before the errors.
The treat column is then a factor whose levels are the treatments and
"Control", so the data go directly to
fit_solomon_glm(y_post, treat, pretested, y_pre, control = "Control").
The "truth" attribute has one row for each treatment-control comparison
and contrast, with the columns comparison (such as "A vs Control"),
contrast, and true_value, in the order of the effects table of that
fit; a last row gives the pretest effect among controls. With one
treatment effect the data and the "truth" attribute are those described
above.
Edmonds, W. A., & Kennedy, T. D. (2017). An applied guide to research designs: Quantitative, qualitative, and mixed methods (2nd ed.). SAGE Publications. https://doi.org/10.4135/9781071802779
Steyn, R. (2009). Re-designing the Solomon four-group: Can we improve on this exemplary model? Design Principles and Practices: An International Journal—Annual Review, 3(1), 383–394. https://doi.org/10.18848/1833-1874/CGP/v03i01/37588
Willson, V. L., & Putnam, R. R. (1982). A meta-analysis of pretest sensitization effects in experimental design. American Educational Research Journal, 19(2), 249–258. https://doi.org/10.3102/00028312019002249
power_solomon() and plan_solomon() for planning,
fit_solomon_glm() for the recommended analysis, and the article
"Teaching with solomonR".
d <- simulate_solomon(n = 40, delta = 0.5, sens = 0.4, rho = 0.6, seed = 1) attr(d, "truth") with(d, fit_solomon_glm(y_post, treat, pretested, y_pre)) # The bundled teaching data. ex <- simulate_solomon(n = 30, delta = 5, pretest_effect = 2, rho = 0.6, sigma = 10, mean = 50, digits = 0, limits = c(0, 100), seed = 20260915) attr(ex, "truth") <- attr(ex, "settings") <- NULL identical(ex, solomon_example) # A six-group design: two treatments and a control. d6 <- simulate_solomon(n = 50, delta = c(A = 0.5, B = 0.2), sens = c(0.3, 0), rho = 0.6, seed = 1) attr(d6, "truth") fit_solomon_glm(y_post, treat, pretested, y_pre, control = "Control", data = d6)d <- simulate_solomon(n = 40, delta = 0.5, sens = 0.4, rho = 0.6, seed = 1) attr(d, "truth") with(d, fit_solomon_glm(y_post, treat, pretested, y_pre)) # The bundled teaching data. ex <- simulate_solomon(n = 30, delta = 5, pretest_effect = 2, rho = 0.6, sigma = 10, mean = 50, digits = 0, limits = c(0, 100), seed = 20260915) attr(ex, "truth") <- attr(ex, "settings") <- NULL identical(ex, solomon_example) # A six-group design: two treatments and a control. d6 <- simulate_solomon(n = 50, delta = c(A = 0.5, B = 0.2), sens = c(0.3, 0), rho = 0.6, seed = 1) attr(d6, "truth") fit_solomon_glm(y_post, treat, pretested, y_pre, control = "Control", data = d6)
A synthetic data set with 25 observations in each of the four combinations of treatment and pretest assignment. It is kept as a second example because two of its features make different analyses of the same effect disagree:
A data frame with 100 rows and 4 variables:
Numeric posttest score.
Treatment indicator: 0 = control, 1 = treatment.
Pretest indicator: 0 = not pretested, 1 = pretested.
Numeric pretest score. Structurally missing for participants assigned to the unpretested groups.
among pretested participants, the pretest and posttest are negatively correlated (r = -0.14); and
the pretested treatment group's mean pretest score is about 4.5 points higher than the pretested control group's.
As a result, unadjusted, ANCOVA, and gain-score estimates of the treatment
effect among pretested participants differ markedly (see
compare_solomon_methods() and vignette("getting-started")). The
parameters used to generate these data were not recorded, so their true
effects are unknown. For the primary example with documented true values,
see solomon_example.
Synthetic data generated for examples and package documentation.
Computes standardized treatment effects for the pretested and unpretested
pairs of a Solomon four-group study, with sampling variances in the
yi/vi form that meta-analysis software reads.
solomon_effect_sizes( n, mean_post, sd_post, mean_pre = NULL, sd_pre = NULL, r = NULL )solomon_effect_sizes( n, mean_post, sd_post, mean_pre = NULL, sd_pre = NULL, r = NULL )
n |
Sample sizes of the four groups, in the order pretested treated, pretested control, unpretested treated, unpretested control. |
mean_post, sd_post
|
Posttest means and standard deviations of the four groups. |
mean_pre, sd_pre
|
Pretest means and standard deviations of the two pretested groups (treated, control). Optional; without them only the unpretested pair is returned. |
r |
Pre-post correlation in the pretested groups, needed with
|
Pretested pair. The effect size is Morris's (2008) : the
difference between the treated and control groups' mean pre-post change,
divided by the pooled pretest standard deviation and multiplied by a
small-sample bias correction (Eqs. 8-10). The correction here is the exact
form (Eq. 22). Its sampling variance is Eq. 25, which needs the pre-post
correlation r, assumed equal in the two groups. Morris (2008, p. 374)
found that Eq. 25 was within 3% of the simulated variance in most
conditions. When the treatment inflates posttest variance, however, it
underestimated the true variance by 21% to 48% (p. 380), and a correlation
that differs between the groups can make it less accurate still.
Unpretested pair. The effect size is Hedges's g for the two posttest groups, with the pooled posttest standard deviation. Its variance comes from the same noncentral t argument that Morris (2008, pp. 371-373) uses for Eq. 25, following Hedges (1981), without the pretest adjustment.
Variances are evaluated at the estimated effect size. The two rows use different standardizers (the pretest SD and the posttest SD), so their difference is not a clean measure of pretest sensitization.
A data frame with one row per pair: the estimator, yi (effect
size), vi (sampling variance), sei (standard error), and the group
sizes.
Hedges, L. V. (1981). Distribution theory for Glass's estimator of effect size and related estimators. Journal of Educational Statistics, 6(2), 107–128. https://doi.org/10.3102/10769986006002107
Morris, S. B. (2008). Estimating effect sizes from pretest-posttest-control group designs. Organizational Research Methods, 11(2), 364–386. https://doi.org/10.1177/1094428106291059
# Pretested pair: the first study in Morris (2008, Table 1); # unpretested pair: hypothetical. solomon_effect_sizes( n = c(20, 20, 20, 20), mean_post = c(38.5, 19.7, 36.0, 25.0), sd_post = c(11.6, 14.8, 13.0, 14.0), mean_pre = c(30.6, 23.1), sd_pre = c(15.0, 13.8), r = 0.47 )# Pretested pair: the first study in Morris (2008, Table 1); # unpretested pair: hypothetical. solomon_effect_sizes( n = c(20, 20, 20, 20), mean_post = c(38.5, 19.7, 36.0, 25.0), sd_post = c(11.6, 14.8, 13.0, 14.0), mean_pre = c(30.6, 23.1), sd_pre = c(15.0, 13.8), r = 0.47 )
A simulated randomized Solomon four-group study with 30 participants per group and scores on a 0-100 scale. Because the data were simulated, the true effects are known, so estimates can be compared with the truth. This is the main example in the package documentation; solomon_demo is a second example in which different analyses of the same effect disagree.
A data frame with 120 rows and 4 variables:
Posttest score (0-100).
Treatment indicator: 0 = control, 1 = treatment.
Pretest indicator: 0 = not pretested, 1 = pretested.
Pretest score (0-100). Structurally missing for participants assigned to the unpretested groups.
Every participant has a latent baseline ability A drawn from a standard normal distribution. Participants in the pretested groups have a pretest score of 50 + 10A. Every participant's posttest score is 50 + 5 x treat + 2 x pretested + 10(0.6A + 0.8e), where e is independent standard normal error. Scores are rounded to whole points and kept within 0-100.
The seed (20260915) and all parameters were fixed and posted in issue #21
before the data were generated, and the data were not regenerated to obtain
particular results. The script is data-raw/solomon_example.R in the package
repository.
The treatment effect is 5 points among both pretested and unpretested participants, so there is no sensitization. The pretest effect is 2 points, the equal-weighted average treatment effect (ATE) is 5 points, and the pretest-posttest correlation is 0.6.
A single study can miss a real effect. With 30 participants per group, this
design has approximately 85% power at alpha = .05 for the ATE, 67% for the
treatment effect among pretested participants, and 48% among unpretested
participants. In this sample, fit_solomon_glm() estimates the ATE at about
2.7 points, with a 95% confidence interval that includes both 0 and the true
value of 5. The sample pretest-posttest correlation is 0.61, and the two
pretested groups have nearly identical mean pretest scores.
Simulated for solomonR; see data-raw/solomon_example.R in the
package repository.
data(solomon_example) with(solomon_example, validate_solomon(y_post, treat, pretested, y_pre)) with(solomon_example, fit_solomon_glm(y_post, treat, pretested, y_pre))data(solomon_example) with(solomon_example, validate_solomon(y_post, treat, pretested, y_pre)) with(solomon_example, fit_solomon_glm(y_post, treat, pretested, y_pre))
Reanalyzes a published Solomon four-group study from the sample size,
mean, and standard deviation of the posttest in each of the four groups.
With
treat and pretested it also reanalyzes designs with several
treatments (see "Designs with several treatments").
solomon_from_summary( n, mean, sd, conf_level = 0.95, treat = NULL, pretested = NULL, control = NULL )solomon_from_summary( n, mean, sd, conf_level = 0.95, treat = NULL, pretested = NULL, control = NULL )
n, mean, sd
|
Posttest sample size, mean, and standard deviation of the
four groups, in the order above. With |
conf_level |
Confidence level for intervals. Default 0.95. |
treat |
Optional condition of each group, in the order of |
pretested |
1 (or |
control |
The control condition, when |
The four groups are given in the order used throughout the package:
pretested treated (O2), pretested control (O4), unpretested treated (O5),
and unpretested control (O6). The analysis is the 2 x 2 between-groups
model on the posttest with a pooled error variance, so it reproduces the
historical Tests A-D and the simple treatment effects (Tests B and C) of
fit_solomon_classic(). Main effects are contrasts of unweighted cell
means, which match the Type III sums of squares that statistical packages
report for unbalanced cells.
Summary statistics limit the analysis. The pooled error variance assumes equal variances in the four groups; heteroskedasticity-consistent standard errors, covariate adjustment, and the analyses of the pretested groups (Tests E-G) need the individual data. Rounded published statistics reproduce published tests only to within rounding: for El Karkri et al. (2025a), the interaction F is 11.46 against the published 11.48.
An object of class solomon_summary_fit with contrasts (Tests
A-D, the pretest main effect, and the simple effects: estimate, standard
error, t, degrees of freedom, p-value, confidence interval, F, and Type
III sum of squares), an anova table, the cells, the error mean
square and degrees of freedom, and the settings.
For a design with several treatments, an object of class
solomon_summary_ngroup with contrasts (for each comparison of a
treatment with the control and each of the four contrasts: estimate,
standard error, t, p-value, Holm-adjusted p-value p.adjusted, degrees
of freedom, and confidence interval), the omnibus tests in anova
(Type III sum of squares, df, mean square, F, p-value), the cells in
the package's group order, the conditions (control first), adjust
("holm"), the error mean square and degrees of freedom, and the
settings.
A Solomon N-group design has k treatments and a control, each with and
without a pretest: 2(k + 1) groups (Edmonds & Kennedy, 2017; Steyn, 2009).
Give n, mean, and sd for every group, in any order, and say which
group each value belongs to with treat (its condition) and pretested
(1 for a pretested group), naming the control with control.
The analysis is the cell-means model of the posttest with a pooled error
variance on N - 2(k + 1) degrees of freedom. For each treatment against
the control it gives the four Solomon contrasts with t tests and
confidence intervals. They equal those of
fit_solomon_glm(y_post, treat, pretested, control = , robust = "none")
on the individual data, without the pretest as a covariate. The p-values
of each contrast are adjusted across the k comparisons by Holm's (1979)
procedure. The confidence intervals are not adjusted.
The omnibus F tests are those of the two-way ANOVA with Type III sums of
squares: Condition (k df), Pretest (1 df), and Pretest x Condition (k
df). Each is a Wald test of contrasts of the unweighted cell means, as in
the four-group analysis. The result has class solomon_summary_ngroup.
With two conditions, the result is the four-group analysis above.
Edmonds, W. A., & Kennedy, T. D. (2017). An applied guide to research designs: Quantitative, qualitative, and mixed methods (2nd ed.). SAGE Publications. https://doi.org/10.4135/9781071802779
El Karkri, M., Quesada, A., & Romero-Ariza, M. (2025a). The dual impact of pretest sensitisation and the cognitive acceleration through science education programme in the Solomon four-group design. Brain Sciences, 16(1), Article 64. https://doi.org/10.3390/brainsci16010064
Holm, S. (1979). A simple sequentially rejective multiple test procedure. Scandinavian Journal of Statistics, 6(2), 65–70. https://www.jstor.org/stable/4615733
Mai, N. N., Takahashi, Y., & Oo, M. M. (2020). Testing the effectiveness of transfer interventions using Solomon four-group designs. Education Sciences, 10(4), Article 92. https://doi.org/10.3390/educsci10040092
Steyn, R. (2009). Re-designing the Solomon four-group: Can we improve on this exemplary model? Design Principles and Practices: An International Journal—Annual Review, 3(1), 383–394. https://doi.org/10.18848/1833-1874/CGP/v03i01/37588
Walton Braver, M. C., & Braver, S. L. (1988). Statistical treatment of the Solomon four-group design: A meta-analytic approach. Psychological Bulletin, 104(1), 150–154. https://doi.org/10.1037/0033-2909.104.1.150
solomon_effect_sizes() for effect sizes for meta-analysis, and
fit_solomon_glm() for the analysis of the individual data.
# El Karkri et al. (2025a), Table 8 solomon_from_summary( n = c(9, 25, 17, 37), mean = c(10.94, 7.80, 8.94, 9.35), sd = c(2.26, 2.29, 1.98, 2.11) ) # A six-group design: two treatments and a control. Posttest statistics # computed from the data of Mai et al. (2020); see mai2020. solomon_from_summary( n = c(24, 23, 27, 22, 15, 22), mean = c(2.929167, 3.168116, 3.112346, 3.128788, 3.152184, 3.018548), sd = c(0.434203, 0.369613, 0.355440, 0.383150, 0.374069, 0.354758), treat = c("RP", "GS", "Control", "RP", "GS", "Control"), pretested = c(1, 1, 1, 0, 0, 0), control = "Control" )# El Karkri et al. (2025a), Table 8 solomon_from_summary( n = c(9, 25, 17, 37), mean = c(10.94, 7.80, 8.94, 9.35), sd = c(2.26, 2.29, 1.98, 2.11) ) # A six-group design: two treatments and a control. Posttest statistics # computed from the data of Mai et al. (2020); see mai2020. solomon_from_summary( n = c(24, 23, 27, 22, 15, 22), mean = c(2.929167, 3.168116, 3.112346, 3.128788, 3.152184, 3.018548), sd = c(0.434203, 0.369613, 0.355440, 0.383150, 0.374069, 0.354758), treat = c("RP", "GS", "Control", "RP", "GS", "Control"), pretested = c(1, 1, 1, 0, 0, 0), control = "Control" )
Group sizes, means, and standard errors from the first published experiment with the Solomon design: spelling lessons in a fifth-grade and a sixth-grade class, analyzed with the three-group design (Solomon, 1949, Tables II and III, pp. 144–145). Numbers reported in the publication are reused with citation.
solomon1949solomon1949
A data frame with 6 rows, one per group and grade, and 11 variables:
5 or 6.
Experimental, Control I, or Control II.
Indicators (1 = yes); treat is the spelling
lesson.
Group size.
Pretest mean and its standard error (pretested groups only).
Posttest mean and its standard error.
Mean improvement, as printed, and its standard error (missing for Control II, printed as "?").
The standard errors are the values printed with a plus-or-minus sign, which Solomon's notation (sigma_m, Table I) identifies as standard errors of the means.
Design. In each class, pupils were assigned to three groups that were "roughly equated in spelling ability by means of teachers' judgments" (p. 144), not randomized.
Experimental group. Pretested on a list of words, given a standard spelling lesson, and posttested on the same words.
Control Group I. Pretested and posttested, without the lesson.
Control Group II. Given the lesson and the posttest, without the pretest.
There was no fourth group; Solomon introduced it later in the article for field studies (p. 147).
Known result. fit_solomon_1949() reproduces the published values
from these means: an inferred pretest of 3.0 and 5.7, improvements for
Control Group II of 8.2 and 8.7, and interactions I = -2.2 (grade 5) and
-3.1 (grade 6). The pretest reduced the effect of the lesson, so the usual
two-group design would have underrated it (p. 145).
Caveats. The groups are small (8 to 10 pupils) and were not randomized. Solomon printed the standard error of Control Group II's improvement as "?", since it depends on the inferred pretest.
Solomon, R. L. (1949). An extension of control group design. Psychological Bulletin, 46(2), 137–150. https://doi.org/10.1037/h0062958
fit_solomon_1949(), elkarkri2025a, mai2020
solomon1949 g6 <- solomon1949[solomon1949$grade == 6, ] fit_solomon_1949(post_mean = g6$mean, pre_mean = g6$pre_mean[1:2], n = g6$n)solomon1949 g6 <- solomon1949[solomon1949$grade == 6, ] fit_solomon_1949(post_mean = g6$mean, pre_mean = g6$pre_mean[1:2], n = g6$n)
Provides tools for analyzing, teaching, and studying the Solomon four-group experimental design. The package includes the historical Tests A-I workflow, unified generalized linear models with robust covariance estimation, stratified randomization inference, Solomon-specific full-information maximum likelihood, and observed- and latent-variable structural equation models.
The package distinguishes historically important procedures from contemporary recommendations and emphasizes explicit Solomon-specific estimands, structural pretest missingness, reproducible diagnostics, and modern inference.
Key historical references include Huck & Sandler (1973), Walton Braver & Braver (1988), the Sawilowsky and Markman methodological exchanges, and van Engelenburg (1999).
Each exported function's help page, and the reference index of the package website, shows the function's lifecycle stage, in the stages of the lifecycle package (Henry & Wickham, 2026):
Stable. The interface is settled. Any change goes through deprecation: the old name keeps working, with a warning, through v1.x, when the arguments that follow a former argument name are also named.
Experimental. The function is tested, but its interface or defaults
may change. fit_solomon_sem() has no simulation study yet at Solomon
sample sizes. The issue #55 study found no measurement-invariance
criterion that holds its false-rejection rate in Solomon-sized groups,
which affects fit_solomon_sem_latent() and invariance_solomon().
The analysis of designs with several treatments in fit_solomon_glm() is
experimental, because the rule for error control set before its
simulation study (issue #45) was not met for two omnibus tests with
three treatments and 10 participants per group. The pre-specified
rules of their simulation studies were not met for fit_solomon_mmrm()
(issue #57) and for fit_solomon_mi(), tipping_point_solomon(), and
plot_tipping_point() (issue #82). analysis_plan_solomon() stays
experimental until researchers have used it (issue #81).
Deprecated. A former name that still works, with a warning. Its help page names the replacement.
solomonR 0.8.0 settled the interface (issue #83). The outcome arguments
are y_post and y_pre everywhere, a fitted model is passed as fit,
and the planning functions share one argument order: n (or power),
delta, sens, rho, sigma, alpha. Each function that takes data
vectors also takes an optional data data frame.
Campbell, D. T., & Stanley, J. C. (1966). Experimental and quasi-experimental designs for research. Rand McNally. (Original work published 1963)
Henry, L., & Wickham, H. (2026). lifecycle: Manage the life cycle of your package functions (Version 1.0.5) [R package]. https://doi.org/10.32614/CRAN.package.lifecycle
Huck, S. W., & Sandler, H. M. (1973). A note on the Solomon 4-group design: Appropriate statistical analyses. The Journal of Experimental Education, 42(2), 54–55. https://doi.org/10.1080/00220973.1973.11011460
Sawilowsky, S. S., Kelley, D. L., Blair, R. C., & Markman, B. S. (1994). Meta-analysis and the Solomon four-group design. The Journal of Experimental Education, 62(4), 361–376. https://doi.org/10.1080/00220973.1994.9944140
Solomon, R. L. (1949). An extension of control group design. Psychological Bulletin, 46(2), 137–150. https://doi.org/10.1037/h0062958
Steyn, R. (2009). Re-designing the Solomon four-group: Can we improve on this exemplary model? Design Principles and Practices: An International Journal—Annual Review, 3(1), 383–394. https://doi.org/10.18848/1833-1874/CGP/v03i01/37588
van Engelenburg, G. (1999). Statistical analysis for the Solomon four-group design (Research Report 99-06). University of Twente. ERIC. https://eric.ed.gov/?id=ED435692
Walton Braver, M. C., & Braver, S. L. (1988). Statistical treatment of the Solomon four-group design: A meta-analytic approach. Psychological Bulletin, 104(1), 150–154. https://doi.org/10.1037/0033-2909.104.1.150
The sample size, pretest and posttest means, and standard deviations of the eight groups of a Solomon design with three treatments: a study of how information about one's own ability changes self-efficacy perceptions, with 1,723 police trainees (Steyn, 2005, Table 5.59, pp. 151–152). It is the eight-group study that Steyn (2009) describes, and Steyn and Mynhardt (2008) report it in English. Numbers reported in the publication are reused with citation.
steyn2005steyn2005
A data frame with 8 rows, one per group, and 8 variables:
The group's label in the thesis: EG1 to EG3 are the
pretested treatment groups, KG1.1 to KG1.3 the unpretested
treatment groups, KG2 the pretested control, and KG3 the
unpretested control.
Norms, Marking, Test, or Control.
1 if the group was pretested, 0 if not.
Sample size.
Pretest mean and standard deviation (pretested groups only).
Posttest mean and standard deviation.
Design. Three treatments and a control, each with and without a pretest (pp. 103–105). Each treatment added a source of information about the participant's ability (p. 102):
Test. Completing a 60-item cognitive test.
Marking. Completing the test and marking one's own answers.
Norms. Completing and marking the test, and receiving the test's norms.
The outcome is the total score on a 45-item questionnaire of self-efficacy perceptions (p. 94). The posttest followed the treatment after a break of 10 minutes (p. 107).
Assignment. Participants were not randomized individually. Fifty-six
existing classes of a police training college were allocated to the eight
groups, seven classes to each, in consultation with the college's
management, and the thesis states that this allocation was not random
(pp. 105–106). The classes had been formed from the order in which
trainees reported for training. The thesis is not consistent on this
point. Its introduction says that participants were divided at random
into eight groups and that the groups were assigned at random to the
conditions (p. 9), and it calls the allocation random again on p. 107.
So does the English report, which does not mention the classes (Steyn &
Mynhardt, 2008, pp. 566–567).
The method chapter, followed here, gives the detail: the researcher
judged the existing classes to be random groups and made no further
random assignment (pp. 105–106), and balanced the groups by sex: each
held five men's classes and two women's classes (Steyn, 2005, p. 106).
The analyses in the thesis, and those
below, treat participants as the units, so they do not allow for the
classes. See baseline_solomon() for nonrandomized designs and
validate_solomon() for clustered ones.
Known results. These statistics reproduce the analyses in the thesis:
One-way ANOVA of the eight posttest groups (Table 5.60, p. 152): F(7, 1715) = 4.545.
Scheffé's (1953) tests (Table 5.61, p. 153), within .001. Only the unpretested Test group differs from the two control groups (p = .002 and p = .011).
The 2 x 2 ANOVAs of each treatment against the control (Tables 5.21, 5.34, and 5.47; pp. 128, 135, 142; Steyn & Mynhardt, 2008, Table 2, p. 569), within rounding. For Test: intervention F = 21.3, pretest F = 4.5 (p = .033), and interaction F = 2.0 (p = .152). For Marking: 9.3 (p = .002), 0.4 (p = .538), and 0.0 (p = .929). For Norms, the thesis ran this analysis with 213 participants in the unpretested group (Table 5.45, pp. 141–142), one fewer than in Table 5.59, so its error degrees of freedom are 854 and those computed from these statistics are 855. The F statistics for Norms (14.0, 0.9, and 0.1) are the same to one decimal.
Steyn and Mynhardt (2008) report only these three analyses, judged at the .01 level (p. 568), so they read the pretest effect for Test (p = .033) as no effect (p. 568); the thesis calls it significant at .05 (p. 128). Their means of the treated and untreated groups reproduce as unweighted averages of the two groups' means. Their effect size d divides the difference by what they call the mean standard deviation (p. 568): 13.00, 12.696, and 12.803 (Table 2, p. 569), the "Totaal" rows of the thesis (Tables 5.19, 5.32, and 5.45; pp. 127, 134, 142). For Norms, their means and that standard deviation follow the 213 participants of Table 5.45, not the 214 of Table 5.59 and of their own Table 1 (p. 567). Their text gives the Marking pretest p as .583 (p. 568); their Table 2 and these statistics give .538.
The treatments lowered the scores. The thesis analyzed the design as
overlapping four-group designs, one with the treatments pooled and one for
each treatment, and then as a one-way analysis of variance of the eight
posttests (pp. 103–105). The joint model of solomon_from_summary() tests
the Pretest x Condition interaction once, F(3, 1715) = 1.00, p = .392.
Language. The thesis is in Afrikaans. The condition labels are solomonR's.
Steyn, R. (2005). Self-evaluasie en die vorming van selfdoeltreffendheidspersepsies [Self-evaluation and the forming of self-efficacy perceptions] [Doctoral thesis, University of South Africa]. Unisa Institutional Repository. https://hdl.handle.net/10500/1745
Scheffé, H. (1953). A method for judging all contrasts in the analysis of variance. Biometrika, 40(1–2), 87–104. https://doi.org/10.1093/biomet/40.1-2.87
Steyn, R. (2009). Re-designing the Solomon four-group: Can we improve on this exemplary model? Design Principles and Practices: An International Journal—Annual Review, 3(1), 383–394. https://doi.org/10.18848/1833-1874/CGP/v03i01/37588
Steyn, R., & Mynhardt, J. (2008). Factors that influence the forming of self-evaluation and self-efficacy perceptions. South African Journal of Psychology, 38(3), 563–573. https://doi.org/10.1177/008124630803800310
solomon_from_summary(), fit_solomon_steyn(), mai2020,
lana1959
steyn2005 # One model for all eight groups. with(steyn2005, solomon_from_summary(n, mean, sd, treat = condition, pretested = pretested, control = "Control"))steyn2005 # One model for all eight groups. with(steyn2005, solomon_from_summary(n, mean, sd, treat = condition, pretested = pretested, control = "Control"))
Combine one-tailed p-values that test the same directional hypothesis into
a single Z. This is provided to reproduce the Walton Braver & Braver (1988)
meta-analytic option (Test I) for the Solomon four-group design. Use cautiously and document assumptions about homogeneity; see
the 1988–1990 exchanges for caveats.
stouffer_solomon(p)stouffer_solomon(p)
p |
numeric vector of one-tailed p-values (same direction) |
Walton Braver and Braver (1988, p. 152) convert the one-tailed p-value of
each test to z and refer the combined z to a normal table. Their worked
example reports z = 2.05 with p = .040 (p. 153), the two-tailed value, so
fit_solomon_classic() judges Test I by p_meta_two_tailed. The one-tailed
value is also returned.
list with z_meta, p_meta_two_tailed, and p_meta_one_tailed
Sawilowsky, S. S., Kelley, D. L., Blair, R. C., & Markman, B. S. (1994). Meta-analysis and the Solomon four-group design. The Journal of Experimental Education, 62(4), 361–376. https://doi.org/10.1080/00220973.1994.9944140
Stouffer, S. A., Suchman, E. A., DeVinney, L. C., Star, S. A., & Williams, R. M., Jr. (1949). The American soldier: Adjustment during army life (Vol. 1). Princeton University Press.
Walton Braver, M. C., & Braver, S. L. (1988). Statistical treatment of the Solomon four-group design: A meta-analytic approach. Psychological Bulletin, 104(1), 150–154. https://doi.org/10.1037/0033-2909.104.1.150
stouffer_solomon(c(0.10, 0.11)) # Walton Braver and Braver's (1988, p. 153) example: the ANCOVA (p = .0993) # and the t test (p = .2127), halved to one-tailed p-values in the # direction of the effect, give z = 2.05 and p = .040. stouffer_solomon(c(0.0993, 0.2127) / 2)stouffer_solomon(c(0.10, 0.11)) # Walton Braver and Braver's (1988, p. 153) example: the ANCOVA (p = .0993) # and the t test (p = .2127), halved to one-tailed p-values in the # direction of the effect, give z = 2.05 and p = .040. stouffer_solomon(c(0.0993, 0.2127) / 2)
Repeats
fit_solomon_mi() over a range of offsets added to the imputed
posttests of chosen Solomon groups, and reports the smallest offset in
each direction at which the conclusion about a contrast changes. White et
al. (2011, "Perform Sensitivity Analyses" section, para. 1) suggest
reporting "how large an amount should be added to or
subtracted from imputed outcomes" without changing the interpretation, and
Little et al. (2012, p. 1358) call a finding robust if it holds over the
plausible offsets.
tipping_point_solomon( y_post, treat, pretested, y_pre = NULL, contrast = "ATE (avg over pretest)", groups = "all", deltas = NULL, alpha = 0.05, m = 100, robust = c("HC3", "none"), seed = NULL, data = NULL )tipping_point_solomon( y_post, treat, pretested, y_pre = NULL, contrast = "ATE (avg over pretest)", groups = "all", deltas = NULL, alpha = 0.05, m = 100, robust = c("HC3", "none"), seed = NULL, data = NULL )
y_post |
Numeric posttest scores, with |
treat |
Treatment indicator coded 0/1 (or logical). Designs with
several treatments are not supported; see |
pretested |
Pretest indicator coded 0/1 (or logical). |
y_pre |
Optional numeric pretest scores, missing by design for unpretested participants. |
contrast |
The Solomon contrast to follow. Default is the average treatment effect. |
groups |
The groups whose imputed posttests are shifted: |
deltas |
Offsets to try, on the posttest scale. The default is 21 values from -1 to 1 pooled within-group standard deviations of the observed posttests. Zero is always included. |
alpha |
Significance level that defines the conclusion. Default 0.05. |
m |
Number of imputations for each offset. Default 100. |
robust |
Covariance for each completed-data analysis: |
seed |
Optional random-number seed. When |
data |
Optional data frame. When supplied, the other data arguments
are looked up in it first, as bare column names ( |
Which groups. Offsets confined to some groups test different
departures from missing at random. Offsets in the treatment groups
(groups = "treatment") bear on the treatment effect. Offsets that differ
between the pretested and unpretested groups, for example in the
pretested treatment group alone (groups = 1), bear on the sensitization
contrast.
Common random numbers. Every offset uses the same imputation draws,
so the estimates change smoothly with the offset. The location of the
tipping point still carries Monte Carlo error from the imputations: in
the worked example on mai2020, the tipping point for sensitization
ranged from 0.1 to 0.5 standard deviations across seeds with 100
imputations and was 0.3 with 2,000. Before reporting a tipping point,
increase m or compare a few seeds.
An object of class solomon_tipping with results (one row per
offset: the offset in posttest units and in standard deviations, and
the pooled estimate, interval, and p-value), tipping (the smallest
negative and positive offsets at which the conclusion differs from the
one under MAR, NA when it does not change within the range), and the
settings used.
Experimental, with fit_solomon_mi(), whose validation study it shares.
Little, R. J., D'Agostino, R., Cohen, M. L., Dickersin, K., Emerson, S. S., Farrar, J. T., Frangakis, C., Hogan, J. W., Molenberghs, G., Murphy, S. A., Neaton, J. D., Rotnitzky, A., Scharfstein, D., Shih, W. J., Siegel, J. P., & Stern, H. (2012). The prevention and treatment of missing data in clinical trials. The New England Journal of Medicine, 367(14), 1355–1360. https://doi.org/10.1056/NEJMsr1203730
White, I. R., Horton, N. J., Carpenter, J., & Pocock, S. J. (2011). Strategy for intention to treat analysis in randomised trials with missing outcome data. BMJ, 342, Article d40. https://doi.org/10.1136/bmj.d40
fit_solomon_mi(), plot_tipping_point()
d <- solomon_example set.seed(82) d$y_post[sample(nrow(d), 20)] <- NA tipping_point_solomon(y_post, treat, pretested, y_pre, groups = "treatment", deltas = seq(-10, 10, by = 2.5), m = 10, seed = 1, data = d)d <- solomon_example set.seed(82) d$y_post[sample(nrow(d), 20)] <- NA tipping_point_solomon(y_post, treat, pretested, y_pre, groups = "treatment", deltas = seq(-10, 10, by = 2.5), m = 10, seed = 1, data = d)
Checks that data can support a Solomon analysis before a model is fitted:
equal input lengths, the coding of the design indicators, all cells
present, enough observed outcomes per cell, and the distinction between
structurally absent and incidentally missing values (see
check_solomon_missing()). Problems are returned as a table of issues
rather than stopping at the first one, so every problem is reported at
once. Designs with several treatments are checked too (see control).
validate_solomon( y_post, treat, pretested, y_pre = NULL, min_cell_n = 2, cluster = NULL, control = NULL, data = NULL )validate_solomon( y_post, treat, pretested, y_pre = NULL, min_cell_n = 2, cluster = NULL, control = NULL, data = NULL )
y_post |
Numeric posttest scores. |
treat |
Treatment indicator coded 0/1 (or logical); or a factor or
character vector of conditions, with the control named by |
pretested |
Pretest indicator coded 0/1 (or logical). |
y_pre |
Optional numeric pretest scores, missing by design for unpretested participants. |
min_cell_n |
Minimum number of observed posttest scores required in each cell (at least 2). |
cluster |
Optional cluster identifier (for example, class, school, or site), one value per participant. |
control |
The control condition when |
data |
Optional data frame. When supplied, the other data arguments
are looked up in it first, as bare column names ( |
Accepted coding: pretested must be numeric 0/1 or logical, and so must
treat unless the control condition is named with control. Without
control, factors and character codes are rejected so that group
membership is never inferred from level order. The Solomon four-group
design requires all four cells (Solomon, 1949): pretested treatment,
pretested control, unpretested treatment, and unpretested control.
Designs with several treatments: give treat as a factor or character
vector of conditions and name the control with control. A design with k
treatments requires all 2(k + 1) cells, each treatment and the control
with and without a pretest: six cells for two treatments and eight for
three (Steyn, 2009). Every check below is then made for each of these
cells. Levels of a factor treat that no participant has are left out of
the design, with a note.
Severity:
error: the data cannot support a Solomon analysis as supplied
(unequal lengths, invalid coding, an empty cell, fewer than min_cell_n
observed posttest scores in a cell, or no observed pretests among
pretested participants when y_pre is supplied).
warning: analyses can run, but some participants are excluded or values are inconsistent with the design (unassigned participants, incidental missingness, pretest scores recorded for unpretested participants).
note: information for reporting, such as the range of cell sizes.
min_cell_n is a technical minimum, not a sample-size recommendation: at
least two observations per cell are needed to estimate within-cell
variability, and HC3 standard errors can be undefined for a cell with a
single observation. Plan cell sizes with a power analysis.
Clustered designs: when participants belong to classes, schools, or sites,
supply cluster. The number of clusters and the range of cluster sizes are
then reported for each cell, together with whether treatment and pretesting
were assigned to whole clusters or varied within them.
A cell that contains a single cluster is an error. Class and condition are then completely confounded, as when each Solomon condition is one intact class (El Karkri et al., 2025a): a difference between the classes cannot be separated from the treatment, pretest, or sensitization effect, and no between-cluster variability can be estimated. Cluster-robust inference (Pustejovsky & Tipton, 2018) needs several clusters in every cell. For example, Kvalem et al. (1996) randomized 124 school classes to the four Solomon conditions. When whole clusters are randomized, a cell with two or three clusters is a warning: Hayes and Moulton (2017, p. 128) regard four clusters per arm as an absolute minimum.
An object of class solomon_validation with valid (TRUE when
no errors were found), issues (severity, check, and message), cells
(counts by cell, with clusters and cluster sizes when cluster is
supplied), and missing (the check_solomon_missing() result). For a
design with several treatments, cells has one row for each of the
2(k + 1) cells and conditions names the control and the treatments.
El Karkri, M., Quesada, A., & Romero-Ariza, M. (2025a). The dual impact of pretest sensitisation and the cognitive acceleration through science education programme in the Solomon four-group design. Brain Sciences, 16(1), Article 64. https://doi.org/10.3390/brainsci16010064
Hayes, R. J., & Moulton, L. H. (2017). Cluster randomised trials (2nd ed.). Chapman and Hall/CRC. https://doi.org/10.4324/9781315370286
Kvalem, I. L., Sundet, J. M., Rivø, K. I., Eilertsen, D. E., & Bakketeig, L. S. (1996). The effect of sex education on adolescents' use of condoms: Applying the Solomon four-group design. Health Education Quarterly, 23(1), 34–47. https://doi.org/10.1177/109019819602300103
Mai, N. N., Takahashi, Y., & Oo, M. M. (2020). Testing the effectiveness of transfer interventions using Solomon four-group designs. Education Sciences, 10(4), Article 92. https://doi.org/10.3390/educsci10040092
Pustejovsky, J. E., & Tipton, E. (2018). Small-sample methods for cluster-robust variance estimation and hypothesis testing in fixed effects models. Journal of Business & Economic Statistics, 36(4), 672–683. https://doi.org/10.1080/07350015.2016.1247004
Solomon, R. L. (1949). An extension of control group design. Psychological Bulletin, 46(2), 137–150. https://doi.org/10.1037/h0062958
Steyn, R. (2009). Re-designing the Solomon four-group: Can we improve on this exemplary model? Design Principles and Practices: An International Journal—Annual Review, 3(1), 383–394. https://doi.org/10.18848/1833-1874/CGP/v03i01/37588
data(solomon_example) # A valid design. with(solomon_example, validate_solomon(y_post, treat, pretested, y_pre)) # An empty cell makes the design invalid. no_group_3 <- solomon_example[!(solomon_example$pretested == 0 & solomon_example$treat == 1), ] with(no_group_3, validate_solomon(y_post, treat, pretested, y_pre)) # One intact class per condition confounds class with condition. one_class <- with(solomon_example, 2 * pretested + treat) with(solomon_example, validate_solomon(y_post, treat, pretested, y_pre, cluster = one_class)) # A six-group design: two treatments and a control (Mai et al., 2020). validate_solomon(post_behavior, condition, pretested, pre_behavior, control = "Control", data = mai2020)data(solomon_example) # A valid design. with(solomon_example, validate_solomon(y_post, treat, pretested, y_pre)) # An empty cell makes the design invalid. no_group_3 <- solomon_example[!(solomon_example$pretested == 0 & solomon_example$treat == 1), ] with(no_group_3, validate_solomon(y_post, treat, pretested, y_pre)) # One intact class per condition confounds class with condition. one_class <- with(solomon_example, 2 * pretested + treat) with(solomon_example, validate_solomon(y_post, treat, pretested, y_pre, cluster = one_class)) # A six-group design: two treatments and a control (Mai et al., 2020). validate_solomon(post_behavior, condition, pretested, pre_behavior, control = "Control", data = mai2020)