Unit 02.04: statsmodels picks the reference alphabetically
statsmodels picks your reference category alphabetically. It has no idea which group is the baseline.
Every coefficient is a comparison against the reference
When a categorical variable enters a formula, statsmodels codes it against a reference level and reports every other level as a difference from it. Which level is the reference therefore determines what each coefficient means.
The default is alphabetically first, which is arbitrary and frequently wrong: economy sorts before standard, so a model of delivery plans silently compares everything against the cheapest option.
C(plan, Treatment(reference='standard')) sets it explicitly. The fit does not change at all — the same predictions, the same R-squared — only which comparisons are reported.
This block fits the same model with two different references.
import numpy as np, pandas as pd
import statsmodels.formula.api as smf
rng = np.random.default_rng(3)
d = pd.DataFrame({
"plan": np.repeat(["standard", "express", "economy"], 40),
"minutes": np.concatenate([rng.normal(35, 5, 40),
rng.normal(28, 5, 40),
rng.normal(44, 5, 40)]),
})
default = smf.ols("minutes ~ C(plan)", data=d).fit()
print("Default reference (first alphabetically):")
print(default.params.round(3).to_string())
print(" -> every coefficient is a comparison against 'economy'\n")
chosen = smf.ols("minutes ~ C(plan, Treatment(reference='standard'))",
data=d).fit()
print("Reference set to 'standard', the operational baseline:")
print(chosen.params.round(3).to_string())
print()
print(f"Same fit both times -- R-squared {default.rsquared:.5f} and"
f" {chosen.rsquared:.5f}")
print("Only the comparisons changed, and only the second set answers the")
print("question the operations team actually asked.")
The default reference is economy, alphabetically first, so express reads −17.211 and standard −9.671 — comparisons against the slowest plan, which nobody asked for. Set to standard, the same model reports economy at +9.671 and express at −7.540, which are the operational questions. R-squared is 0.62977 both times: the fit is identical and only the reporting changed.
The mistake this prevents
The mistake is interpreting coefficients without checking the reference. The signs come out backwards, the sentence gets written anyway, and nothing in the output looks wrong.
Takeaway
Set the reference explicitly with C(var, Treatment(reference=...)) and state it in the table caption. Every coefficient is meaningless without it.
