Celeus

P-values and confidence intervals: report both

What a p value and a confidence interval each tell you, how they relate, how to read p = 0.06, and how to report both, with a worked example in R.

Updated . Written by Matt Gencer.

On this page

A p-value and a confidence interval come out of the same calculation, but they answer different questions. The p-value tells you how well the data sit with one particular hypothesis, usually that there is no effect. The confidence interval tells you which sizes of effect the data are compatible with. A result is only fully reported when both are there, next to the estimate they describe.

This guide explains what each quantity is and is not, shows how they are tied together, and then reads one real result both ways: a comparison of two groups that gave p = 0.0606 and a 95% interval that runs from just below zero to well above the estimate. The last sections cover how to report both, the misreadings that do the most damage, and what to do when you are tempted to call a result “almost significant”.

What a p-value is

Every significance test starts from a statistical model: a description of how the data would behave if some hypothesis were true and if every assumption behind the test held. For a two-group comparison the hypothesis is usually that the two population means are equal, and the assumptions include independent observations, a sampling scheme that the analysis matches, and a roughly normal sampling distribution for the difference in means.

The test then measures how far the observed data are from what that model predicts, using a test statistic such as t. The p-value is the probability, under the model, of getting a test statistic at least as far from the prediction as the one you observed.

So a small p-value says: if the model were exactly right, data this far from its prediction would be unusual. A large one says that data like these would be unremarkable under the model. That is all it says.

Two features of this definition cause most of the trouble.

The p-value is computed assuming the hypothesis is true. It cannot then be the probability that the hypothesis is true. Those are different quantities, and the second one cannot be computed from a significance test at all.

The p-value is about the whole model, not only the hypothesis. Greenland and colleagues stress that a p-value measures the compatibility between the data and the entire model used to compute it, including every assumption. A small p-value can come from a false null hypothesis, but also from a violated assumption, a selected analysis or a data error. The test cannot tell you which.

The ASA’s six principles

In 2016 the American Statistical Association’s board issued a statement on p-values, published by Wasserstein and Lazar in The American Statistician. In announcing it, the ASA’s president described it as the first time the ASA Board of Directors had issued a statement on these issues. Its six principles are a useful checklist for reading any p-value:

  1. P-values can indicate how incompatible the data are with a specified statistical model.
  2. P-values do not measure the probability that the studied hypothesis is true, or the probability that the data were produced by random chance alone.
  3. Scientific conclusions and business or policy decisions should not be based only on whether a p-value passes a specific threshold.
  4. Proper inference requires full reporting and transparency.
  5. A p-value, or statistical significance, does not measure the size of an effect or the importance of a result.
  6. By itself, a p-value does not provide a good measure of evidence regarding a model or hypothesis.

The first principle says what a p-value can do. The other five say what it cannot do, and principle 5 is the one that makes a confidence interval necessary: if the p-value does not measure the size of an effect, something else in the report has to (writing the interval’s conclusion shows how).

How a p-value is found

Software does the arithmetic, but it helps to see what it does. For a t-test, the observed difference is divided by its standard error to give t. Under the model, t follows a t distribution with a known number of degrees of freedom. The two-sided p-value is the area in both tails of that distribution beyond the observed t, the share of the distribution at least as far from zero as your result.

In R, t.test() prints the p-value directly, on one line with t and its degrees of freedom, with the 95 percent confidence interval just below it. The same number can be computed by hand from t and its degrees of freedom:

# Two-sided p-value from a t statistic and its degrees of freedom
two_sided_p <- function(t, df) 2 * pt(-abs(t), df)

An older route, the critical-value approach, reaches the same verdict without a tail area: look up the t value that cuts off the outer 5%, split between both tails, at the test’s degrees of freedom, and check whether the observed t lies beyond it. The two routes always agree on significance; the p-value also shows how far past, or short of, that line the result fell, which is why software reports it.

One-sided p-values use only one tail: the right tail when the hypothesis predicts an increase, the left when it predicts a decrease. A one-sided test is defensible only if the direction was written down before anyone saw the data, and a result in the opposite direction would have been handled the same way as a null result. Choosing a one-sided test after looking at the data halves the p-value for no reason.

Statistical significance is a label, not a finding

A significance level, usually written alpha and usually set at 0.05, is a cut-off chosen in advance, as part of the design. When p falls at or below it, the result is called statistically significant.

