Celeus

How to report a t-test in APA style, with examples

Fill-in APA 7 sentences for Welch, Student, paired and one-sample t-tests, the formatting rule behind each symbol, and a worked example from a real R run.

Updated . Written by Matt Gencer.

On this page

An APA-style t-test report is one sentence that carries six things: the group means and standard deviations, the name of the test, the difference with its confidence interval, t with its degrees of freedom, the exact p-value and an effect size. This guide gives a fill-in sentence for Welch’s, Student’s, paired and one-sample t-tests, explains the formatting rule behind every symbol, and then fills the Welch sentence from one real analysis run in R, a result that happens to be non-significant, which is the case most write-ups get wrong.

If you are still choosing which t-test to run, start with t-tests explained. For the same reporting conventions applied to other tests (chi-square, ANOVA, correlation, regression), see the guide to reporting statistics in APA style.

What a complete t-test report contains

APA’s reporting standards for quantitative research (JARS-Quant) ask for the number of cases, cell means and standard deviations, every inferential test with exact p-values and the degrees of freedom needed to reconstruct it, and effect-size estimates with confidence intervals where possible. For a t-test, that becomes this checklist:

  1. The design and the test, by name. Welch’s t-test, Student’s t-test, paired t-test or one-sample t-test. “A t-test” alone is ambiguous.
  2. Sample sizes, per group for independent groups, or the number of pairs.
  3. Descriptive statistics: the mean and standard deviation of each group, or of each condition and of the differences for a paired design.
  4. The difference with its confidence interval. The estimate a reader actually needs, and how precisely it was estimated.
  5. The test statistic: t, its degrees of freedom in parentheses, and the exact p-value.
  6. An effect size with its interval, usually Cohen’s d, with the version named.

Items 1 and 2 often sit in the methods; items 3 to 6 make up the results sentence.

The APA 7 formatting rules behind each symbol

APA’s own numbers and statistics guide (the 7th-edition handout, last updated in September 2024) gives the rules that decide how each number is typed. The ones that matter for a t-test:

  • Italicize statistical symbols. M, SD, t, df, p, d and n are italic. Greek letters are not italicized.
  • Use the symbol only next to an operator. Write M = 20.66 inside parentheses, but write “the mean was” in running text, not “the M was”.
  • Do not define the standard symbols. M, SD, t, df, p and n need no definition. Other abbreviations do, and the guide lists CI among them, so write “confidence interval (CI)” once before you use “CI”.
  • Put a space before and after an operator: t = 1.92, not t=1.92. A negative value has a space before the minus sign but not after it.
  • Leading zero only when the statistic can exceed 1. A p-value, a correlation or a proportion cannot be greater than 1, so it has no zero before the decimal point: p = .061. A mean difference, t or Cohen’s d can exceed 1, so it keeps the zero: d = 0.49.
  • Two decimals for means, standard deviations and inferential statistics such as t, as a general rule. The guide says to round as much as possible while keeping the precision a reader needs, and to use one decimal for means and standard deviations of integer-scale data such as questionnaire totals.
  • Exact p-values to two or three decimals, such as p = .061. Below .001, write p < .001 rather than a long string of zeros.
  • No commas in degrees of freedom, however large the sample.
  • Do not repeat the same statistics in a table and the text. If a table gives the means and standard deviations, the sentence can point to it.

Two layout rules sit outside that handout. Confidence limits go in square brackets after the label, as in 95% CI [-0.17, 7.57], the form Purdue OWL’s APA 7 summary gives as 95% CI [LL, UL]. Degrees of freedom sit in parentheses after the symbol, as in t(df); neither source spells that out, but APA-style journals use it consistently.

The guide has no rule for degrees of freedom that are not whole numbers, which Welch’s test produces. Keep two decimals: t(55.31) shows at once that the variances were not pooled; t(55) leaves the reader guessing.

Fill-in sentences for each t-test

Copy the pattern for your design and replace each bracketed slot with your own numbers. The structure is the same in all four: descriptives first, then the estimate and its interval, then the test, then the effect size.

