Effect sizes: Cohen's d, eta squared, OR and r
What an effect size is, which one goes with which test, the SD each version of Cohen's d uses, and a worked R example with d and its 95% interval.
Updated . Written by Matt Gencer.
On this page
An effect size tells you how big a difference or an association is. A p-value tells you something else: how surprising your data would be if the true effect were exactly zero. A study needs both, and of the two, the effect size with its confidence interval is the one a reader can use to judge whether a result matters.
This guide explains what effect sizes are, which one belongs with which test, and the details that decide whether a reported number means what the reader thinks it means: which standard deviation sits under Cohen’s d, which denominator sits under eta squared, and what the confidence interval assumes. It then works one example in full, Cohen’s d for two groups of R’s built-in ToothGrowth data, run through a deterministic engine. The other effect sizes are explained with their formulas and the R function that computes them, without invented numbers.
What an effect size is, and why a p-value is not one
A tiny p-value does not mean a big effect. In a very large study, a difference too small to matter in practice can still produce a tiny p-value, and in a small one, a large and important difference can still produce a p-value above 0.05.
The p-value mixes two things together: how large the effect is and how much data you have. An effect size separates out the first. It answers “how much?” rather than “is it zero?”.
There are two broad kinds:
- Unstandardised (simple) effect sizes are in the outcome’s own units: a difference in millimetres of mercury, in points on a test score, in days in hospital. When the units are meaningful to your readers, this is usually the most useful thing you can report. Baguley’s 2009 review argues that simple effect sizes are, for most purposes, more robust and versatile than standardised ones, and recommends a confidence interval with whichever you report.
- Standardised effect sizes divide by a measure of spread, or express the effect as a share of variance, a correlation or a ratio of odds. They let you compare results measured on different scales, combine studies in a meta-analysis, and plan a sample size. Their price is that the standardiser becomes part of the result: change the standard deviation you divide by and you change the effect size, even though the underlying difference has not moved.
Three families of effect size
Most effect sizes you will meet fall into three families. Knowing the family tells you how to read the number.
The difference family expresses a difference between means in standard deviation units. Cohen’s d, Hedges’ g and Glass’s delta are its members. A d of one half means the means are half a standard deviation apart. These suit two-group comparisons of a continuous outcome.
The variance-explained family expresses how much of the variation in the outcome goes with a factor or a predictor. Eta squared, partial eta squared, omega squared, epsilon squared, r squared and R squared belong here. They are proportions, from 0 to 1, and they suit ANOVA and regression, where a factor may have more than two levels and “the difference” is not a single number.
The association family covers correlations and their relatives, and the measures for categorical outcomes. Pearson’s r, Spearman’s rho and the rank-biserial correlation run from -1 to 1. For binary outcomes the usual effect sizes are ratios or differences of risks or odds: the odds ratio, the relative risk and the risk difference. For larger contingency tables, Cramér’s V plays the role of a correlation.
The families are connected: for two groups, d, the point-biserial correlation and eta squared all describe the same comparison and convert into each other. That is useful for a meta-analysis, but do not report three versions of one effect as if they were three findings.
Which effect size goes with which test
The test you ran mostly decides the effect size, because the effect size should describe the same quantity the test is about. A test of means gets an effect size about means; a test of ranks gets one about ranks.
| Test | Effect size | In R (effectsize package) | Interval and what it assumes |
|---|---|---|---|
| Two independent groups, Student’s t-test | Cohen’s d_s with the pooled SD, or Hedges’ g | cohens_d(y ~ g, data = d), hedges_g(...) |
Noncentral t; assumes normal outcomes with equal variances |
| Two independent groups, Welch’s t-test | d with the average of the two variances, or Glass’s delta | cohens_d(..., pooled_sd = FALSE), glass_delta(...) |
Approximate when variances differ; glass_delta() applies Hedges’ correction by default |
| Paired t-test | Cohen’s d_z (SD of the differences), or d_av / d_rm | cohens_d(x, y, paired = TRUE), repeated_measures_d(x, y, method = "av") |
Noncentral t on the differences |
| Mann-Whitney test | Rank-biserial correlation | rank_biserial(y ~ g, data = d) |
Normal approximation via Fisher’s z; no normality assumption on the data |
| Wilcoxon signed-rank test | Matched-pairs rank-biserial correlation | rank_biserial(x, y, paired = TRUE) |
Normal approximation via Fisher’s z; no normality assumption on the data |
| One-way ANOVA | Eta squared, omega squared or epsilon squared | eta_squared(fit), omega_squared(fit) |
Noncentral F; one-sided by default |
| Factorial ANOVA, ANCOVA | Partial or generalised eta squared, partial omega squared | eta_squared(fit, partial = TRUE), eta_squared(fit, generalized = TRUE) |
Noncentral F; one-sided by default |
| Kruskal-Wallis test | Rank epsilon squared | rank_epsilon_squared(y ~ g, data = d) |
Bootstrap; one-sided by default |
| Linear regression | R squared, or Cohen’s f squared | cohens_f_squared(fit) |
Noncentral F; partial and one-sided by default |
| Correlation | Pearson’s r or Spearman’s rho | cor.test() in base R |
Fisher z transformation |
| 2x2 table, binary outcome | Odds ratio, relative risk, risk difference | oddsratio(), riskratio(), arr() |
Normal approximation, ratios on the log scale; the sampling design decides which measure is valid |
| Larger contingency table | Cramér’s V | cramers_v(table) |
Noncentral chi-squared; bias-adjusted and one-sided by default |
| Logistic regression | Odds ratio per unit of the predictor | exp(coef(fit)), exp(confint(fit)) |
Profile likelihood |
The design matters as well as the test: a paired d_z and an independent-groups d_s sit on different scales even for the same mean difference.
The effectsize package, described by Ben-Shachar, Lüdecke and Makowski in 2020, computes most of these with their confidence intervals. For d and the ANOVA measures it uses the noncentrality parameter method that Steiger set out in 2004; for the others it uses the methods in the last column. The effect size in the worked example below also comes from this package.
Cohen’s d: one name, several standardisers
Cohen’s d is a difference between two means divided by a standard deviation. The difficulty is that “a standard deviation” is not one thing. Lakens’ 2013 primer, written to settle exactly this confusion, lays out the versions and when each fits. Which one you used is part of the result, so a report that says only “Cohen’s d” leaves the reader guessing.
d_s: two independent groups, pooled SD
For two independent groups, the classic version divides the mean difference by the pooled standard deviation:
d_s = (mean_1 - mean_2) / SD_pooled, where SD_pooled = sqrt(((n_1 - 1) * SD_1^2 + (n_2 - 1) * SD_2^2) / (n_1 + n_2 - 2)).
The pooled SD is the same quantity Student’s t-test uses, which is why d_s and Student’s t convert directly into each other: d_s = t * sqrt(1 / n_1 + 1 / n_2). Pooling assumes the two groups share one population standard deviation. With equal group sizes, the pooled SD is the square root of the average of the two variances, so the point estimate does not lean on that assumption; with unequal sizes, it does.
The usual confidence interval for d_s inverts a noncentral t distribution. That method assumes the outcome is normal within each group and the two variances are equal. When either fails, the interval is approximate, and the more the variances differ, the less you should trust its exact limits.
Hedges’ g: the small-sample correction
The sample d_s overestimates the population effect slightly, and the bias is larger in small samples. Hedges showed in 1981 that the estimator is biased and derived the unbiased one. In practice, Hedges’ g multiplies d by a correction factor that is close to 1:
g = d_s * (1 - 3 / (4 * (n_1 + n_2) - 9)) (the common approximation).
The difference only matters in small samples. Lakens notes that the difference is very small, especially in samples above about 20, and suggests reporting g anyway, since it costs nothing. If you report g, call it g.
Glass’s delta and Welch-style d
When the groups clearly differ in spread, pooling makes little sense. Two alternatives exist. Glass’s delta divides by the standard deviation of the control group only, which keeps the effect on the scale of the untreated population; it is the natural choice when a treatment is expected to change the spread as well as the mean. The other option, offered by cohens_d(..., pooled_sd = FALSE), divides by the square root of the average of the two variances. That pairs naturally with Welch’s t-test, but it is a different quantity from d_s and should be labelled as such. Two defaults in the effectsize package are worth knowing: glass_delta() divides by the SD of the second group unless you name the control group with reference, and it applies Hedges’ small-sample correction unless you pass adjust = FALSE.
Paired designs: d_z is not d_s
In a paired design, the same units are measured twice. Here you have two quite different choices of standardiser, and they give numbers on different scales.
d_z divides the mean difference by the standard deviation of the differences. It matches the paired t-test exactly, since that test is a one-sample test on the differences, and it is the standardiser that power software for paired designs expects. But because pairing removes the variation between units, the SD of the differences is often much smaller than the SD of either measurement, so d_z is often much larger than a d_s computed from the same means.
d_av and d_rm divide by a standard deviation of the raw measurements: the average of the two SDs, or an SD corrected for the correlation between the measurements. These put a within-subject effect on roughly the same scale as a between-subjects d_s, which is what you want when comparing across designs. Lakens recommends reporting one of these, and notes that power software for within-subjects designs takes d_z as its input.
In R, cohens_d(x, y, paired = TRUE), with the two measurements as separate vectors, returns d_z, the one-sample effect size on the differences. The grouped formula form, y ~ g, refuses paired = TRUE; for data in wide format use cohens_d(Pair(x, y) ~ 1, data = d). repeated_measures_d() offers d_av, d_rm and other versions through its method argument, with Hedges’ correction applied by default. The rule for the write-up is the same as for every d: name the standardiser.
Worked example: Cohen’s d for two groups on ToothGrowth
The data are ToothGrowth, which comes with R and records Crampton’s 1947 vitamin C experiment in guinea pigs. Each of the 60 animals got vitamin C through orange juice (OJ) or through ascorbic acid (VC), at one of three doses, and had its odontoblasts measured; odontoblasts are the cells that build tooth tissue, and their length is called “length” from here on. No animal appears in both delivery groups, so the comparison is between two independent groups of 30, which is exactly the design d_s was made for.
The question for this example is how large the difference in mean length between the two delivery methods is, in standard deviation units. Seeded and run in R; Student’s two-sample t-test was chosen before the run. The R script and the full output are below the article.
Why Student’s test here, when Welch’s is the safer default for testing two means? Because this example is about d_s, and Student’s test uses the same pooled standard deviation that d_s divides by. The test and the effect size then rest on the same assumption, and their intervals are directly comparable. With equal group sizes, as here, Student’s and Welch’s t statistics are identical; only the degrees of freedom differ.
The result
| Quantity | Value |
|---|---|
| Animals analysed | 60 (30 per delivery method) |
| Mean length, orange juice (OJ) | 20.66 |
| Mean length, ascorbic acid (VC) | 16.96 |
| Difference in means, OJ minus VC | 3.70 |
| 95% confidence interval for the difference | -0.167 to 7.567 |
| Student’s t | 1.915 on 58 degrees of freedom |
| p-value (two-sided) | 0.0604 |
| Cohen’s d_s (pooled SD) with its 95% interval | 0.4945 (-0.02151 to 1.006) |
Reading the effect size
Start with the simple effect. The orange juice group’s mean length was 3.7 units higher than the ascorbic acid group’s, with a 95% interval from -0.167 to 7.567. In the outcome’s own units, the data are compatible with no difference and with a difference about twice the estimate.
Now the standardised version. Cohen’s d_s is 0.4945: the means are just under half a pooled standard deviation apart. That is the 3.7-unit difference re-expressed on a scale that does not depend on how length was measured.
The interval for d runs from -0.02151 to 1.006. It crosses zero, matching the interval for the raw difference and the p-value of 0.0604; the three are different views of one result, and they agree. It also reaches past 1, so the data are compatible with anything from no effect to a difference of a full standard deviation. The honest one-line summary is an estimated difference of about half a standard deviation, measured imprecisely.
Notice what the interval does to any label. The app’s plain-language explanation calls this d a small effect, because it applies Cohen’s conventions with a strict cut and 0.4945 falls just under the half that marks “medium” (the section on benchmarks explains the cut). Yet the interval spans “none”, “small”, “medium” and “large” at once, and a label on the point estimate hides that.
The interval for d is computed by the standard noncentral t method, so it assumes normal outcomes and equal variances. The engine’s assumption checks speak to both. Levene’s test did not detect unequal variances (statistic 1.214, p = 0.275), which is not evidence that the variances are equal, since such tests have little power at this size. The Shapiro-Wilk test found evidence of non-normality in the orange juice group (W = 0.918, p = 0.0236) and none in the ascorbic acid group (W = 0.966, p = 0.428). The engine flagged this and suggested a rank-based alternative, the Mann-Whitney test. For a mean difference with 30 animals per group, the t-test itself is usually robust to a departure like this, but the interval for d leans on normality more directly, because d divides by a standard deviation. Treat its limits as approximate.
There is a likely reason for the non-normality in the design. Each delivery group pools 10 animals at each of three doses, so if length depends on dose, each group is a mixture of three clusters. This run tested delivery method only and produced no dose output, so that is a candidate explanation to check, not a finding. The reasoning for why it would matter to the effect size goes like this: if dose explains part of the spread, the pooled SD includes that spread and is larger than the SD within a single dose, so the same mean difference comes out as fewer standard deviations. A standardised effect inherits every source of variance in its denominator. The analysis that matches the full design is a two-way ANOVA, explained in the two-way ANOVA guide, and its natural effect sizes are the partial and generalised eta squared described below.
If non-normality were the concern, the rank-biserial correlation would describe ranks instead; it answers a different question and does not replace d.
What the example says about sample size, and what it does not
The engine also reports a sensitivity figure for the design, which is about the study, not about this result: with 30 animals per group, a two-sided test at the 0.05 level had 80% power only for effects of d = 0.74 or larger, and detecting an effect of half a standard deviation with 80% power would need 64 animals per group.
Use that figure to read the result, not to plan the next study. It says this study could reliably detect only fairly large effects, which is why a non-significant result here is inconclusive rather than evidence of no effect. It is not “observed power”, which is computed from the observed effect and adds nothing to the p-value. Nor should the observed d of 0.49 size a new study: its interval runs from about zero to about one. Size it for the smallest effect that would matter in your field.
Eta squared, partial eta squared and omega squared
When a factor has more than two levels, there is no single mean difference to standardise. ANOVA effect sizes instead ask what share of the variation in the outcome goes with the factor. The definitions differ only in the denominator.
Eta squared divides the sum of squares for the effect by the total sum of squares: eta^2 = SS_effect / SS_total. It is the proportion of all the variation in the outcome that is associated with the factor. In a one-way ANOVA it is the same as R squared from the equivalent regression.
Partial eta squared divides by the effect plus the error only: eta_p^2 = SS_effect / (SS_effect + SS_error). Other factors in the model are left out of the denominator. In a one-way design there are no other factors, so partial eta squared equals eta squared; Lakens remarks wryly on how often one-way results carry the “partial” label anyway. In a factorial design, partial eta squared is usually larger than eta squared, and it changes when you add or remove other factors, so partial values from different designs are not comparable.
Generalised eta squared, proposed by Olejnik and Algina in 2003, was designed for that comparability problem. It treats manipulated factors and measured (individual-difference) factors differently, so that the same effect gets a similar value whether it was studied in a between-subjects or a repeated-measures design. If you want your ANOVA effect size to be comparable with other studies, especially across designs, this is the one to report. When every factor is manipulated between subjects, as Lakens notes, generalised and partial eta squared are identical.
Omega squared and epsilon squared correct a bias. Eta squared describes the sample, and in the sample a factor always explains some variation by chance, so eta squared overestimates the population value. Omega squared and epsilon squared adjust for this and are less biased. The difference is largest in small samples and shrinks as samples grow. They can come out slightly negative when the true effect is near zero; that is a sign of a negligible effect, usually reported as zero.
Cohen’s f turns the same share into a ratio, f^2 = eta_p^2 / (1 - eta_p^2), or R^2 / (1 - R^2) for a regression. Cohen defined it for power analysis, which is why sample-size software asks for it.
Two R details change the numbers you get. In the effectsize package, eta_squared() returns the partial version by default; pass partial = FALSE for the classic one. And its confidence intervals are one-sided by default, with the upper limit fixed at 1, so the “interval” printed is a lower bound. If you want a conventional two-sided 95% interval, pass alternative = "two.sided". A second trap is the type of sums of squares: eta_squared() applied to an aov or lm fit with unbalanced data uses sequential (Type I) sums of squares, so the value for a factor depends on the order you entered it.
The one-way ANOVA, Welch and Kruskal-Wallis guide covers when each of those tests fits; the rank-based version of a variance-explained effect size, rank epsilon squared, pairs with Kruskal-Wallis.
Correlations as effect sizes: r and the rank-biserial correlation
A correlation is already an effect size. Pearson’s r describes the strength and direction of a linear association between two continuous variables, from -1 to 1, and its interval comes from the Fisher z transformation, which cor.test() in base R reports. Its square, r squared, is the share of variance in one variable that goes with a linear function of the other. Both are useful, but r squared makes modest correlations sound negligible, so say which you report.
Spearman’s rho is a correlation of ranks. It fits monotonic but not linear relationships, and ordinal data.
For two groups compared with a Mann-Whitney test, the matching effect size is the rank-biserial correlation. Kerby’s 2014 paper gives the clearest way to read it, the simple difference formula: take every pair made of one value from each group, count the proportion of pairs in which the first group’s value is higher (f) and the proportion in which it is lower (u), and the correlation is r = f - u. A rank-biserial correlation of a half means the first group “wins” 75% of cross-group pairs and loses 25%. The same idea extends to the Wilcoxon signed-rank test for paired data. The t-test or Mann-Whitney guide explains when the rank-based test is the better choice in the first place.
For two groups of equal size, d converts to a correlation as r = d / sqrt(d^2 + 4), and back as d = 2 * r / sqrt(1 - r^2); unequal group sizes change the conversion.
Odds ratios and other effect sizes for binary outcomes
When the outcome is binary (an event happens or not), means and standard deviations are the wrong vocabulary. The effect is a comparison of risks or of odds between groups.
- The risk difference is the difference in the proportion with the event. It is the most directly interpretable for planning: it tells you how many events per hundred a change would add or prevent.
- The relative risk is the ratio of the two risks. It is intuitive (“twice as likely”) but needs the design to give valid risks, which a case-control study does not.
- The odds ratio is the ratio of the two odds. It is what logistic regression estimates and the only one of the three a case-control study can estimate directly. When the outcome is common, it lies further from 1 than the relative risk, so reading an odds ratio as “times as likely” overstates the effect.
All three are effect sizes, and all three should be reported with confidence intervals. In the effectsize package, oddsratio(), riskratio() and arr() (the risk difference) read a 2x2 table with the groups in columns, treatment first, and the event in the first row; a table laid out the other way round answers a different question. On a ratio scale, 1 means no effect and intervals are asymmetric, because they are computed on the log scale and transformed back. Which one fits your study, and how the design restricts the choice, is the subject of the odds ratio or relative risk guide, which this guide does not repeat.
For a 2x2 table, phi (phi(), bias-adjusted by default) is the matching correlation. For larger tables, Cramér’s V gives one association measure from 0 to 1, computed from the chi-squared statistic. It does not say where the association lies, so report the proportions alongside it.
An odds ratio can be converted to an approximate d for a meta-analysis that combines binary and continuous outcomes. Chinn showed in 2000 that the natural log of the odds ratio, divided by a constant equal to π divided by the square root of 3, gives a d on roughly the scale of a continuous outcome: d ≈ ln(OR) * sqrt(3) / pi. The conversion assumes the binary outcome comes from dichotomising an underlying continuous variable with a logistic distribution. It is a tool for synthesis, not a reason to report a d instead of the odds ratio you estimated.
How big is big? Benchmarks and their limits
Cohen offered conventional values for “small”, “medium” and “large” effects: for d, a fifth, a half and four fifths of a standard deviation; for r, a tenth, three tenths and a half; for eta squared in ANOVA, about 1%, 6% and 14% of variance. These numbers are everywhere, and they are often used as if they were facts about the world.
They are single reference points, not ranges. Software that labels an effect turns them into ranges with a strict cut, calling everything from one value up to just under the next by the lower name, and the app’s plain-language explanation does the same. So a d just under a half is “small” and a d of exactly a half is “medium”, though no reader could tell the two apart. The label adds a cliff edge the data do not have.
Cohen did not intend them that way. In the second edition of his book he wrote that there is “a certain risk inherent in offering conventional operational definitions” for these terms, and that the conventions are “recommended for use only when no better basis for estimating the ES index is available”. He also stressed that the terms are relative to the area of research and to the specific content and methods of a given investigation. Lakens makes the same point with an example: an intervention that reliably reduced suicide rates with a d of only a tenth would be enormously important.
So use the benchmarks as a last resort, not as a default. Better bases for judging an effect, in roughly the order to try them:
- The raw effect in meaningful units. A difference of 3.7 units of tooth length means something to someone who studies tooth growth. A threshold for clinical or practical importance, set before the study, is the strongest basis of all.
- Effects in comparable studies. What range of effects has your field observed for similar interventions or exposures? An effect half the size of the usual one is small in context whatever its label.
- The smallest effect of interest. What is the smallest effect that would change a decision, a theory or a recommendation? An effect whose interval lies entirely below it is unimportant, however significant.
- Cohen’s conventions, only if none of the above is available, and labelled as conventions.
Never label an effect without its interval, which often spans several labels. And a d_z from a paired study is not “large” by the same standard as a d_s from a between-groups study.
Confidence intervals for effect sizes
Effect sizes are estimates, and in the sample sizes common in research their intervals are wide. In the worked example, 60 animals gave an interval for d about a full standard deviation wide.
Most intervals for standardised effect sizes are computed with the noncentrality parameter method that Steiger described in 2004: find the noncentral t, F or chi-squared distributions that place the observed test statistic at the 2.5th and 97.5th percentiles, and convert their noncentrality parameters back into effect sizes. That method is exact when the test’s own assumptions hold exactly, and approximate otherwise. Bootstrap intervals are an alternative when the assumptions are doubtful, at the cost of needing enough data for the resampling to be stable.
Two rules:
- Check whether the interval is two-sided. Some software prints one-sided intervals for variance-explained measures by default, as noted above. A one-sided interval with an upper limit of 1 is a lower bound, not a range.
- Read the interval against the effects that matter. If it includes both negligible and important effects, the study is inconclusive about importance, whatever the p-value says.
How to report an effect size
A complete report gives the simple effect with its interval, the test, and a standardised effect size with its exact name, the standardiser and its interval. For the worked example:
Mean odontoblast length was 20.66 in the orange juice group and 16.96 in the ascorbic acid group (30 animals each), a difference of 3.70 (95% CI -0.17 to 7.57); Student’s t(58) = 1.92, p = 0.060. The standardised difference was Cohen’s d_s = 0.49 (pooled SD; 95% CI -0.02 to 1.01), computed by the noncentral t method, which assumes equal variances. The interval is compatible with no difference and with a large one.
Points to get right:
- Name the effect size exactly: “d_s with the pooled SD”, “d_z”, “Hedges’ g”, “partial eta squared”. Each is a different quantity.
- Give the interval and its level, and say whether it is two-sided.
- Report what the interval assumes when an assumption is doubtful, as the non-normality in the example is.
- State the software and function, since defaults (partial or not, one- or two-sided, pooled or not) change the numbers.
Common mistakes
Saying “Cohen’s d” without saying which one. A d_z from paired data and a d_s from independent groups can differ a great deal for the same mean difference. Name the standardiser.
Treating Cohen’s benchmarks as universal. Cohen offered them as a fallback for when nothing better is available. Judge an effect against your field and the smallest effect that would matter.
Computing “observed power” from the effect size. It is a function of the p-value and adds no information. A sensitivity analysis of the design, as in the example, is the useful version.
Forgetting what is in the denominator. A standardised effect inherits every source of variation in its SD. By the reasoning in the worked example, pooling over a second factor that affects the outcome makes the SD larger and d smaller; the ToothGrowth example pools over dose, though this run did not test dose itself.
Rerunning the example
You can rerun the worked example yourself. The script below the article is the one the engine wrote, unedited, with its seed and data path, next to the output it printed. Run on the same package versions, it recomputes the Student’s t-test and the sensitivity figure. It does not compute the effect size or the assumption checks; those come from the engine itself. To reproduce Cohen’s d and its interval, add effectsize::cohens_d(len ~ supp, data = data) to the script, which uses the pooled SD by default. effectsize::hedges_g(len ~ supp, data = data) gives the small-sample-corrected version, and car::leveneTest(len ~ factor(supp), data = data) with shapiro.test() within each group reproduces the assumption checks.
To see how dose changes the picture, fit a two-way model and compute eta squared for each term with effectsize::eta_squared(fit, partial = TRUE, alternative = "two.sided"). The engine’s reference page for Student’s t-test lists what it reports for this method, and the guide to choosing a statistical test starts from your design when the test itself is the open question.
Worked example
Data: Crampton EW (1947). The growth of the odontoblasts of the incisor tooth as a criterion of the vitamin C intake of the guinea pig. Journal of Nutrition 33(5):491-504. https://doi.org/10.1093/jn/33.5.491. Seed: 20261021.
Run on Celeus engine 0.30.0, seed 20261021, public data.
Output
# Results - Test: Student's t-test - n: 60 - statistic: 1.915 - p-value: 0.0604 - effect size: Cohen's d = 0.4945 (95% CI -0.02151 to 1.006) - 95% CI: [-0.167, 7.567] - seed: 20261021 ## Assumption checks - normality by group (Shapiro-Wilk): passed=FALSE - variance homogeneity (Levene): passed=TRUE (no evidence of unequal variances) - sample size: passed=TRUE (adequate n) ## Power (sensitivity, not observed power) - minimum detectable effect at n=60: Cohen's d = 0.7356 - to detect a conventional medium effect: 64 per group to detect d=0.50 - alpha = 0.05, target power = 0.8
R script
# Celeus - reproduce.R (run from this package folder; bundled data in data/)
# Test: Student's t-test | engine 0.30.0 | catalog c39-d3cd
# Research context: not provided for this run.
# Reproduces the recorded result deterministically.
set.seed(20261021)
.data_path <- "data/effect-sizes-explained.csv"
if (!file.exists(.data_path)) stop("Run reproduce.R from the package folder (the bundled data is in data/).")
data <- readr::read_csv(.data_path, show_col_types = FALSE) # needs the readr package
clean_cells <- function (df)
{
ctrl_collapse <- "[\r\n\t\v\f]+"
zero_width_chars <- intToUtf8(c(8203L, 65279L), multiple = TRUE)
uni_space_chars <- intToUtf8(c(160L, 8239L, 8199L), multiple = TRUE)
clean_text <- function(x) {
out <- x
for (ch in zero_width_chars) out <- gsub(ch, "", out,
fixed = TRUE)
out <- gsub(ctrl_collapse, " ", out)
for (ch in uni_space_chars) out <- gsub(ch, " ", out,
fixed = TRUE)
trimws(gsub(" +", " ", out))
}
changed_cols <- character(0)
cells_cleaned <- 0L
retyped <- character(0)
for (j in seq_along(df)) {
col <- df[[j]]
if (!is.character(col))
next
cleaned <- clean_text(col)
n_changed <- sum(!is.na(col) & !is.na(cleaned) & col !=
cleaned, na.rm = TRUE)
if (n_changed > 0L) {
changed_cols <- c(changed_cols, names(df)[j])
cells_cleaned <- cells_cleaned + n_changed
}
df[[j]] <- cleaned
non_blank <- cleaned[!is.na(cleaned) & nzchar(cleaned)]
if (length(non_blank) && all(grepl("^[+-]?(0|[1-9][0-9]*)([.][0-9]+)?$",
non_blank))) {
parsed <- suppressWarnings(as.numeric(cleaned))
was_blank <- is.na(cleaned) | !nzchar(cleaned)
lost <- (is.na(parsed) | is.infinite(parsed)) & !was_blank
if (!any(lost)) {
finite <- parsed[!is.na(parsed)]
all_whole <- all(finite == floor(finite))
in_range <- all(abs(finite) <= .Machine$integer.max)
df[[j]] <- if (all_whole && in_range)
as.integer(parsed)
else parsed
retyped <- c(retyped, names(df)[j])
}
}
}
names(df) <- clean_text(names(df))
if (length(changed_cols)) {
attr(df, "ingest_clean_columns") <- changed_cols
attr(df, "ingest_clean_cells_cleaned") <- cells_cleaned
}
if (length(retyped))
attr(df, "ingest_clean_retyped") <- retyped
df
}
data <- clean_cells(data)
# Complete-case analysis: drop rows missing any analysis value.
.acols <- c("len", "supp")
data <- data[stats::complete.cases(data[, .acols, drop = FALSE]), , drop = FALSE]
result <- t.test(`len` ~ `supp`, data = data, var.equal = TRUE)
print(result)
# Sensitivity: minimum detectable effect at n=60 (power=0.8, alpha=0.05). NOT observed power.
power <- pwr::pwr.t2n.test(n1 = 30, n2 = 30, sig.level = 0.05, power = 0.8)
print(power)Common questions
What is an effect size?
An effect size is a number that says how large a difference or an association is, as opposed to a p-value, which says how surprising the data would be if there were no effect at all. It can be in the outcome's own units, such as a difference in means, or standardised, such as Cohen's d, eta squared, an odds ratio or a correlation r.
How do I calculate an effect size?
Pick the effect size that matches your test and design, then compute it with its confidence interval. In R, the effectsize package covers the common ones: cohens_d() or hedges_g() for two means, eta_squared() or omega_squared() for ANOVA terms, rank_biserial() for rank tests, and cramers_v() for contingency tables. Always state which standardiser or denominator you used.
Which effect size goes with a Mann-Whitney test?
The rank-biserial correlation is the natural partner of the Mann-Whitney test. It equals the proportion of cross-group pairs in which the first group's value is higher minus the proportion in which it is lower, so it runs from -1 to 1 and needs no normality assumption. Cohen's d is the wrong partner, because it describes means and standard deviations, not ranks.
Is partial eta squared the same as eta squared?
Only in a one-way design, where the two are identical. With more than one factor, partial eta squared divides by the effect plus error only, so it is usually larger than eta squared and is not comparable across designs that include different factors. Say which one you report, and consider generalised eta squared when comparing across designs.
Can I plan my next study from the effect size I observed?
Not on its own. An observed effect size from one study has a wide interval, and an effect that happened to come out large is the one most likely to be followed up, so planning from it tends to give a study that is too small. Plan for the smallest effect that would matter in your field instead.
How does effect size relate to sample size and power?
A sample-size calculation takes the effect size you want to detect, the significance level and the power you want, and returns the number of units needed. Smaller effects need far more data. In the worked example, detecting half a standard deviation with 80% power at the 0.05 level needs 64 animals per group, and the 30 per group actually used could reliably detect only d = 0.74 or larger.
What counts as a small, medium or large effect size?
Cohen's conventions for d are a fifth, a half and four fifths of a standard deviation, and for r a tenth, three tenths and a half. Cohen himself recommended them only when no better basis exists. Judge an effect first in its own units, against effects in comparable studies and against the smallest effect that would matter.
Sources
- Cohen J (1988). Statistical Power Analysis for the Behavioral Sciences, 2nd edition. Lawrence Erlbaum Associates (reissued by Routledge, 2013). doi:10.4324/9780203771587
- Lakens D (2013). Calculating and reporting effect sizes to facilitate cumulative science: a practical primer for t-tests and ANOVAs. Frontiers in Psychology 4:863. doi:10.3389/fpsyg.2013.00863
- Hedges LV (1981). Distribution theory for Glass's estimator of effect size and related estimators. Journal of Educational Statistics 6(2):107-128. doi:10.3102/10769986006002107
- Olejnik S, Algina J (2003). Generalized eta and omega squared statistics: measures of effect size for some common research designs. Psychological Methods 8(4):434-447. doi:10.1037/1082-989X.8.4.434
- Steiger JH (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. doi:10.1037/1082-989X.9.2.164
- Baguley T (2009). Standardized or simple effect size: what should be reported? British Journal of Psychology 100(3):603-617. doi:10.1348/000712608X377117
- Kerby DS (2014). The simple difference formula: an approach to teaching nonparametric correlation. Comprehensive Psychology 3:11.IT.3.1. doi:10.2466/11.IT.3.1
- Chinn S (2000). A simple method for converting an odds ratio to effect size for use in meta-analysis. Statistics in Medicine 19(22):3127-3131. doi:10.1002/1097-0258(20001130)19:22<3127::AID-SIM784>3.0.CO;2-M
- Ben-Shachar MS, Lüdecke D, Makowski D (2020). effectsize: Estimation of effect size indices and standardized parameters. Journal of Open Source Software 5(56):2815. doi:10.21105/joss.02815
Methods discussed
Try it on your own data
Upload a dataset and Celeus suggests a method, checks its assumptions, runs it in R, and gives you the script to rerun it.
Try it in Celeus