Greenland and colleagues draw the distinction sharply: alpha is fixed before the data exist, while the p-value is a result computed from them. Statistical significance is a description of the p-value relative to that cut-off. It is a property of a test result, not of the effect or the population being studied. Two studies of the same real effect can land on opposite sides of 0.05 by chance alone.

What a confidence interval is

A confidence interval is a range of values for the quantity you are estimating, here a difference in means, built from the estimate, its standard error and the same reference distribution the test uses.

The “95%” is a property of the procedure, not of any one interval. If you computed 95% intervals in very many valid studies, about 95% of those intervals would contain the true value. Any single interval, once computed, either contains the true value or it does not. Greenland and colleagues list “the specific 95% confidence interval presented by a study has a 95% chance of containing the true effect size” among their 25 common misinterpretations for exactly that reason.

There is a second reading that is often more useful in practice. Imagine running the same test, with the same assumptions, against not only “the difference is zero” but every possible difference: one unit, two units, minus one, and so on. Each run gives its own p-value. The difference with p = 1 is the estimate itself, the value most compatible with the data under the model. The values whose two-sided test gives p above 0.05 form a range, and that range is the 95% confidence interval. This is the reading Greenland and colleagues describe when they move “from tests to estimates”: the interval summarises the results of hypothesis tests for many effect sizes at once.

That gives the interval a plain-language meaning. The values inside a 95% interval are the effect sizes the data are reasonably compatible with, given the model. Values outside it are less compatible. Less compatible is not ruled out: the interval is computed from the same assumptions as the p-value, and Greenland and colleagues warn that an effect size outside the interval has not been “refuted” by the data.

How the two are tied together

When the interval and the test come from the same method, they share the estimate, the standard error and the reference distribution, and then they always agree on one thing. For a Welch comparison, that means the Welch interval read against the Welch test:

  • A 95% interval excludes zero exactly when the two-sided p-value for “no difference” is below 0.05.
  • A 95% interval includes zero exactly when that p-value is 0.05 or above.
  • The edges of the 95% interval are the values whose own two-sided p-value is exactly 0.05.

The condition matters. Pair a Welch p-value with an interval built on the equal-variance (Student) formula, or a test and an interval that use different standard errors, and the two can disagree for results near the boundary. In R, t.test() returns the interval and the p-value from one method, Welch’s by default, so they match.

So if you have an interval from the same method as the test, you already know whether p is above or below 0.05. What the interval adds is everything else: where the estimate sits, how wide the range of compatible values is, and whether values large enough to matter in your field are inside it or not. The p-value adds one thing the interval does not show directly: an exact measure of how the data sit against the null value specifically, rather than only whether it is inside or outside one fixed range.

That asymmetry is the case for reporting both, with the interval doing most of the work. The ASA statement makes the same point from the other side: among the approaches it says statisticians use to supplement or even replace p-values, the first it names are methods that emphasise estimation over testing, with confidence intervals at the head of the list.

Worked example: one comparison read both ways

The data are ToothGrowth, a dataset that comes with R and records Crampton’s 1947 guinea pig experiment on vitamin C. Every one of the 60 animals got vitamin C at one of three doses, delivered either as orange juice (OJ) or as ascorbic acid (VC). What was measured is the length of the odontoblasts, the cells that build tooth, which this guide calls “length” from here on. There is one measurement per animal and 30 different animals per delivery method, so the groups are independent and the design is two-sample.

Here the question is whether mean length differs by delivery method. The method is Welch’s two-sample t-test: it compares two independent means and does not require the groups to have equal variances. Welch published it in 1947, and t.test() in R uses it unless told otherwise. Seeded and run in R; the test was chosen before the run. Its output and the generated R script are shown under the article.

This is the same comparison the t-tests explained guide works through in detail, including its assumption checks. Here the focus is narrower: what the p-value and the interval each say about one result, and how to write both down.

The result

Engine output Value
Sample size 60 animals, 30 in each group
OJ group mean length 20.66
VC group mean length 16.96
Estimated difference (OJ - VC) 3.70
95% interval for that difference -0.171 to 7.571
Test statistic t = 1.915, df = 55.31 (Welch)
Two-sided p-value 0.0606
Cohen’s d (95% interval) 0.4945 (-0.02151 to 1.006)

Reading the p-value alone

