Introduction to DMAR

Ken Kelley

September 2026

What Is DMAR?

DMAR is a more modern, more general, and greatly expanded reimagining of the MBESS package (Kelley, 2007a, Journal of Statistical Software; 2007b, Behavior Research Methods). MBESS itself was originally framed as Methods for the Behavioral, Educational, and Social Sciences, but the methods it implements became useful far beyond that scope; DMAR ships under a new name to make that scope expansion explicit. Its emphasis is the methodology that the substantive disciplines depend on most: confidence intervals for effect sizes built from noncentral sampling distributions, sample size planning for both power and accuracy in parameter estimation (AIPE), reliability, factor analysis, and the critical values used in classical inference. DMAR is intended to serve as the computational companion to Maxwell, Delaney, and Kelley’s Designing Experiments and Analyzing Data (4th ed., 2027; henceforth MDK), and it is suitable for both instruction and substantive research.

Although the package’s origins are in psychology, the questions it answers are not field-specific. Researchers in biostatistics (clinical-trial effect size CIs and AIPE-based trial sizing), organizational behavior and management science (intervention, training, and program evaluation), information systems (user-experience A/B comparisons; technology-adoption studies), education (instructional effectiveness, longitudinal achievement gains), sociology (program evaluation, attitudinal surveys), and the methodological literature itself will find tools here for the same three tasks: estimating effect sizes, attaching confidence intervals that hold their stated coverage, and planning future studies that will not be underpowered or underestimated.

What DMAR keeps from MBESS is the philosophy, that is, the same insistence on effect sizes with uncertainty quantified, and on planning studies for accurate estimation rather than only for sufficient power. What DMAR changes is the implementation: a uniform snake_case interface, tidy data.frame returns with stable column schemas, native ggplot2 visualization, dependencies that follow current best practice, and a test suite. The function families have also been broadened, particularly the ss_power_* family, which now covers between-subjects, within-subjects, mixed, and multi-level designs across the chapters of MDK.

Why Effect Size Confidence Intervals?

A p-value tells you whether an effect is plausibly nonzero in the direction you tested. It does not tell you how large the effect is, and it does not tell you how precisely you have estimated it. Both of those questions matter scientifically: a study can produce a “significant” but trivially small effect, or a “nonsignificant” effect whose confidence interval is so wide that it is consistent with both a small and a large true value. Reporting an effect size and a confidence interval for it addresses both shortcomings, and the practice is now standard in most quantitative areas of psychology and education (Kelley & Preacher, 2012).

The technical machinery underneath is less familiar than it should be. For most standardized effect sizes, the sampling distribution is noncentral (e.g., the noncentral t underlying Cohen’s \(d\), the noncentral F underlying \(R^2\), the noncentral \(\chi^2\) underlying RMSEA), which means the correct interval is asymmetric about the point estimate. The usual symmetric “estimate \(\pm\) standard error” shortcut ignores that skew, so it puts the limits in the wrong places. DMAR computes the correct intervals from the noncentral distributions directly. This is the common engine behind every ci_*() function in the package.

Two Philosophies of Sample Size Planning

Researchers who plan studies in DMAR can do so from either of two complementary perspectives:

It is worth being precise about what accuracy means in this framework, because the term is sometimes used loosely. Accuracy considers precision and bias together: an accurate estimator is one whose sampling distribution is concentrated and centered on the target parameter. Precision alone, in contrast, can always be improved by trading bias for precision. A trivial estimator that returns the same constant value for every sample has zero variance and is therefore arbitrarily “precise,” but it is biased unless the constant happens to equal the population parameter. The AIPE framing asks for sample sizes that buy narrow confidence intervals (a precision target) without trading bias to get there. The confidence interval width target \(w\) in ss_aipe_* is shorthand for that joint accuracy goal: a CI that is informative because it is both narrow and centered on the parameter (Kelley & Rausch, 2006; Kelley & Maxwell, 2003; Maxwell, Kelley, & Rausch, 2008).

The two perspectives often imply different sample sizes for the same study. An AIPE plan tends to require more subjects than a power plan when the expected effect is moderate, because narrow intervals are more demanding than null rejection. DMAR provides both side by side so that the choice can be made deliberately, in light of the scientific question.

When Do You Reach for DMAR?

The package is organized around five families of tasks. Pick the one that matches the question you are trying to answer.

