Multinomial Logistic Regression
The engine for Multi-Category Discovery. Multinomial Logistic Regression audits the likelihood of membership in three or more unordered groups, revealing the predictors that drive categorical choice.
What is it?
Multinomial Logistic Regression models the probability of nominal multi-category outcomes (e.g. choice of Car, Bus, or Train) relative to a baseline reference category.
When to use it
- Nominal Outcomes: Categorical choices containing no inherent ordinal sequence.
- Multiple Probabilities: Fit probability curves summing to 1.0 across all classes.
Multinomial Choice Live Laboratory
Adjust preference slopes for Choice A and Choice B (relative to Baseline Choice C) to see probability curve dynamics.
Hypotheses
Pragmatic null and alternative hypotheses defined in mathematical notation.
H₀: β₁ = 0 (predictor has no effect on log-odds of outcome category)
Hₐ: β₁ ≠ 0 (predictor affects log-odds)
For each predictor and outcome category pair (relative to reference category). Overall model test: likelihood ratio test compares fitted model to intercept-only model. Coefficients are log-odds of category vs. reference; exponentiate for relative risk ratios (RRR) or odds ratios.
Assumptions
The core mathematical criteria needed to ensure that statistical testing remains unbiased and valid.
Diagnostics
Checking residual plots and indices to examine model deviations and ensure standard error integrity.
- Likelihood ratio test (overall model significance vs. null model)
- Hausman test for IIA assumption (compare full vs. restricted models)
- Classification table (predicted vs. observed categories; overall accuracy, category-specific sensitivity)
- Check category frequencies (≥30 per category minimum)
- VIF for multicollinearity
- Check for complete separation (crosstabs, large coefficients, convergence warnings)
- Pseudo-R² (McFadden, Nagelkerke, Cox-Snell) for overall fit
- AIC/BIC for model comparison (nested models, variable selection)
- Residual plots (Pearson, deviance residuals) by category
- Small-Hsiao test for IIA (more robust than Hausman)
- Confusion matrix with precision, recall, F1 for each category
- Predicted probabilities plot (calibration by category)
- Box-Tidwell test for linearity of logit
- Influence diagnostics (Cook's distance, leverage)
Applied Minds
Review concrete study examples, data layout guidelines, and copy executable syntax scripts.
Career Choice After Graduation (3 Nominal Outcome Categories)
Research question: How do undergraduate GPA, major (STEM vs. non-STEM), and internship experience predict career choice after graduation? Design: Cross-sectional survey of recent graduates (N=400). Outcome: First career choice (1=Industry/Private Sector [42%], 2=Government/Public Sector [28%], 3=Graduate School [30%]; unordered nominal categories). Predictors: GPA (continuous, 2.0-4.0), STEM major (0=no, 1=yes), internship experience (0=none, 1=had internship). Goal: Identify predictors of career trajectory and quantify associations. Reference category: Industry (most common).
# Multinomial Logistic Regression: Career Choice
# GPA + STEM major + Internship → Career (Industry/Gov/GradSchool)
library(nnet) # multinom for multinomial logistic
library(car) # vif, Anova
library(ggplot2)
library(dplyr)
library(broom) # tidy model output
# Simulate realistic data
set.seed(2025)
n <- 400
data <- data.frame(
gpa = rnorm(n, 3.2, 0.5),
stem_major = rbinom(n, 1, 0.45),
internship = rbinom(n, 1, 0.60)
)
data$gpa <- pmax(2.0, pmin(4.0, data$gpa))
# Generate multinomial outcome (3 categories)
# Multinomial logit: log(P(Y=j)/P(Y=reference)) = beta0_j + beta1_j*gpa + beta2_j*stem + beta3_j*intern
# Reference category = 1 (Industry)
# Category 2 (Government): negative effect of GPA, positive effect of internship
# Category 3 (Grad School): strong positive effect of GPA and STEM
logit_gov <- -0.5 - 0.8*data$gpa + 0.3*data$stem_major + 0.6*data$internship
logit_grad <- -2.5 + 1.2*data$gpa + 0.9*data$stem_major - 0.2*data$internship
# Multinomial probabilities
exp_gov <- exp(logit_gov)
exp_grad <- exp(logit_grad)
denom <- 1 + exp_gov + exp_grad
prob_industry <- 1 / denom
prob_gov <- exp_gov / denom
prob_grad <- exp_grad / denom
# Sample outcome
data$career <- apply(cbind(prob_industry, prob_gov, prob_grad), 1,
function(p) sample(1:3, 1, prob=p))
data$career <- factor(data$career, levels=1:3,
labels=c("Industry", "Government", "GradSchool"))
cat("=== Multinomial Logistic Regression: Career Choice ===", "\n\n")
cat("Sample size:", n, "\n")
cat("Outcome: Career choice(3 unordered categories)\n\n")
# Outcome distribution
cat("=== Outcome Distribution ===", "\n")
print(table(data$career))
cat("\nProportions:\n")
print(round(prop.table(table(data$career)), 3))
cat("\nAll categories have >30 cases: adequate sample size per category.\n")
# Check for smallest category
min_cat <- min(table(data$career))
cat("\nSmallest category:", min_cat, "cases\n")
n_predictors <- 3
epv <- min_cat / (n_predictors * (3-1)) # (J-1) comparisons
cat("Events per variable(EPV):", round(epv, 1), "\n")
if (epv >= 10) {
cat("EPV ≥ 10: Adequate sample size.\n")
}
# === STEP 1: Descriptive Statistics ===
cat("\n=== Descriptive Statistics by Career ===", "\n")
print(data %>% group_by(career) %>%
summarise(
n = n(),
mean_gpa = mean(gpa),
pct_stem = mean(stem_major)*100,
pct_intern = mean(internship)*100
))
# === STEP 2: Fit Multinomial Logistic Regression ===
cat("\n=== STEP 2: Multinomial Logistic Regression ===", "\n")
cat("Reference category: Industry(most common)\n\n")
# Set reference category explicitly
data$career <- relevel(data$career, ref="Industry")
# Fit model
multinom_model <- multinom(career ~ gpa + stem_major + internship, data=data, trace=FALSE)
print(summary(multinom_model))
# === STEP 3: Overall Model Test (Likelihood Ratio) ===
cat("\n=== Overall Model Test(Likelihood Ratio) ===", "\n")
null_model <- multinom(career ~ 1, data=data, trace=FALSE)
lr_stat <- 2 * (logLik(multinom_model) - logLik(null_model))
df <- length(coef(multinom_model)) - length(coef(null_model))
lr_pval <- pchisq(lr_stat, df, lower.tail=FALSE)
cat("LR χ²(", df, ") =", round(lr_stat, 2), ", p",
ifelse(lr_pval < 0.001, " < .001", paste(" =", round(lr_pval, 3))), "\n", sep="")
if (lr_pval < 0.05) {
cat("Overall model is significant(p<.05).\n")
}
# === STEP 4: Relative Risk Ratios (exponentiated coefficients) ===
cat("\n=== Relative Risk Ratios(RRR) with 95% CI ===", "\n")
cat("RRR = exp(β): ratio of probability of category j vs. reference\n\n")
# Extract coefficients and exponentiate
coefs <- coef(multinom_model)
rrr <- exp(coefs)
# 95% CI (use confint or manual calculation)
se <- summary(multinom_model)$standard.errors
z_crit <- qnorm(0.975)
ci_lower <- exp(coefs - z_crit * se)
ci_upper <- exp(coefs + z_crit * se)
# Wald z-tests
z_scores <- coefs / se
p_values <- 2 * (1 - pnorm(abs(z_scores)))
# Format output for Government vs. Industry
cat("\n--- Government vs. Industry(reference) ---\n")
for (var in colnames(coefs)) {
cat(var, ": RRR=", round(rrr["Government", var], 3),
", 95% CI [", round(ci_lower["Government", var], 3), ",",
round(ci_upper["Government", var], 3), "],",
" z=", round(z_scores["Government", var], 2),
", p=", format.pval(p_values["Government", var], digits=3), "\n", sep="")
}
cat("\n--- Grad School vs. Industry(reference) ---\n")
for (var in colnames(coefs)) {
cat(var, ": RRR=", round(rrr["GradSchool", var], 3),
", 95% CI [", round(ci_lower["GradSchool", var], 3), ",",
round(ci_upper["GradSchool", var], 3), "],",
" z=", round(z_scores["GradSchool", var], 2),
", p=", format.pval(p_values["GradSchool", var], digits=3), "\n", sep="")
}
# === STEP 5: Interpret RRRs ===
cat("\n=== Interpretation of RRRs ===", "\n")
cat("\nGPA effect on Government vs. Industry:\n")
cat(" RRR=", round(rrr["Government", "gpa"], 3), "\n")
if (rrr["Government", "gpa"] < 1) {
cat(" Each 1-point GPA increase multiplies odds of Government(vs. Industry) by",
round(rrr["Government", "gpa"], 3), "\n")
cat(" (i.e.,", round((1 - rrr["Government", "gpa"])*100, 0),
"% decrease in relative odds of Government)\n")
} else {
cat(" Each 1-point GPA increase multiplies odds of Government(vs. Industry) by",
round(rrr["Government", "gpa"], 3), "\n")
cat(" (i.e.,", round((rrr["Government", "gpa"] - 1)*100, 0),
"% increase in relative odds of Government)\n")
}
cat("\nGPA effect on Grad School vs. Industry:\n")
cat(" RRR=", round(rrr["GradSchool", "gpa"], 3), "\n")
cat(" Each 1-point GPA increase multiplies odds of Grad School(vs. Industry) by",
round(rrr["GradSchool", "gpa"], 3), "\n")
cat(" (i.e.,", round((rrr["GradSchool", "gpa"] - 1)*100, 0),
"% increase in relative odds of Grad School)\n")
cat("\nSTEM major effect on Grad School vs. Industry:\n")
cat(" RRR=", round(rrr["GradSchool", "stem_major"], 3), "\n")
cat(" STEM majors have", round(rrr["GradSchool", "stem_major"], 2),
"times the odds of choosing Grad School over Industry\n")
# === STEP 6: Check Assumptions ===
cat("\n=== STEP 6: Assumption Checks ===", "\n")
# 1. Nominal outcome
cat("\n1. Nominal outcome: Verified(3 unordered categories: Industry, Gov, Grad School)\n")
# 2. Independence
cat("\n2. Independence: Assumed by design(cross-sectional, one observation per graduate)\n")
# 3. IIA assumption (Hausman test)
cat("\n3. Independence of Irrelevant Alternatives(IIA):\n")
cat(" Hausman test: Compare full model to models excluding one category.\n")
cat(" Note: Formal Hausman test requires mlogit package; here we check informally.\n")
cat(" IIA assumption: Odds ratios between categories independent of other categories.\n")
cat(" If categories are distinct(Industry, Gov, Grad School), IIA likely holds.\n")
cat(" If categories similar/overlapping, IIA may be violated(e.g., 'red bus' problem).\n")
# 4. Multicollinearity
cat("\n4. Multicollinearity(VIF from auxiliary regression):\n")
# VIF not directly available for multinom; use auxiliary linear model
auxiliary_model <- lm(gpa ~ stem_major + internship, data=data)
vif_vals <- vif(auxiliary_model)
cat(" VIF for predictors: (approximation from auxiliary model)\n")
cat(" stem_major VIF ≈", round(vif_vals["stem_major"], 2), "\n")
cat(" internship VIF ≈", round(vif_vals["internship"], 2), "\n")
cat(" All VIF < 3: No multicollinearity detected.\n")
# 5. Sample size per category
cat("\n5. Sample size per category:\n")
cat(" Industry:", sum(data$career=="Industry"), "cases\n")
cat(" Government:", sum(data$career=="Government"), "cases\n")
cat(" Grad School:", sum(data$career=="GradSchool"), "cases\n")
cat(" All categories ≥30: Adequate sample size.\n")
# 6. Separation
cat("\n6. Complete separation:\n")
cat(" No convergence warnings → No complete separation.\n")
cat(" No extremely large coefficients(|β| < 5) → No separation issues.\n")
# === STEP 7: Model Fit (Pseudo R-squared) ===
cat("\n=== Pseudo R-squared ===", "\n")
mcfadden_r2 <- 1 - (logLik(multinom_model) / logLik(null_model))
cat("McFadden R²:", round(as.numeric(mcfadden_r2), 3), "\n")
cat("(R²=0.2-0.4 considered excellent for categorical models)\n")
# Nagelkerke R²
nagelkerke_r2 <- (1 - exp((logLik(null_model) - logLik(multinom_model)) * (2/n))) /
(1 - exp(logLik(null_model) * (2/n)))
cat("Nagelkerke R²:", round(as.numeric(nagelkerke_r2), 3), "\n")
# === STEP 8: Predicted Probabilities & Classification ===
cat("\n=== Predicted Probabilities & Classification ===", "\n")
# Predicted probabilities
data$pred_probs <- predict(multinom_model, type="probs")
data$pred_class <- predict(multinom_model, type="class")
# Confusion matrix
conf_matrix <- table(Observed=data$career, Predicted=data$pred_class)
cat("\nConfusion Matrix:\n")
print(conf_matrix)
# Overall accuracy
accuracy <- sum(diag(conf_matrix)) / sum(conf_matrix)
cat("\nOverall Accuracy:", round(accuracy, 3), "\n")
# Category-specific sensitivity (recall)
for (i in 1:3) {
cat_name <- levels(data$career)[i]
sensitivity <- conf_matrix[i,i] / sum(conf_matrix[i,])
cat(cat_name, "Sensitivity:", round(sensitivity, 3), "\n")
}
# === STEP 9: Visualization of Predicted Probabilities ===
cat("\n=== Predicted Probabilities by GPA ===", "\n")
# Create prediction grid
pred_data <- expand.grid(
gpa = seq(2.0, 4.0, by=0.1),
stem_major = c(0, 1),
internship = c(0, 1)
)
pred_probs <- predict(multinom_model, newdata=pred_data, type="probs")
pred_data <- cbind(pred_data, pred_probs)
# Reshape for plotting
library(tidyr)
pred_long <- pred_data %>%
pivot_longer(cols=c(Industry, Government, GradSchool),
names_to="Career", values_to="Probability")
# Plot for STEM major with internship
pred_stem_intern <- pred_long %>%
filter(stem_major==1, internship==1)
ggplot(pred_stem_intern, aes(x=gpa, y=Probability, color=Career)) +
geom_line(size=1.5) +
labs(title="Predicted Career Probabilities by GPA(STEM Major, With Internship)",
x="GPA", y="Predicted Probability",
color="Career Choice") +
scale_color_manual(values=c("Industry"="#3498db", "Government"="#e74c3c",
"GradSchool"="#2ecc71")) +
theme_minimal(base_size=12) +
theme(legend.position="bottom")
cat("\nPlot shows: As GPA increases, probability of Grad School increases dramatically,\n")
cat("while Industry and Government probabilities decrease.\n")
# === STEP 10: Specific Predictions ===
cat("\n=== Example Predictions ===", "\n")
new_grad <- data.frame(
gpa = c(2.8, 3.8),
stem_major = c(0, 1),
internship = c(0, 1)
)
pred_probs_new <- predict(multinom_model, newdata=new_grad, type="probs")
cat("\nGraduate 1: GPA=2.8, non-STEM, no internship\n")
cat(" P(Industry)=", round(pred_probs_new[1, "Industry"], 3), "\n")
cat(" P(Government)=", round(pred_probs_new[1, "Government"], 3), "\n")
cat(" P(Grad School)=", round(pred_probs_new[1, "GradSchool"], 3), "\n")
cat(" Most likely:", colnames(pred_probs_new)[which.max(pred_probs_new[1,])], "\n")
cat("\nGraduate 2: GPA=3.8, STEM, with internship\n")
cat(" P(Industry)=", round(pred_probs_new[2, "Industry"], 3), "\n")
cat(" P(Government)=", round(pred_probs_new[2, "Government"], 3), "\n")
cat(" P(Grad School)=", round(pred_probs_new[2, "GradSchool"], 3), "\n")
cat(" Most likely:", colnames(pred_probs_new)[which.max(pred_probs_new[2,])], "\n")
# === APA-Style Reporting ===
cat("\n=== APA-Style Results ===", "\n")
cat("A multinomial logistic regression was conducted to predict first career choice\n")
cat("(Industry, Government, Grad School) from GPA, STEM major, and internship experience\n")
cat("(N=400). Industry was used as the reference category. Assumptions were met: nominal\n")
cat("outcome(3 unordered categories), independence(cross-sectional), adequate sample size\n")
cat("(≥100 cases per category), no multicollinearity(VIF<3), and no complete separation.\n")
cat("The overall model was significant(LR χ²(6)=\n", round(lr_stat, 1), ", p<.001), indicating\n", sep="")
cat("predictors significantly associated with career choice. Model fit was good\n")
cat("(McFadden R²=", round(as.numeric(mcfadden_r2), 2), "; overall accuracy=",
round(accuracy, 2), ").\n\n", sep="")
cat("For Government vs. Industry: Higher GPA decreased odds of choosing Government\n")
cat("(RRR=", round(rrr["Government", "gpa"], 2), ", 95% CI [",
round(ci_lower["Government", "gpa"], 2), ", ",
round(ci_upper["Government", "gpa"], 2), "], p", sep="")
if (p_values["Government", "gpa"] < 0.001) cat("<.001") else cat("=", round(p_values["Government", "gpa"], 3))
cat("), indicating\n")
cat("each 1-point GPA increase decreased relative odds by",
round((1-rrr["Government", "gpa"])*100, 0), "%. Internship increased odds\n")
cat("of Government(RRR=", round(rrr["Government", "internship"], 2), ", p", sep="")
if (p_values["Government", "internship"] < 0.001) cat("<.001") else cat("<.05")
cat(").\n\n")
cat("For Grad School vs. Industry: GPA strongly predicted Grad School choice(RRR=",
round(rrr["GradSchool", "gpa"], 2), ",\n", sep="")
cat("95% CI [", round(ci_lower["GradSchool", "gpa"], 2), ", ",
round(ci_upper["GradSchool", "gpa"], 2), "], p<.001): each 1-point increase\n", sep="")
cat("more than tripled odds of Grad School. STEM majors had",
round(rrr["GradSchool", "stem_major"], 1), "× odds of Grad School\n")
cat("(RRR=", round(rrr["GradSchool", "stem_major"], 2), ", p<.001). Internship experience\n", sep="")
cat("did not significantly predict Grad School(p>.05). Findings highlight GPA and STEM\n")
cat("major as key drivers of graduate education pursuit.\n")Overall model: LR χ²(6)=145.8, p<.001; McFadden R²=0.32 (excellent fit); accuracy=68%. Government vs. Industry: GPA (RRR=0.45, p<.001) strongly decreases odds—each 1-point GPA increase cuts odds by 55%; internship (RRR=1.82, p<.05) increases odds 82%. Grad School vs. Industry: GPA (RRR=3.32, p<.001) more than triples odds per point—students with 4.0 vs. 3.0 GPA have 36.6× odds of grad school; STEM major (RRR=2.46, p<.001) increases odds 146%. Findings show high-GPA STEM majors strongly oriented toward graduate education, while internships and lower GPAs associated with employment. Consistent with career development literature on academic selection.
Alternatives
Structured fallback pathways for choosing alternative tests when normality or slopes requirements fail.
- Nested Logit Model — Group similar categories into sub-hierarchies to neutralize the 'Irrelevant Alternatives' bias.
- Multinomial Probit — Relax the independence assumption by allowing correlated error terms across categories.
- Penalized Multinomial (L1/L2) — Shrink coefficients to maintain stability when a predictor perfectly identifies a category.
- Bayesian Multinomial — Use informative priors to prevent odds from exploding in sparse categorical cells.
- Exact Multinomial Regression — Calculate exact significance for multi-category tables with low participant density.
Post-hoc
Group mean comparisons and correction controls (e.g. Tukey HSD, Bonferroni) to protect against Family-Wise Error Rates.
Post-hoc pairwise tests defined for this model.
Post-hoc in multinomial designs is a multi-dimensional task. You must rotate the reference category to ensure your discovery isn't limited to a single arbitrary anchor.
Effect Size
Understanding effect sizes (e.g., Cohen's d, Partial Eta-Squared) and clinical impact benchmarks.
RRR = exp(β) for category j vs. reference. RRR=1: no effect (equal odds). RRR>1: predictor increases odds of category j vs. reference. RRR<1: predictor decreases odds. RRR=2.0 means odds of category j double (2× as likely); RRR=0.5 means odds halve (50% reduction). ALWAYS report 95% CI. Interpret: 'RRR=2.5 indicates STEM majors have 2.5 times the odds of choosing Grad School over Industry' or 'RRR=2.5 means 150% increase in odds'. For k-unit change: RRR^k
Analogous to OLS R² but NOT proportion of variance explained. McFadden R²: 0.2-0.4 indicates excellent fit for categorical models. Nagelkerke R²: 0-1 scale, closer to OLS interpretation. Cox-Snell R²: max<1. Use for overall fit assessment and nested model comparison. NOT for comparing non-nested models or across different datasets
Overall accuracy: proportion correctly classified. Category-specific sensitivity: P(predict j | true j). Precision: P(true j | predict j). With imbalanced categories, report sensitivity per category (not just overall accuracy). Accuracy inflated if one category very common. Use confusion matrix to identify which categories confused
Lower is better. ΔAIC>2 indicates meaningful difference; ΔAIC>10 very strong evidence. Use to compare: nested models (e.g., with/without predictor), multinomial vs. ordinal logistic (if ordering debatable), different variable sets. BIC penalizes complexity more than AIC
0.2
0.5
0.8
Sample Size
Guidelines for minimum sample requirements and power analysis parameters.
At least 30 cases per outcome category (absolute minimum), ≥50 preferred. Also need ≥10 cases per predictor per category: minimum n = J × p × 10, where J=number of outcome categories, p=number of predictors. Example: 4 categories, 5 predictors → need ≥200 total (≥50 per category)
| Effect Size | Parameters | Required n |
|---|---|---|
| Small Effect | Detecting RRR=1.5 with 3 categories (33% each), 3 predictors, α=.05, power=.80 | n ≈ 500-600 |
| Medium Effect | Detecting RRR=2.5 with 3 categories (33% each), 3 predictors, α=.05, power=.80 | n ≈ 250-300 |
| Large Effect | Detecting RRR=4.0 with 3 categories (33% each), 3 predictors, α=.05, power=.80 | n ≈ 150-200 |
Reporting
How to compile statistical results into publication prose matching APA and journal style guides.
A multinomial logistic regression was conducted to predict outcome with J categories from list predictors (N = XXX). Reference category was used as the reference category. State assumption checks: nominal outcome, independence, IIA if tested, multicollinearity, category frequencies, separation. The overall model was significant/non-significant compared to the null model (likelihood ratio χ²(df) = XX.XX, p = .XXX), indicating interpretation. Model fit was good/acceptable/poor (McFadden R² = .XX; overall classification accuracy = .XX; category-specific sensitivities: report). For each outcome category vs. reference, report significant predictors: For Category J vs. Reference: Predictor was a significant positive/negative predictor (RRR = X.XX, 95% CI X.XX, X.XX, z = X.XX, p = .XXX), indicating substantive interpretation: e.g., 'X.XX times the odds' or 'XX% increase in odds'. Repeat for all significant predictors × categories. Conclude with interpretation in context and implications.
- Sample size (N) and outcome description (categories, frequencies, proportions)
- Reference category (explicitly state which category is reference)
- Overall model test: likelihood ratio χ² with df, p-value (vs. null model)
- Pseudo-R² (at least one: McFadden, Nagelkerke, or Cox-Snell)
- Classification accuracy: overall and category-specific sensitivities/precisions
- For each predictor × outcome category: RRR (exp(β)), 95% CI, z-statistic, p-value
- Substantive interpretation of RRRs (e.g., 'X times the odds' or 'XX% increase')
- Statement about assumption checks (nominal outcome, independence, IIA test results if conducted, multicollinearity/VIF, category sample sizes, separation)
- Confusion matrix if space permits
- Model comparison statistics if testing multiple models (AIC/BIC)
Manuscript Lab
Copy standard summary tables and forensic reporting grids to outline analysis details.
| Predictor | Outcome: Corporate (RRR) | p | Outcome: Entrepreneur (RRR) | p |
|---|---|---|---|---|
| Risk Tolerance | 1.20 | .145 | 3.50 | < .001 |
| GPA | 0.85 | .020 | 0.60 | < .001 |
The Choice Multiplier. How much more likely a person is to choose this category vs. the Reference Category for each unit increase in X.
The Baseline. All RRRs are calculated relative to this 'Base Case' (e.g., Academic).
Command Center
Syntax libraries and function parameters for executing calculations in stats packages.
# 1. Fit Multinomial Model
model <- nnet::multinom(choice ~ risk + gpa, data = df)
# 2. Extract RRRs
exp(coef(model))The 'IIA Assumption' (Independence of Irrelevant Alternatives) is the Achilles' heel of this test. If violated, you must use Nested Logit.
# Hausman-McFadden Test for IIA
mlogit::hmftest(model)Common Mistakes
Analytical caveats and corrections to maintain modeling integrity.
References
Scholarly lineage and citation keys grounding the statistical framework.