Taken alone, the result is p = 0.0606. This is a statement about the null model, not about the null hypothesis being true: suppose the two delivery methods gave the same mean length and every assumption of the test held. Then, in repeated experiments of this size, about 6% would produce a t at least as far from zero as 1.915 on 55.31 degrees of freedom. That figure is the two tails of the t distribution beyond 1.915, added together. It is computed by assuming the null model, so it cannot also be the probability that the null model is right.

At the conventional 0.05 cut-off the result is not statistically significant. That is the whole of what a significance verdict can say, and a report that stops here loses most of the information in the data. It does not say how big the difference was, which direction it went, or whether the study could have told a small effect from no effect.

It also does not say that the delivery methods are equivalent, and it does not give a 94% chance that they differ. Both readings are common, and both are wrong for the reasons in the ASA’s second principle.

Reading the interval

The estimated difference is 3.70 units in favour of orange juice, with a 95% interval from -0.171 to 7.571. In words: the data are compatible with orange juice giving anything from a fraction of a unit less length to about 7.6 units more, with the estimate in the middle.

Three things are visible here that the p-value hid.

Direction. Almost all of the interval lies above zero. The data point towards a higher mean with orange juice, and only a sliver of the compatible range is on the other side.

Size. The estimate is 3.70 units. Whether that matters is a question about tooth growth in this experiment, not about statistics, and the interval puts the question in the right units.

Precision. The interval is roughly twice as wide as the estimate itself. The upper end is about twice the estimate, and the lower end is just below zero. With 30 animals per group, this experiment pins the difference down only loosely.

And because the interval and the p-value both come from the Welch method, they agree exactly. The interval includes zero, so the two-sided p for “no difference” is above 0.05. The lower edge sits only just below zero, so the p-value sits only just above 0.05. Tested against the exact upper edge of the interval, the Welch two-sided p-value would be exactly 0.05. The 7.571 in the table is that edge rounded to three decimals, so a test against 7.571 gives a p-value of about 0.05 rather than exactly 0.05. Tested against 3.70, the estimate, the p-value is 1.

You can see this for yourself in R. The mu argument sets the hypothesised difference the test is run against:

# The same Welch test, run against different hypothesised differences (OJ minus VC).
# Against the estimate, p is 1; against an edge of the 95% interval, p is about 0.05
# (7.571 is the edge rounded to three decimals, so p is close to, not exactly, 0.05).
t.test(len ~ supp, data = ToothGrowth, mu = 0)      # the usual test of no difference
t.test(len ~ supp, data = ToothGrowth, mu = 7.571)  # the upper edge of the interval, rounded
t.test(len ~ supp, data = ToothGrowth, mu = 3.7)    # the estimate itself

# A 90% interval is narrower and corresponds to the 0.10 level instead of 0.05.
t.test(len ~ supp, data = ToothGrowth, conf.level = 0.90)$conf.int

Reading the effect size

The engine also reports Cohen’s d, the difference expressed in standard deviation units: 0.4945, with a 95% interval from -0.02151 to 1.006. The standard deviation here is the pooled one. Because both groups have 30 animals, pooling amounts to taking the mean of the two variances, and the d of 0.4945 itself needs no equal-variance assumption. The interval around it is a different matter: the usual formula for a d interval assumes the two variances are equal, which makes this one an approximation. For the different versions of d used with t-tests, and when each fits, see Lakens’ 2013 primer.

The d interval tells the same story on a standard scale: compatible with no effect at one end and with an effect of about one standard deviation at the other. That scale is what lets a reader compare this result with studies that measured something else, and it is the scale a sample size calculation uses.

What a sensitivity figure adds

A non-significant result invites the question: could this study have detected an effect worth caring about? The engine’s answer is a sensitivity analysis, which depends only on the design. It does not compute “observed power” from the result, a number that is a restatement of the p-value and adds no information.

The sensitivity figure: for a two-sided test at the 0.05 level with 30 animals in each group, 80% power is reached only when the true effect is d = 0.74 or more. Getting the same 80% power for d = 0.50, the conventional “medium” effect, takes 64 animals in each group. The estimate this study produced, d = 0.49, is well under 0.74, so an effect of that size was never one this design could expect to detect reliably. Anyone planning a follow-up should size it for the smallest effect that matters in their field; this estimate, with an interval this wide, is no basis for a sample size.

The honest summary

