Lesson 11 of 13

Beta and Ordinal Regression

Last lesson your outcomes were amounts of money: strictly positive, but free to climb as high as they liked. Now the outcomes hit walls they cannot cross.

Meet Maya, a data scientist on a customer-success team. For every company that pays for her product she watches two numbers. The first is seat utilisation: of the licences a customer bought, what fraction are actually being used this month. That number lives between 0 and 1 and can never leave: you cannot use 120% of your seats, or minus 10%. The second is an analyst's quarterly health rating, one of three ordered rungs: at risk, then stable, then healthy. It has an order (healthy beats stable beats at risk) but no numbers: "healthy" is not "3 units" of anything.

Neither outcome fits on the open number line that ordinary regression assumes. A proportion is trapped inside an interval; a rating is trapped inside a short, ordered ladder. This lesson gives each its own model, and both turn out to lean on the same tool you met in logistic regression: the logit link. Toggle the panel below to Beta to see the shape of the first one.

By the end of this lesson you will be able to:

  • Say why ordinary regression is the wrong tool for a proportion in the interval (0, 1), and fit a beta regression instead
  • Read a beta model's coefficients as odds ratios on the mean proportion, not as amounts added
  • Fit a proportional-odds model to an ordered rating, and read it as a cumulative odds ratio plus predicted category probabilities

Prerequisites: you can fit and read a linear model, and you have met the GLM idea, the logit link, and reading exp(coef) as a multiplier in logistic regression and the count-model lesson. Comfortable with odds and log-odds (the logit is the log of the odds).

Why the straight line fails

A proportion cannot leave the interval from 0 to 1

Maya's first outcome is active_frac, the fraction of paid seats a customer actually used this month. Here is her book of 300 accounts, built right here so every line on this page runs in interactive R. Onboarding hours and the plan tier push utilisation up through a logit link, and the actual fraction is a genuine Beta draw around that mean, so it always lands strictly inside (0, 1):

RInteractive R
set.seed(2026) n <- 300 onboarding <- round(runif(n, 0, 8), 1) # hours of guided onboarding plan <- factor(sample(c("basic", "pro"), n, replace = TRUE, prob = c(0.6, 0.4))) eta <- -0.7 + 0.25 * onboarding + 0.6 * (plan == "pro") # a linear predictor, on the logit scale active_frac <- rbeta(n, plogis(eta) * 12, (1 - plogis(eta)) * 12) # seats-active fraction, always in (0,1) # The same onboarding also drives an ordered health rating; we return to it later. z <- -1.6 + 0.45 * onboarding + rlogis(n) health <- ordered(ifelse(z < 0, "at risk", ifelse(z < 2.4, "stable", "healthy")), levels = c("at risk", "stable", "healthy")) accounts <- data.frame(onboarding, plan, active_frac = round(active_frac, 3), health) head(accounts, 4) #> onboarding plan active_frac health #> 1 5.6 basic 0.691 stable #> 2 4.5 basic 0.634 healthy #> 3 1.1 pro 0.680 at risk #> 4 2.3 basic 0.629 at risk

  

Plot utilisation against onboarding and two facts jump out. The cloud is pinned between 0 and 1 (no point can escape the floor or the ceiling), and it climbs along a gentle S, steep in the middle and flattening as it nears either wall. A straight line respects neither.

Fit a straight line anyway and it breaks at the wall. Ask it for the utilisation of a heavily onboarded pro account and its 95% prediction interval runs clean past 1.0, predicting a real chance of using more than 100% of the seats, which is impossible:

RInteractive R
lm_fit <- lm(active_frac ~ onboarding + plan, data = accounts) round(predict(lm_fit, data.frame(onboarding = c(0.5, 8), plan = "pro"), interval = "prediction"), 3) #> fit lwr upr #> 1 0.509 0.252 0.767 #> 2 0.900 0.642 1.158

  

There is a second, quieter problem. A proportion's spread is not constant: an account sitting near 0.5 can swing a lot, but one already at 0.95 has almost nowhere to move, so its variance is squeezed against the ceiling. Ordinary regression assumes the noise is the same size everywhere. It is not.