39 — Python Power Tools

scipy.stats & statsmodels#

PythonPractice 1 min read
◆ The PatternStatistical tests, regression diagnostics, time series — the Python stats foundation

scipy.stats has every distribution and statistical test. statsmodels adds regression diagnostics, time series models (ARIMA, ADF), and proper statistical inference with confidence intervals — what sklearn deliberately leaves out.

// scipy.stats + statsmodels workflow
Taskscipy.statsstatsmodels
Compare two groupsttest_ind, mannwhitneyu—
Normalityshapiro, normaltest—
Regression—OLS with summary()
Time series—ARIMA, adfuller, acf
Distributionsnorm, beta, gamma, etc.—
sklearn vs statsmodels: sklearn is for prediction (fit/predict). statsmodels is for inference (coefficients, p-values, diagnostics). Use both — they complement each other.
Pattern bridge: statsmodels fits the ARIMA and GARCH models used across the Timeseries collection, so the diagnostics here are the ones you run on every forecast model there.
Worked example

Ten p-values, eight of them below 0.05. Bonferroni keeps 2 as significant; the Benjamini–Hochberg procedure keeps 6, controlling the expected share of false discoveries instead of the chance of any. statsmodels’ multipletests does both; which one is right depends on whether a single false positive is costly or a few are acceptable.

Where it misleads
  • Corrections apply to the family of tests you actually ran, including the ones you did not report.
  • Benjamini–Hochberg assumes independent or positively dependent tests; under other dependence use Benjamini–Yekutieli.
  • A non-significant result after correction is not evidence of no effect.
In code
p = np.array([0.001, 0.004, 0.008, 0.012, 0.02, 0.03, 0.04, 0.045, 0.2, 0.5])
m = len(p)
bonferroni = (p < 0.05 / m).sum()
order = np.sort(p)
passed = order <= 0.05 * np.arange(1, m + 1) / m    # Benjamini-Hochberg step-up
bh = (np.max(np.nonzero(passed)) + 1) if passed.any() else 0
Python, in your browser — edit the code and run it again

Assumes import numpy as np and import pandas as pd (and SciPy where imported). Each snippet simulates or makes up its own data, as the comments say.

The same idea with a library
# scipy.stats — statistical tests
from scipy.stats import (
    ttest_ind, ttest_rel, mannwhitneyu,
    ks_2samp, shapiro, spearmanr
)

# Two-sample t-test
t_stat, p_val = ttest_ind(group_a, group_b)

# Normality check
stat, p = shapiro(data)

# statsmodels — regression with full diagnostics
import statsmodels.api as sm

X_sm = sm.add_constant(X)
model = sm.OLS(y, X_sm).fit()
print(model.summary())  # R², coefficients, p-values, CI

# Time series — ADF stationarity test
from statsmodels.tsa.stattools import adfuller
result = adfuller(series)
print(f"ADF Stat: {result[0]:.3f}, p: {result[1]:.4f}")
Sources
  • Y. Benjamini & Y. Hochberg, “Controlling the False Discovery Rate: A Practical and Powerful Approach to Multiple Testing”, Journal of the Royal Statistical Society B 57(1), 1995
  • S. Holm, “A Simple Sequentially Rejective Multiple Test Procedure”, Scandinavian Journal of Statistics 6(2), 1979
  • S. Seabold & J. Perktold, “Statsmodels: Econometric and Statistical Modeling with Python”, Proceedings of the 9th Python in Science Conference, 2010
  • P. Virtanen et al., “SciPy 1.0: Fundamental Algorithms for Scientific Computing in Python”, Nature Methods 17, 2020

Last reviewed October 2026 · How this site checks its content · Report a mistake

Linked from 1
← Previous
pandas-ta & yfinance
Open in the full reader, with the topic sidebar