Put together, the correct conclusion is: orange juice was estimated to give 3.70 units more length, the data are compatible with anything from essentially no difference to a difference about twice that size, and the experiment was not large enough to tell those apart. That is an inconclusive result, and it is a more informative one than “not significant”.

What this example leaves out

Two caveats belong with any reading of this comparison. First, the engine’s normality check by group flagged the orange juice group (Shapiro-Wilk W = 0.918, p = 0.0236), with no departure detected in the ascorbic acid group (W = 0.966, p = 0.428), and Levene’s test did not detect unequal variances (p = 0.275), which is not evidence that they are equal. Because one group was flagged, the engine suggested a rank-based alternative. With 30 animals per group and a question about means, Welch’s test remains a reasonable choice here; the t-tests guide walks through that reasoning, and the t-test or Mann-Whitney guide covers what changes if you compare ranks instead.

Second, the experiment crossed two factors, delivery method and dose. Pooling over the three doses, as this comparison does, answers a marginal question: how delivery methods differ on average across the doses used. A design like this one is properly analysed with a two-way ANOVA of delivery method, dose and their interaction, which the two-way ANOVA guide covers. Here the comparison serves to show how a p-value and an interval are read; it is not what a researcher should report as the analysis of this experiment.

How to interpret p = 0.06

The worked example landed at p = 0.0606, which is exactly where readers and authors most often go wrong. A few rules settle it.

It is not a different kind of result from p = 0.05. The p-value is a continuous measure. Values just above and just below 0.05 reflect almost the same compatibility between the data and the model. Treating one as a discovery and the other as nothing is the threshold thinking the ASA’s third principle warns against.

Do not call it a trend, a tendency or “marginally significant”. Those phrases try to claim a significant result after the fact without the evidence for one. If the cut-off was 0.05, the result did not meet it. Say so, and then say what the estimate and interval show.

Do not conclude there is no effect. Greenland and colleagues list “a nonsignificant test result (P > 0.05) means that the test hypothesis is true or should be accepted” as a misinterpretation. In the worked example the interval reaches up to 7.571 units, about twice the estimate. “No effect” is one value among many that remain compatible with the data.

Report the exact value. Write p = 0.061, not “p > 0.05” or “n.s.”. Greenland and colleagues call reporting p-values as inequalities bad practice because it hides what the reader needs; an inequality is justifiable only for very small values, such as p < 0.001.

Let the interval carry the conclusion. The useful sentence about a p = 0.06 result is almost always about the interval: which effects are still compatible with the data, and whether the study could have distinguished them.

Do not rescue it. Adding a few more observations, dropping an outlier, switching to a one-sided test or trying another method until p falls below 0.05 turns the p-value into a measure of how hard someone searched. If more data are genuinely needed, plan a new study for a meaningful effect and analyse it as planned.

How to report a p-value and a confidence interval together

Order the result statement so the reader meets the answer first: the estimate, then its confidence interval, then the test statistic and its degrees of freedom, then the exact p-value, and finally an effect size with its own interval. Leave the name of the test, the cut-off and the assumption checks to the methods section.

Written up that way, the worked example becomes:

With 30 animals per group, orange juice gave a mean odontoblast length of 20.66 against 16.96 for ascorbic acid, a difference of 3.70 (95% CI -0.17 to 7.57; Welch’s t(55.31) = 1.92, p = 0.061; Cohen’s d using the pooled SD = 0.49, 95% CI -0.02 to 1.01). Both no difference and a difference about twice the estimate are compatible with these data, so at this sample size the comparison is inconclusive.

Points to get right:

  • Lead with the estimate and its interval. They are the answer to the research question. The p-value supports them.
  • Match the interval to the test. With a 0.05 cut-off, report 95% intervals, and compute them by the same method as the test (a Welch interval with a Welch test), so the two agree.
  • Give the exact p-value, to two or three decimals. Reserve the inequality “p < 0.001” for values below that.
  • Give the test statistic and its degrees of freedom. For Welch’s test the degrees of freedom are not a whole number; keep the decimals so the reader can see which test was used.
  • Report an effect size with its interval, and say which standard deviation it uses.
  • Say what the interval means in words when the result is inconclusive, so no reader turns “not significant” into “no difference”.

Write an interval as lower then upper, in the units of the estimate, and follow the target journal’s style for decimals and leading zeros.

Statistical significance and practical importance