1. I Just Ran an ANOVA, t-Test, or Regression. What’s the Effect Size and a CI for It?

Use the ci_* family.

# Confidence interval for omega squared (proportion of variance accounted
# for) from a one-way ANOVA with F = 11.221 on (4, 50) df, total N = 55.
ci_omega_squared(F_value = 11.221, df_effect = 4, df_error = 50, N = 55)
effect omega_squared lower_limit upper_limit F_value df_effect df_error N
overall 0.426 0.226 0.587 11.2 4 50 55

# More naturally, from a fitted model:
fit <- aov(weight ~ group, data = PlantGrowth)
ci_omega_squared(fit)
effect omega_squared lower_limit upper_limit F_value df_effect df_error N
group 0.204 0.0099 0.464 4.85 2 27 30

The output is a tidy data.frame: an effect label, the point estimate (omega_squared), the lower and upper limits of the CI, and the inputs that produced it (F_value, df_effect, df_error, and N). That format makes it easy to feed the result directly into a table or a forest plot (plot_ci() is built to consume it).

CI variants exist for many other effect sizes: ci_smd() for the standardized mean difference (Cohen’s \(d\)); ci_smd_c() for the standardized mean difference using the control-group SD as the divisor; ci_pvaf() for the proportion of variance accounted for by a single predictor; ci_snr() and ci_srsnr() for signal-to-noise ratios; ci_R(), ci_R2(), and ci_rc() for correlations and standardized regression coefficients; ci_rmsea() for the RMSEA model-fit index; and others.

2. I’m Planning a Study. How Many Subjects Do I Need?

Use ss_power_* for sufficient power, or ss_aipe_* for sufficient precision. The same effect can be approached from either angle.

# Power-based: per-group n needed for 90% power to detect a contrast among
# 4 groups with population means (90, 92, 88, 81) and within-group
# variance 144. The contrast compares the average of the first three
# groups against the fourth.
ss_power_contrast(
  c_weights     = c(1/3, 1/3, 1/3, -1),
  mu            = c(90, 92, 88, 81),
  sigma_squared = 144,
  desired_power = 0.90
)
term value
necessary_n_per_group 26
total_N 104
actual_power 0.907
noncentral_t_parm 3.31
effect_size_f 0.325
# AIPE-based: n needed so a 95% CI around a standardized mean difference
# (delta) of 0.50 is no wider than 0.30 units (a tight interval).
ss_aipe_smd(delta = 0.50, conf_level = 0.95, width = 0.30)
term value
necessary_n_per_group 353
supposed_smd 0.5
width 0.3

Confidence level: 95%

The ss_power_* family in v1.0.0 spans most of the standard designs covered in MDK: one-way ANOVA (ss_power_one_way_anova), factorial ANOVA (ss_power_factorial_anova), repeated measures ANOVA with sphericity adjustment (ss_power_rm_anova), split-plot mixed ANOVA (ss_power_split_plot_anova), Pearson correlation (ss_power_r), two-independent-groups standardized mean difference (ss_power_smd), contrasts standardized and unstandardized (ss_power_c, ss_power_sc, ss_power_c_ancova, ss_power_contrast), regression coefficients (ss_power_reg_coef), and two-level random-intercept models for cluster-randomized trials (ss_power_mixed_effects). For SEM-style designs, use ss_power_sem(). AIPE counterparts exist for the correspondingly named effects.

3. I Want to Test a Specific Contrast or Set of Pairwise Comparisons.

Use contrast_test() for arbitrary contrasts in a one-way ANOVA, with optional multiple-comparison adjustment.

fit <- aov(weight ~ group, data = PlantGrowth)
# All pairwise comparisons, Tukey-protected family-wise error rate:
contrast_test(fit, contrasts = "pairwise", adjust = "tukey")
contrast estimate se t df p_value p_adjusted ci_lower ci_upper
trt1 - ctrl -0.371 0.279 -1.33 27 0.1944 0.3909 -1.06 0.32
trt2 - ctrl 0.494 0.279 1.77 27 0.0877 0.1980 -0.197 1.19
trt2 - trt1 0.865 0.279 3.1 27 0.0045 0.0120 0.174 1.56

Confidence level: 95%