Welch’s t-test (two independent groups, the default)

[Group A] (M = [mean], SD = [SD], n = [n]) and [group B] (M = [mean], SD = [SD], n = [n]) differed by [difference] [units], 95% CI [[lower], [upper]]. Welch’s t-test gave t([df, two decimals]) = [t], p = [p], Cohen’s d = [d], 95% CI for d [[lower], [upper]].

Welch’s version does not assume equal variances, which is why it is the safer choice for two independent groups. Keep the decimals in the degrees of freedom.

Student’s t-test (two independent groups, equal variances assumed)

[Group A] (M = [mean], SD = [SD], n = [n]) and [group B] (M = [mean], SD = [SD], n = [n]) differed by [difference] [units], 95% CI [[lower], [upper]]. Student’s t-test, assuming equal variances, gave t([n1 + n2 - 2]) = [t], p = [p], Cohen’s d = [d], 95% CI for d [[lower], [upper]].

The degrees of freedom are a whole number, the total sample minus two. Say in the methods why equal variances were assumed. “Levene’s test was not significant” is a poor reason; t-tests explained covers why.

Paired t-test (two measurements on the same units)

Across [n] [participants or pairs], [measure] was higher at [condition B] (M = [mean], SD = [SD]) than at [condition A] (M = [mean], SD = [SD]). The mean difference was [difference] [units] (SD of the differences = [SD]), 95% CI [[lower], [upper]], t([n - 1]) = [t], p = [p], Cohen’s dz = [d], 95% CI for dz [[lower], [upper]].

Three points are specific to the paired design. The degrees of freedom are the number of pairs minus one. The test is run on the within-pair differences, so the standard deviation of those differences is the most informative spread to report. And the effect size needs a name: dz divides the mean of the within-pair differences by their standard deviation, which shrinks as the two measurements become more correlated, so it is not comparable with a between-groups d. Lakens’ 2013 primer sets out when each version is the right summary; say which you used. If you are unsure whether your data are paired, the paired t-test or Wilcoxon guide starts from that question.

One-sample t-test (one group against a fixed value)

[Group] (M = [mean], SD = [SD], n = [n]) differed from the reference value of [value] by [difference] [units], 95% CI [[lower], [upper]], t([n - 1]) = [t], p = [p], Cohen’s d = [d], 95% CI for d [[lower], [upper]].

Here d divides the difference from the reference value by the sample standard deviation. State where the reference value came from, since the result only means something relative to it.

Which line of your software output to report

Software can print several versions of the test; the sentence must match the one you chose. R’s t.test() prints Welch’s by default, with fractional degrees of freedom. SPSS prints two rows, one assuming equal variances and one not; report the row for the test you decided on in advance, not the row with the smaller p. Fractional degrees of freedom mark the Welch row; the pooled row always has n1 + n2 - 2. For a paired test, check that the degrees of freedom equal the number of pairs minus one.

Worked example: a Welch report built from a real run

The example uses ToothGrowth, a dataset that ships with R. It comes from a 1947 nutrition experiment by Crampton in which 60 guinea pigs received vitamin C by one of two delivery methods, orange juice or ascorbic acid, at one of three doses. The outcome is odontoblast length, a measure of tooth growth, shortened here to “length”. Each animal gives one measurement, so the two delivery groups of 30 are independent: a two-sample design, which makes Welch’s t-test the right default.

The question: does mean length differ between the two delivery methods? Seeded and run in R; Welch’s t-test was chosen before the run. The output and script appear below the article.

What the engine reported

Quantity Value
Animals analysed 60 (30 per delivery method)
Mean length, orange juice 20.66
Mean length, ascorbic acid 16.96
Difference in means, orange juice minus ascorbic acid 3.70, 95% CI [-0.171, 7.571]
Welch’s t 1.915 on 55.31 degrees of freedom
p-value (two-sided) 0.0606
Cohen’s d (pooled SD) 0.4945, 95% CI [-0.02151, 1.006]

From output to sentence