A p-value mixes two things: the size of the effect and the amount of data. A small effect measured in a very large sample can give a tiny p-value; a large effect measured in a small sample can give a p-value well above 0.05. That is why the ASA’s fifth principle says a p-value does not measure the size of an effect or the importance of a result, and why Greenland and colleagues reject “statistical significance indicates a scientifically or substantively important relation has been detected”.

The confidence interval separates the two. Its centre shows the size of the effect; its width shows how much data there was. To judge practical importance, decide before the analysis what size of effect would matter in your field, then look at where the interval sits relative to that value:

  • Interval entirely above the smallest important effect: the effect is both detectable and large enough to matter.
  • Interval excludes zero but sits entirely below the smallest important effect: the data point to an effect that is not zero but is smaller than anything that would matter. This is the typical large-sample result.
  • Interval includes zero and also includes important effects: inconclusive. The worked example is this case.
  • Interval includes zero and excludes all important effects: the data are compatible only with effects too small to matter. This is the closest a conventional analysis comes to showing “no meaningful effect”, and a formal equivalence test makes it precise.

None of these readings is available from the p-value alone.

Common misreadings, and what to say instead

Greenland and colleagues catalogue 25 misinterpretations of p-values, confidence intervals and power. These are the ones that turn up most in research reports; each comes with a correct alternative.

“The p-value is the probability that the null hypothesis is true.” The calculation starts by taking the null hypothesis as given, so it cannot return the probability of that hypothesis. Say instead: “If there were no difference and the model held, data at least this extreme would occur with probability p.”

“p = 0.0606 means a 6% chance the result is due to chance.” The ASA’s second principle rejects this directly. The p-value is not the probability that chance alone produced the data.

“Not significant, so there is no difference.” Say instead what the interval allows. In the worked example: “compatible with no difference and with a difference of about twice the estimate”.

“Significant, so the effect is important.” Significance depends on sample size. Look at the interval against the smallest effect that would matter.

“The 95% interval has a 95% chance of containing the true value.” The 95% describes the procedure over many studies. Say instead: “the values compatible with the data at the 95% level”.

“Values outside the interval have been ruled out.” They are less compatible with the data under the model. The model’s assumptions could be wrong, and 95% is itself a convention.

“The two groups’ intervals overlap, so they do not differ.” Greenland and colleagues give an example in which two 95% intervals overlap yet the test of the difference between them gives p below 0.05. To compare two estimates, compute the interval for their difference directly.

“One study was significant and the other was not, so they disagree.” Two results on opposite sides of 0.05 can be entirely consistent with each other. Compare their estimates and intervals, or test the difference between them.

“This study proves the effect”, or “we accept the null hypothesis”. All a test can report is how compatible the data are with one hypothesis, judged at a level someone chose. A small p does not prove the effect, and a large one does not prove its absence.

Many tests, selected results

Everything above assumes one test, planned in advance and reported whatever its result. When a study runs many tests, the meaning of each p-value changes.

When a null hypothesis and every assumption hold, the p-value of a test with a continuous statistic is equally likely to land anywhere between 0 and 1 (very nearly so for approximate tests such as Welch’s). So at a 0.05 cut-off each such test has a 5% chance of a significant result: a false positive, or type I error. Run enough of them and some significant results are expected even if nothing is going on. Comparing every pair of groups, testing many outcomes, or analysing many subgroups all raise the chance of at least one false positive across the study.

Selection makes this worse and is harder to see. Greenland and colleagues stress that choosing which analyses to present based on the p-values they produce can lead to small p-values even when the hypothesis being tested is true. The selection does not have to be deliberate. Trying a second outcome definition, a different covariate set, or a subgroup that “looked interesting” all count.

Three habits keep p-values meaningful:

  • Plan the primary analysis before seeing the data, and say in the report which analyses were planned and which were exploratory.
  • Adjust for multiple comparisons when several tests address one question, for example pairwise comparisons after an analysis of several groups. For the available corrections and how to choose between them, see the multiple comparisons guide.
  • Report every test you ran. A reader can only interpret one p-value when they know how many others were computed alongside it.

Confidence intervals are not immune: an interval chosen from many is subject to the same selection. The fix is the same, planning and complete reporting, which is why the ASA puts transparency among its six principles.

When a p-value is the wrong summary