For the bare critical value of a particular procedure, see the cv_* family: cv_t(), cv_tukey_hsd(), cv_scheffe(), cv_smm() (the studentized maximum modulus), cv_dunnett(), and cv_z(). These return the threshold value alone, suitable for inclusion in user code or hand-checking textbook examples.

4. I Have Within-Subjects (Repeated Measures) Data.

Start with anova_within(), which combines the univariate within-subjects F test with a sphericity diagnostic (Mauchly’s W) and the three standard \(\varepsilon\)-corrected p-values (Greenhouse-Geisser, Huynh-Feldt, lower-bound). The motivation is that an uncorrected within-subjects F test can be substantially anticonservative when the sphericity assumption fails, and anova_within() puts the diagnostic and the correction in one place.

if (requireNamespace("nlme", quietly = TRUE)) {
  res <- anova_within(nlme::Orthodont,
                      id = "Subject", time = "age", outcome = "distance")
  res
}
adjustment F_value df_1 df_2 p_value epsilon
none 38 3 78 < 0.0001 NA
Greenhouse-Geisser 38 2.63 68.4 < 0.0001 0.877
Huynh-Feldt 38 2.95 76.8 < 0.0001 0.984
lower_bound 38 1 26 < 0.0001 0.333

For the underlying components separately, see mauchly_test() and epsilon_corrections(). For visualizing individual subject trajectories, see plot_trajectories() and plot_trajectories_fitted().

5. I Want Descriptive Statistics, a Correlation Table, or Distribution-Shape Diagnostics.

descriptives() returns a tidy summary suitable for screening:

descriptives(attitude)$descriptives
#>     variable    type  n n_missing prop_missing     mean median        sd min
#> 1     rating numeric 30         0            0 64.63333   65.5 12.172562  40
#> 2 complaints numeric 30         0            0 66.60000   65.0 13.314757  37
#> 3 privileges numeric 30         0            0 53.13333   51.5 12.235430  30
#> 4   learning numeric 30         0            0 56.36667   56.5 11.737013  34
#> 5     raises numeric 30         0            0 64.63333   63.5 10.397226  43
#> 6   critical numeric 30         0            0 74.76667   77.5  9.894908  49
#> 7    advance numeric 30         0            0 42.93333   41.0 10.288706  25
#>   max   q25   q75   skewness    kurtosis
#> 1  85 58.75 71.75 -0.3967148 -0.49460977
#> 2  90 58.50 77.00 -0.2387632 -0.38172518
#> 3  83 45.00 62.50  0.4202101 -0.04219127
#> 4  75 47.00 66.75 -0.0598894 -1.07638294
#> 5  88 58.25 71.00  0.2189518 -0.28201359
#> 6  92 69.25 80.00 -0.9596072  0.69175815
#> 7  72 35.00 47.75  0.9425594  1.07314413

Adding correlations = TRUE appends a Pearson correlation matrix. For a publication-ready correlation table with p-values, confidence intervals, and significance stars (and, optionally, HTML or LaTeX export), use correlations_test():

correlations_test(attitude, stars = TRUE)
#> Correlations (Pearson, 95% CI)
#> 
#>               rating        complaints    privileges    learning      raises        critical      advance       
#> ----------------------------------------------------------------------------------------------------------------
#> rating        -                                                                                                 
#>                                                                                                                 
#>                                                                                                                 
#>                                                                                                                 
#> 
#> complaints    .83***        -                                                                                   
#>               p < .0001                                                                                         
#>               [.66, .91]                                                                                        
#>               N = 30                                                                                            
#> 
#> privileges    .43*          .56**         -                                                                     
#>               p = .0189     p = .0013                                                                           
#>               [.08, .68]    [.25, .76]                                                                          
#>               N = 30        N = 30                                                                              
#> 
#> learning      .62***        .60***        .49**         -                                                       
#>               p = .0002     p = .0005     p = .0056                                                             
#>               [.34, .80]    [.30, .79]    [.16, .72]                                                            
#>               N = 30        N = 30        N = 30                                                                
#> 
#> raises        .59***        .67***        .45*          .64***        -                                         
#>               p = .0006     p < .0001     p = .0136     p = .0001                                               
#>               [.29, .78]    [.41, .83]    [.10, .69]    [.36, .81]                                              
#>               N = 30        N = 30        N = 30        N = 30                                                  
#> 
#> critical      .16           .19           .15           .12           .38*          -                           
#>               p = .4091     p = .3205     p = .4375     p = .5417     p = .0401                                 
#>               [-.22, .49]   [-.19, .51]   [-.22, .48]   [-.25, .46]   [.02, .65]                                
#>               N = 30        N = 30        N = 30        N = 30        N = 30                                    
#> 
#> advance       .16           .22           .34           .53**         .57***        .28           -             
#>               p = .4132     p = .2328     p = .0633     p = .0025     p = .0009     p = .1292                   
#>               [-.22, .49]   [-.15, .54]   [-.02, .63]   [.21, .75]    [.27, .77]    [-.09, .58]                 
#>               N = 30        N = 30        N = 30        N = 30        N = 30        N = 30                      
#> 
#> Note. * p < .05, ** p < .01, *** p < .001.