Rounding to APA’s conventions gives t = 1.92, p = .061 (no leading zero), the interval [-0.17, 7.57], d = 0.49 with its interval [-0.02, 1.01], and degrees of freedom of 55.31, decimals kept. The second interval is labelled as the one for d. The filled sentence:

Mean odontoblast length was 20.66 (SD = [SD]) in the orange juice group and 16.96 (SD = [SD]) in the ascorbic acid group (n = 30 each). The difference of 3.70, 95% CI [-0.17, 7.57], was not statistically significant, Welch’s t(55.31) = 1.92, p = .061, Cohen’s d = 0.49, 95% CI for d [-0.02, 1.01]. The interval is compatible with no difference and with a moderately large one.

The standard deviations are left as slots on purpose: the engine run reports the group means but not the standard deviations, and every number here comes from that run. One line of R gives them:

aggregate(len ~ supp, data = ToothGrowth, FUN = sd)

If your SDs are already in a table, point to the table instead of repeating them.

Four decisions inside that sentence

The effect size names its standardizer. The d here divides the mean difference by the pooled standard deviation of the two groups. Its interval is computed the standard way for d, which assumes equal variances, so treat it as approximate. If your groups differ in size and spread, say which standardizer you used; a reader cannot recover it from the number.

The interval is reported for the difference, in the outcome’s own units. The 95% CI of -0.17 to 7.57 is the main result: the data are compatible with anything from essentially no difference to a gap about twice the estimate.

The non-significant result is reported in full. Same format, exact p, interval, effect size. Writing “n.s.” or “p > .05” would throw away the information a reader or a future meta-analysis needs.

The conclusion is “inconclusive”, not “no effect”. A p of .061 does not show that the two delivery methods give equal lengths, and it is not a 6% probability that there is no difference. Greenland and colleagues list both readings among their 25 common misinterpretations of p-values and confidence intervals. The engine adds a sensitivity figure that makes the point concrete: 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. Detecting d = 0.50 with 80% power would need 64 animals per group. Label a figure like this a sensitivity analysis of the design, never “observed power” computed from the result, which adds nothing to the p-value. Do not size a follow-up study from this estimate either: its interval is far too wide.

What goes in the methods section

The results sentence is only half the report. In the methods, a reader needs enough to judge whether the test fits:

  • The test and why. “Mean length was compared between delivery methods with Welch’s t-test, which does not assume equal variances.”
  • How independence follows from the design. Here, each animal contributes one measurement.
  • What you checked and what you found, in neutral words. In the example, the engine’s Shapiro-Wilk check found evidence of non-normality in the orange juice group (W = 0.92, p = .024) and none detected in the ascorbic acid group; Levene’s test did not detect unequal variances (p = .275), which is not evidence that they are equal. The engine flagged the non-normality and suggested a rank-based alternative. With 30 animals per group and a moderate departure, the mean difference is usually close enough to normally distributed for a t-test, and switching to Mann-Whitney would change the question from means to ranks. The t-test or Mann-Whitney guide covers that decision.
  • The software and versions, and where the analysis script can be found.

One caveat belongs in any write-up of this example. ToothGrowth crosses delivery method with three doses, and the t-test pools over dose, so it answers a marginal question: the delivery difference averaged over the doses used. That mixture is a plausible but untested reason for the non-normality in one group. The analysis matching the full design is a two-way ANOVA; the t-test here is a reporting example, not the analysis this study needs.

Common reporting mistakes

Leaving out the descriptives. A t and a p without means and standard deviations cannot be interpreted or reused. JARS asks for them for each group.

Reporting “p < .05” or “n.s.” instead of the exact value. APA asks for exact p down to .001.

An effect size with no interval and no name. Report d with its 95% CI, and say which d it is, especially for a paired design.

Writing “there was no difference” after a non-significant test. Say the result was not statistically significant and what the interval still allows. Do not “accept the null hypothesis”, call a p just above .05 “a trend toward significance”, or say a significant test “proves” a difference.

Calling a one-sided test two-sided, or choosing one-sided after seeing the data. State the direction in the methods if it was fixed in advance; otherwise report the two-sided p.