A p-value answers a narrow question: how compatible are the data with one specific hypothesis, usually zero effect? Some research questions are not of that shape.

  • “How big is the effect?” This is an estimation question. Report the estimate and its interval; a p-value adds little.
  • “Are the two methods equivalent?” A non-significant difference cannot show equivalence. An equivalence test, which tests whether the effect lies inside a margin set in advance, answers it directly.
  • “How should I update my belief?” A p-value is not a probability that a hypothesis is true. Bayesian methods, which the ASA statement lists among the alternatives, address that question with explicit prior assumptions.
  • “Which of several models fits best?” Model comparison tools answer this better than a series of significance tests.

Whatever the method, the choice of test still starts from the design and the outcome. That decision is the subject of the guide to choosing a statistical test, and the reference page for Welch’s t-test shows what the engine reports for the method used in the worked example.

Rerunning the example

Under the article sit two things: the R script the engine generated for this run, unedited, carrying its seed and the path to its bundled data, and the output the run printed. The script expects its data in a data/ folder next to it. Run on the same package versions, it recomputes the Welch test (the estimate, the 95% interval, t, the degrees of freedom and the p-value) and the sensitivity figure.

The script does not recompute the effect size or the assumption checks; those numbers are the engine’s own. To reproduce them in R, use effectsize::cohens_d(len ~ supp, data = data) for d, car::leveneTest(len ~ factor(supp), data = data) for Levene’s test, and shapiro.test() on each group separately. The extra t.test() calls in the worked example’s code block are not part of the engine run; they are there for you to try in R. What a reviewer needs before they can rerun a result like this one is the subject of the guide to reproducible statistical analysis.

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: 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: 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: 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(20261021)
.data_path <- "data/p-values-and-confidence-intervals.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

What is a p-value?

A p-value is the probability, computed under a stated statistical model that includes the null hypothesis, of getting a test statistic at least as far from what that model predicts as the one observed. Small values mean the data sit poorly with the whole model; they do not give the probability that the null hypothesis is true.

How do I find a p-value?

Software computes it from the test statistic and its reference distribution. For a two-sided t-test it is twice the tail area of the t distribution beyond the observed t, at the test's degrees of freedom. In R, t.test() prints it, and 2 * pt(-abs(t), df) gives the same number by hand.

What is the difference between a confidence interval and a p-value?

A p-value tests one hypothesis, usually zero effect, and returns one number. A confidence interval lists every effect size the data are reasonably compatible with under the model, so it shows the size, direction and precision of the effect. They share the same ingredients, and when both come from the same method (a Welch interval with Welch's test, for example), a 95% interval excludes zero exactly when the two-sided p is below 0.05.

How do I interpret p = 0.06?

As weak evidence against the null hypothesis, nearly the same as p = 0.05 and not a different kind of result. Do not call it a trend or a near miss, and do not conclude there is no effect. Report the exact value with the estimate and its confidence interval, and say what range of effects the data still allow.

Is a p-value of 0.05 significant, and why 0.05?

By the usual convention a result is called significant when p is at or below the cut-off chosen in advance, so p = 0.05 counts at a 0.05 level. Nothing in the mathematics makes 0.05 special; it is a convention. Choose the level before the analysis, report the exact p-value, and do not treat 0.049 and 0.051 as different kinds of result.

What does a p-value of 0.001 mean?

If the model, including the null hypothesis, were right, a result at least this extreme would occur about once in a thousand repetitions, so the data sit very poorly with that model. It says nothing about how large the effect is: a trivial effect in a big sample can produce it. Report it exactly, as p = 0.001 (values below that are written p < 0.001), alongside the estimate and its confidence interval.

Should I report the p-value or the confidence interval?

Report both, with the estimate and an effect size. The interval carries the size and precision of the result, which is what readers need to judge practical importance; the exact p-value tells them how the data sit against the null hypothesis. Neither alone is a complete result, and the p-value alone is the weaker of the two.

Sources

  1. Wasserstein RL, Lazar NA (2016). The ASA statement on p-values: context, process, and purpose. The American Statistician 70(2):129-133. doi:10.1080/00031305.2016.1154108
  2. American Statistical Association (2016). American Statistical Association releases statement on statistical significance and p-values. Press release, 7 March 2016. amstat.org
  3. 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
  4. Welch BL (1947). The generalization of 'Student's' problem when several different population variances are involved. Biometrika 34(1-2):28-35. doi:10.1093/biomet/34.1-2.28
  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

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