SciPy standard error: scipy.stats.sem, ddof, NaN and regression (tested)

scipy.stats.sem(x) returns the standard error of the mean, x.std(ddof=1) / sqrt(n). If your own number is smaller, you used np.std, which defaults to ddof=0. Below: NaN, axis, confidence intervals, and standard errors of regression coefficients, all measured.

1. scipy.stats.sem: ddof, NaN, axis

b1.py compares scipy.stats.sem with the manual formula and shows the three things that change its result:

import numpy as np
from scipy import stats

x = np.array([4.1, 5.0, 3.8, 6.2, 5.5, 4.9])
print("stats.sem(x)            ", stats.sem(x))
print("std(ddof=1)/sqrt(n)     ", x.std(ddof=1) / np.sqrt(len(x)))
print("np.std(x)/sqrt(n)       ", np.std(x) / np.sqrt(len(x)), "<- ddof=0, smaller")
print("stats.sem(x, ddof=0)    ", stats.sem(x, ddof=0))

y = np.array([4.1, np.nan, 3.8])
print("sem with NaN            ", stats.sem(y))
print("nan_policy='omit'       ", stats.sem(y, nan_policy="omit"))

m = np.array([[1.0, 2.0, 3.0], [2.0, 4.0, 9.0]])
print("2-D default axis=0      ", stats.sem(m))
print("axis=1                  ", stats.sem(m, axis=1))
print("axis=None               ", stats.sem(m, axis=None))
print("one value               ", stats.sem([5.0]))

Output (SciPy 1.18.1, NumPy 2.5.4, Python 3.13.5):

stats.sem(x)             0.36094013046179535
std(ddof=1)/sqrt(n)      0.36094013046179535
np.std(x)/sqrt(n)        0.3294917522713047 <- ddof=0, smaller
stats.sem(x, ddof=0)     0.3294917522713047
sem with NaN             nan
nan_policy='omit'        0.1499999999999999
2-D default axis=0       [0.5 1.  3. ]
axis=1                   [0.57735027 2.081666  ]
axis=None                1.1761519176251567
/tmp/se408/b1.py:18: SmallSampleWarning: One or more sample arguments is too small; all returned values will be NaN. See documentation for sample size requirements.
  print("one value               ", stats.sem([5.0]))
one value                nan

2. pandas .sem(), a 95% confidence interval, and regression standard errors

import numpy as np, pandas as pd
from scipy import stats
from scipy.optimize import curve_fit

x = np.array([4.1, 5.0, 3.8, 6.2, 5.5, 4.9])
print("pandas Series.sem()     ", pd.Series(x).sem())
print("pandas with NaN         ", pd.Series([4.1, np.nan, 3.8]).sem(), "<- skips NaN")

# 95% confidence interval for the mean from the SEM
lo, hi = stats.t.interval(0.95, df=len(x) - 1, loc=x.mean(), scale=stats.sem(x))
print("mean, 95% CI            ", round(x.mean(), 3), (float(round(lo, 3)), float(round(hi, 3))))

# standard error of a regression slope and intercept
t = np.array([0, 1, 2, 3, 4, 5.0])
y = np.array([1.1, 2.9, 5.2, 7.1, 8.8, 11.2])
res = stats.linregress(t, y)
print("linregress slope, stderr", round(res.slope, 4), round(res.stderr, 4))
print("intercept, stderr       ", round(res.intercept, 4), round(res.intercept_stderr, 4))

# standard errors of curve_fit parameters
popt, pcov = curve_fit(lambda t, a, b: a * t + b, t, y)
print("curve_fit perr          ", np.round(np.sqrt(np.diag(pcov)), 4))

Output:

pandas Series.sem()      0.36094013046179535
pandas with NaN          0.1499999999999999 <- skips NaN
mean, 95% CI             4.917 (3.989, 5.844)
linregress slope, stderr 2.0029 0.0439
intercept, stderr        1.0429 0.1329
curve_fit perr           [0.0439 0.1329]

To plot these as error bars: matplotlib errorbar, seaborn errorbar="se", plotly error_y. Related: scipy minimize errors.

Frequently asked questions

How do I calculate standard error in SciPy?

scipy.stats.sem(x); it equals x.std(ddof=1) / sqrt(len(x)).

Why does np.std / sqrt(n) differ from scipy.stats.sem?

np.std uses ddof=0 by default while scipy.stats.sem uses ddof=1; pass ddof=1 to np.std or ddof=0 to sem to make them match.

How do I get the standard error of a regression slope in SciPy?

scipy.stats.linregress returns it as result.stderr, and the intercept's as result.intercept_stderr.

Written with AI assistance. Measured on 2026-10-23 with SciPy 1.18.1, NumPy 2.5.4, pandas 3.1.0 and Python 3.13.5 on Linux. Scripts ran verbatim and the output was pasted unedited. PlainTables is our extension; SciPy is free.