Skip to content

How to calculate a confidence interval for a sample mean in SciPy (with Code)

The Short Answer (TL;DR)

Pass the sample mean and its standard error to scipy.stats.t.interval, using one fewer degree of freedom than the sample size. State the confidence level and sampling assumptions, because the resulting interval describes uncertainty in the population mean.

import numpy as np; from scipy import stats
sample = np.array([4.5, 4.8, 5.1, 4.7, 5.3, 5.0, 4.9, 5.2])
print(stats.t.interval(0.95, df=sample.size-1, loc=sample.mean(), scale=stats.sem(sample, ddof=1, nan_policy="raise")))

Detailed Implementation

This example uses synthetic data and does not need a network connection. Install the recorded package versions in a separate Python environment before running it.

python -m pip install numpy==2.5.4 scipy==1.18.1
from pathlib import Path
import numpy as np
from scipy import stats

# Independent synthetic measurements, all in the same units.
sample = np.array([4.5, 4.8, 5.1, 4.7, 5.3, 5.0, 4.9, 5.2])
confidence = 0.95
if sample.ndim != 1 or sample.size < 2 or not np.isfinite(sample).all():
    raise ValueError("Use at least two finite observations in one dimension.")
if not 0 < confidence < 1 or sample.std(ddof=1) == 0:
    raise ValueError("Use a confidence level between zero and one and nonzero variance.")
standard_error = stats.sem(sample, ddof=1, nan_policy="raise")
lower, upper = stats.t.interval(confidence, df=sample.size-1,
                                loc=sample.mean(), scale=standard_error)
report = (
    f"Sample size: {sample.size}\n"
    f"Sample mean: {sample.mean():.6f}\n"
    f"Standard error: {standard_error:.6f}\n"
    f"Degrees of freedom: {sample.size-1}\n"
    f"{confidence:.0%} CI for population mean: [{lower:.6f}, {upper:.6f}]\n"
)
print(report)
Path("sample-mean-ci-output.txt").write_text(report, encoding="utf-8")

The report uses eight observations and seven degrees of freedom. Its mean is 4.9375 synthetic units, and the 95% interval is symmetric about that mean. The automated checks also confirm that the 99% interval from the same sample is wider.

Why use the standard error rather than the sample standard deviation?

The standard deviation describes the spread of individual measurements. The standard error describes how much the estimated mean varies under the sampling model and equals the sample standard deviation divided by the square root of the sample size. Passing the standard deviation as scale would produce a different, excessively wide interval for the mean.

When is this t interval justified?

For independent, identically distributed normal observations with unknown nonzero variance, the t interval has its stated coverage. For other populations it is an approximation whose quality depends on the sample size, tails and sampling design. Eight observations alone do not justify a normal approximation for arbitrary skewed or contaminated data. Dependence, survey weights or clustered sampling require a suitable standard-error method.

What does 95% confidence mean?

Under the stated model, the procedure covers the fixed population mean in 95% of repeated samples. This does not mean that 95% of individual measurements lie between the limits, nor that a new observation has a 95% chance to fall there. State the confidence level before examining the outcome, and distinguish an interval for a mean from a prediction or reference interval.

Mathematical Context

For n observations, calculate the mean xbar and the sample variance with denominator n minus one. The standard error is the square root of (sample variance divided by n), equivalently the sample standard deviation divided by sqrt(n). For confidence level 1 minus alpha, multiply the standard error by the Student t quantile at probability 1 – alpha/2, with n minus one degrees of freedom, then add and subtract the product from xbar. SciPy supplies this location-and-scale form through stats.t.interval. The example uses ddof=1 explicitly so the variance denominator agrees with the t calculation. Increasing the confidence level increases the interval width for the same data. Replacing the t critical value with a standard normal critical value would ignore the additional uncertainty from estimating variance in a small normal sample.

\[ \bar{x}\;\pm\;t_{1-\alpha/2,n-1}\frac{s}{\sqrt{n}} \]

Reproducibility

Executed with Python 3.12.14; numpy 2.5.4, scipy 1.18.1. Automated checks confirm the stated output properties.

Primary documentation

Related guides