How the leaderboards are computed

The headline ranking on every segment page is the per-segment residual of an OLS regression. This page explains what that means, why it's the metric of choice, and the caveats attached to it.

Why residuals, not raw watches

Letterboxd watch counts correlate strongly with theatrical reach: a film released in 50 countries with a $200M box office will collect millions of LB watches almost regardless of how good it is. Ranking by raw watches mostly ranks by marketing budget.

Residuals strip out the expected effect of theatrical reach and ask the more interesting question: given how widely this film was released, how much more (or less) did Letterboxd embrace it? A positive residual means LB punched above the regression line; a negative one means it punched below.

The two metrics

The site sorts segments by per-segment Metric B residual. Each release type fits its own regression, so a streaming-only film's residual is interpreted relative to other streaming-only films, not against blockbusters.

What residual_b_segment means

For a film in wide_theatrical:

What different residual values look like

Concrete examples from the current dataset, picked to give the magnitudes some weight.

Important caveats (don't read these as causal)

Per-segment film counts

Films currently in the residual fit per segment:

Distribution of residuals per segment

Residuals are mean-zero by construction (OLS includes an intercept), so the centre of each distribution sits on 0. A wider spread = the segment has more variability in LB outcome relative to theatrical reach.

A segment with fewer than 20 films in the residual fit gets no per-segment residual (films keep their pooled residual_b instead). Cutoff per MIN_SEGMENT in src/pipeline/compute_residuals.py.

Pipeline stages

  1. build_universe — TMDB discover ∪ Box Office Mojo, deduped by tmdb_id
  2. enrich_metadata — TMDB per-film metadata + watch/providers (cached)
  3. scrape_letterboxd — Playwright per-film page (watches, likes, themes)
  4. the_numbers — best-effort budget gap-fill
  5. classify_release_type — wide / limited / festival / streaming / hybrid
  6. merge — single films table + validate outlier flags
  7. compute_residuals — Metric A + B + per-segment, written back to films.parquet

Source: GitHub repo (private until publish-decision).