For interrater agreement, use cohen_kappa() (two raters), fleiss_kappa() (multiple raters), or icc() (intraclass correlation, all six classical forms). For distribution-shape statistics in isolation, use skewness() and kurtosis().

What DMAR Is Not

DMAR deliberately overlaps with, but does not duplicate, several specialized packages.

DMAR layers tidy effect size CIs, sample size planning, and publication-ready output over those tools, rather than replacing them.

A Note on Argument Naming

The package uses snake_case throughout. Capital letters in identifiers are reserved for statistically meaningful symbols, for example R2 for the squared multiple correlation, N for total sample size, S for a covariance matrix, Lambda for a factor-loadings matrix, F_value for an F statistic. Every other argument is lowercase, with the result that examples read consistently regardless of discipline:

ci_R2(R2 = 0.25, N = 100, p = 5, random_predictors = TRUE)
ss_power_reg_coef(rho2_Y_X = 0.78, rho2_Y_X_without_j = 0.74,
                  p = 5, desired_power = 0.85)
ss_aipe_cv_sensitivity(true_cv = 0.25, estimated_cv = 0.25,
                       width = 0.10, conf_level = 0.95, G = 200)

The MBESS dot.case style (conf.level, Random.Predictors, Specified.N) is no longer accepted. Scripts written against MBESS will need to convert dots to underscores in argument names and lower-case any prefix words that are not themselves statistical notation. Function names are unchanged in nearly all cases (smd(), ci_smd(), ci_R2(), ss_aipe_reg_coef(), etc.), and return shapes are unchanged or strictly richer.

If you have scripts written against MBESS or against pre-1.0 DMAR snapshots and you see errors of the form

Error in foo(...) : unused argument (Group.1 = ...)

the fix is mechanical: replace dots with underscores in the argument name (Group_1, n_1, Mean_1, Specified_N, etc.) and then lowercase the non-meaningful capitalized prefix words (group_1, mean_1, specified_N, …). See NEWS.md for the full mapping. The exception worth noting on the function side is aipe_smd(), which has been renamed to ss_aipe_smd() to align it with the rest of the ss_aipe_* family.

The motivation for the unification is simple: the former mix of Random.Predictors (dot.case for legacy MBESS arguments) and conf_level (snake_case for newer arguments) was confusing in side-by-side examples, especially in teaching, and a single convention removes the source of friction.

Where to Next

References

Kelley, K. (2007a). 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

Kelley, K. (2007b). Methods for the behavioral, educational, and social sciences: An R package. Behavior Research Methods, 39(4), 979–984. https://doi.org/10.3758/BF03192993

Kelley, K., & Maxwell, S. E. (2003). Sample size for multiple regression: Obtaining regression coefficients that are accurate, not simply significant. Psychological Methods, 8(3), 305–321.

Kelley, K., & Preacher, K. J. (2012). On effect size. Psychological Methods, 17(2), 137–152.

Kelley, K., & Rausch, J. R. (2006). Sample size planning for the standardized mean difference: Accuracy in parameter estimation via narrow confidence intervals. Psychological Methods, 11(4), 363–385.

Maxwell, S. E., Delaney, H. D., & Kelley, K. (2027). Designing experiments and analyzing data: A model comparison perspective (4th ed.). Routledge.

Maxwell, S. E., Kelley, K., & Rausch, J. R. (2008). Sample size planning for statistical power and accuracy in parameter estimation. Annual Review of Psychology, 59, 537–563. https://doi.org/10.1146/annurev.psych.59.103006.093735