Calling d “small”, “medium” or “large” and stopping there. Those labels are rough conventions, not findings. Say what the interval allows and what size of difference would matter in your field.

Reporting many t-tests across three or more groups. Use a model built for several groups and adjust follow-up comparisons; the multiple comparisons guide explains the options.

Rerunning the example

The R script below the article is the one the engine generated, followed by the output it printed. On the same package versions it reproduces the Welch test and the sensitivity figure. The effect size and assumption checks are not in it; effectsize::cohens_d(len ~ supp, data = data), car::leveneTest(len ~ factor(supp), data = data) and shapiro.test() within each group reproduce them. The methods are documented on the engine’s reference pages for Welch’s t-test, Student’s t-test and the paired t-test, and the guide to reproducible statistical analysis explains what a reviewer needs to rerun a result like this one.

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: 20261016.

Run on Celeus engine 0.30.0, seed 20261016, public data.

Output

# Results

- Test: Welch's t-test
- n: 60
- statistic: 1.915
- p-value: 0.0606
- effect size: Cohen's d = 0.4945 (95% CI -0.02151 to 1.006)
- 95% CI: [-0.171, 7.571]
- seed: 20261016

## 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: Welch's t-test  |  engine 0.30.0  |  catalog c39-d3cd
# Research context: not provided for this run.
# Reproduces the recorded result deterministically.

set.seed(20261016)
.data_path <- "data/how-to-report-a-t-test.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 = FALSE)
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

How do I report an independent samples t-test in APA style?

Give each group's mean and standard deviation, name the test (Welch's or Student's), then the difference with its 95% confidence interval, t with its degrees of freedom in parentheses, the exact p-value without a leading zero, and an effect size such as Cohen's d with its own interval.

Should degrees of freedom have decimals for Welch's t-test?

Yes. Welch's adjustment produces degrees of freedom that are usually not a whole number, so keep them to two decimals, for example t(55.31). Rounding them to a whole number hides which test was run and makes the result harder to check.

Do I put a zero before the decimal point in a p-value?

No. APA 7 drops the leading zero for any statistic that cannot be greater than 1, which includes p-values, correlations and proportions. Statistics that can exceed 1, such as t, a mean difference or Cohen's d, keep the zero: d = 0.49, p = .061.

How do I report a non-significant t-test?

Report it in exactly the same format as a significant one, with the exact p-value, the interval and the effect size. Then say what the interval allows: a non-significant result is inconclusive when the interval still includes differences that would matter, and it never shows that the means are equal.

Which Cohen's d should I report for a paired t-test?

There is more than one, and they give different numbers. The common one, d_z, divides the mean of the within-pair differences by the standard deviation of those differences, so it is not comparable with a between-groups d. Name the version and its standardizer in the text so a reader or a meta-analyst can tell which one you used.

Should I report t-test results in a table or in the text?

A single comparison reads best as one sentence in the text. When there are many comparisons, put the means, standard deviations, test statistics, intervals and effect sizes in a table and mention only the main findings in the text. Avoid giving the same statistics in both places, as APA's guide advises.

Sources

  1. American Psychological Association (2024). APA Style numbers and statistics guide (7th ed. handout, last updated September 11, 2024). apastyle.apa.org
  2. American Psychological Association. JARS-Quant Table 1: Information recommended for inclusion in manuscripts that report new data collections regardless of research design. apastyle.apa.org
  3. Purdue Online Writing Lab. Numbers and statistics (APA 7th edition). owl.purdue.edu
  4. Appelbaum M, Cooper H, Kline RB, Mayo-Wilson E, Nezu AM, Rao SM (2018). Journal article reporting standards for quantitative research in psychology: the APA Publications and Communications Board task force report. American Psychologist 73(1):3-25. doi:10.1037/amp0000191
  5. 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
  6. Greenland S, Senn SJ, Rothman KJ, Carlin JB, Poole C, Goodman SN, Altman DG (2016). Statistical tests, P values, confidence intervals, and power: a guide to misinterpretations. European Journal of Epidemiology 31(4):337-350. doi:10.1007/s10654-016-0149-3

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