statsmodels: Diagnostics, Time Series & Experiment Planning
Assumption-Checking Diagnostics
import statsmodels.stats.api as sms
from statsmodels.stats.outliers_influence import variance_inflation_factor
# Heteroscedasticity: is residual variance roughly constant?
bp_test = sms.het_breuschpagan(results.resid, results.model.exog)
# Fix WITHOUT respecifying the model -- corrects standard errors/
# p-values, doesn't change the coefficient estimates themselves
results_robust = model.fit(cov_type='HC3')
# Normality of residuals (visual check)
sm.qqplot(results.resid, line='45')
# Multicollinearity: are predictors too correlated with EACH OTHER?
vif = [variance_inflation_factor(X.values, i) for i in range(X.shape[1])]
# results.summary() also reports Durbin-Watson by default --
# near 2 = no significant residual autocorrelationTime Series: ARIMA & ACF/PACF
import statsmodels.api as sm
# ACF/PACF: how correlated is the series with its own past values?
# Used to help choose AR/MA order before fitting ARIMA
sm.graphics.tsa.plot_acf(data)
sm.graphics.tsa.plot_pacf(data)
# order=(p, d, q): AR order, differencing order, MA order
model = sm.tsa.ARIMA(data, order=(1, 1, 1))
results = model.fit()
forecast = results.forecast(steps=12)ANOVA: Comparing 3+ Groups
import statsmodels.api as sm
import statsmodels.formula.api as smf
# Are conversion rates significantly different across 3+ campaign variants?
model = smf.ols('conversion_rate ~ C(campaign_variant)', data=df).fit()
anova_table = sm.stats.anova_lm(model)Power Analysis: Planning an Experiment
from statsmodels.stats.power import TTestPower
# BEFORE running an A/B test: what sample size do we need to
# reliably detect an effect of this size, at this significance/power?
analysis = TTestPower()
required_n = analysis.solve_power(effect_size=0.5, alpha=0.05, power=0.8)
# Avoids running an underpowered study that couldn't reliably
# detect a real effect even if one truly exists.Keep your own version of these notes — editable, searchable, and organised by your stack.
Start free