Fatigue & Weakness: Ordinal Regression

Proportional odds models for ordinal fatigue and weakness severity, with formal model selection.

Ordinal regression R Markdown analysis

Project Info

Data and variables

The analysis uses clinical-style ordinal measures from the Joachim IC dataset: SSC-W (weakness) and SSC-F (fatigue), each coded on an ordered scale 0-3, plus a binary treatment / intervention indicator (IC) (0 = control, 1 = treatment). Repeated observations over time points were present in the raw file; per the problem design, time was disregarded by collapsing to unique combinations of weakness, fatigue, and treatment.

Why proportional odds (cumulative logit)

Fatigue and weakness are ordered categories, not continuous scores and not unordered labels. A natural model is the proportional odds (cumulative logit) model:

log(P(Y ≤ j) / P(Y > j)) = αj − βTX

Cutpoints αj separate adjacent response levels; a single coefficient vector β shifts the cumulative odds of being in a higher category. Models were fit with polr() in the MASS package, with cell frequencies as weights.

Aggregation to frequency-weighted cell counts

Fitting polr() to the raw longitudinal rows would treat repeated measures as independent observations. Instead, the data were aggregated with table() over (SSC-W, SSC-F, IC), producing frequency-weighted independent cell counts. Those frequencies enter the likelihood as weights, so model comparison reflects the collapsed three-way table rather than inflated sample size from repeated visits.

Problem 1: modeling fatigue given weakness and treatment

Four nested proportional odds models for fatigue were compared:

  • Null: fatigue ~ 1
  • Weakness-only: fatigue ~ weakness
  • Treatment-only: fatigue ~ ic
  • Full: fatigue ~ weakness + ic

Selection used likelihood ratio tests (LRT) together with AIC and BIC. Weakness alone produced a very large improvement over the null (LRT χ² ≈ 641 on 4 df, p < 0.0001; residual deviance falling from about 3585 to 2944). Treatment alone improved on the null only modestly and remained far worse than the weakness-only model by AIC and BIC. Adding treatment on top of weakness did not help: LRT χ² ≈ 0.17 on 1 df (p ≈ 0.68), with AIC and BIC both increasing.

Preferred model for fatigue: weakness-only. Treatment adds little once weakness is included. Estimated odds of more severe fatigue rose steeply across weakness levels relative to weakness = 0: OR ≈ 5.9 (weakness 1), 17.6 (weakness 2), and 78.5 (weakness 3). Fitted probabilities shift accordingly: at weakness 0, no fatigue is most likely; at weakness 3, severe fatigue dominates.

Problem 2: modeling weakness given fatigue and treatment

Roles were reversed to model ordinal weakness from fatigue and treatment, again comparing null, fatigue-only, treatment-only, and full models with LRT, AIC, and BIC. Fatigue was the dominant predictor; treatment alone explained little. Unlike Problem 1, adding treatment to the fatigue model produced a small but statistically significant improvement (LRT χ² ≈ 10.2 on 1 df, p ≈ 0.001), and the full model had the best AIC and BIC.

Preferred model: full (weakness ~ fatigue + ic). Fatigue shows a strong positive association with higher weakness (linear contrast OR on the order of ~23). Treatment has a modest protective association after controlling for fatigue (OR ≈ 0.71).

Problem 3: log-linear models for the three-way table

Hierarchical log-linear models were fit to the Weakness × Fatigue × Treatment contingency table (independence through all pairwise associations). Nested G² comparisons favored the second-order model [WF][WI][FI] (all pairwise interactions, no three-way term): it fits the observed counts well, while dropping any pairwise association worsens fit significantly. That structure is consistent with mutual pairwise association among weakness, fatigue, and treatment in the aggregated data, without requiring a three-factor interaction. Pearson residuals under the preferred model were generally small, supporting adequate fit across cells.

Materials

Download the analysis write-up and code: final_project_writeup.Rmd and final_project_code.Rmd.