On this page
A season average is slow to move. A team’s form changes faster: the offense that struggled in September can look different over its last two games or so. This recipe compares each team’s last 150 offensive plays with the 150 before them, then lists the five biggest risers and the five biggest fallers.
There is no NBA rolling-window release yet, so this recipe is college football only.
The data
The cfb_rolling_windows release has one file per season
and no R loader, so read it by URL.
nflreadr::load_from_url() reads the .rds copy
with packages the site already uses. The .parquet and
.csv copies hold the same rows.
url <- paste0(
"https://github.com/sportsdataverse/sportsdataverse-data/releases/download/",
"cfb_rolling_windows/rolling_windows_2026.rds"
)
windows <- as.data.frame(nflreadr::load_from_url(url))
stopifnot(nrow(windows) > 0)
dim(windows)
#> [1] 25228 20
names(windows)
#> [1] "season" "entity_type" "entity_id" "entity_name"
#> [5] "team_id" "metric" "window_unit" "window_n"
#> [9] "cur" "prev" "season_start" "career_baseline"
#> [13] "delta_prev" "delta_season" "delta_career" "delta_prev_rank"
#> [17] "n" "qualified" "last_event_date" "as_of_date"Each row is one player or team, one metric and one window size.
-
curis the metric over the lastwindow_nevents (plays, carries, dropbacks or targets, named inwindow_unit). -
previs the metric over thewindow_nevents before those. -
delta_previscur - prev, anddelta_prev_rankranks it (1 is the biggest rise). -
nis how many events the last window holds. A row isqualifiedonce that window is full.
count(windows, entity_type, metric, window_unit, window_n)
#> entity_type metric window_unit window_n n
#> 1 player epa carry 50 2044
#> 2 player epa carry 100 2044
#> 3 player epa dropback 50 626
#> 4 player epa dropback 100 626
#> 5 player epa dropback 300 626
#> 6 player epa target 30 3089
#> 7 player epa target 60 3089
#> 8 player success_rate carry 50 2044
#> 9 player success_rate carry 100 2044
#> 10 player success_rate dropback 50 626
#> 11 player success_rate dropback 100 626
#> 12 player success_rate dropback 300 626
#> 13 player success_rate target 30 3089
#> 14 player success_rate target 60 3089
#> 15 team epa play 150 235
#> 16 team epa play 300 235
#> 17 team success_rate play 150 235
#> 18 team success_rate play 300 235This file is the season in progress. The date shows how current it is:
Risers and fallers
Keep teams, EPA per play and the 150-play window, and only qualified rows that also have a previous window: a program with no earlier plays has no change to rank. The percentile places each team’s last 150 plays among every team in the same pool, so a big riser can still be below average.
pool <- windows |>
filter(
entity_type == "team", metric == "epa", window_n == 150,
qualified, !is.na(prev)
) |>
mutate(pct = 100 * percent_rank(cur))
stopifnot(all(pool$n == 150), !anyDuplicated(pool$entity_id))
nrow(pool)
#> [1] 228
movers <- bind_rows(
Risers = slice_max(pool, delta_prev, n = 5, with_ties = FALSE),
Fallers = slice_min(pool, delta_prev, n = 5, with_ties = FALSE),
.id = "group"
) |>
select(group, entity_name, prev, cur, n, pct, delta_prev_rank)
movers
#> group entity_name prev cur n pct
#> 1 Risers Louisiana Tech Bulldogs -0.26370043 0.339675717 150 98.237885
#> 2 Risers Kansas Jayhawks -0.17726527 0.328040471 150 97.356828
#> 3 Risers UL Monroe Warhawks -0.07478280 0.269625081 150 95.594714
#> 4 Risers Texas Southern Tigers -0.34182483 -0.023425918 150 51.541850
#> 5 Risers Southern Miss Golden Eagles -0.07446965 0.231102587 150 91.189427
#> 6 Fallers Northern Iowa Panthers 0.27039169 -0.273207534 150 9.251101
#> 7 Fallers Holy Cross Crusaders 0.30123470 -0.204168123 150 18.061674
#> 8 Fallers Eastern Washington Eagles 0.14616080 -0.271634752 150 9.691630
#> 9 Fallers Northwestern State Demons -0.13158858 -0.543159627 150 0.000000
#> 10 Fallers Texas State Bobcats 0.38671371 -0.007728742 150 54.185022
#> delta_prev_rank
#> 1 1
#> 2 2
#> 3 3
#> 4 4
#> 5 5
#> 6 228
#> 7 227
#> 8 226
#> 9 225
#> 10 224The pool holds every team the release covers, FCS programs as well as FBS.
The table
gt_delta() computes the change from the two rate
columns, so the table shows the arithmetic it ranks. Every rate shows
its sample: the earlier window is 150 plays by definition, and the last
window’s n sits next to its rate. The change column’s green
and red are not the only cue, since every change also carries its sign.
Pass color_positive and color_negative to
gt_delta() for a pair that does not rely on red-green
vision.
movers |>
gt(groupname_col = "group") |>
gt_sdv_logos(entity_name, league = "cfb", height = 22, include_name = TRUE) |>
gt_delta(prev, cur, column_label = "Change", decimals = 3) |>
fmt_number(c(prev, cur), decimals = 3) |>
cols_merge(c(cur, n), pattern = "{1} (n = {2})") |>
gt_percentile_bar(pct, width = 160) |>
cols_label(
entity_name = "Team",
prev = "Previous 150 plays",
cur = "Last 150 plays",
pct = "Last 150, percentile",
delta_prev_rank = "Change rank"
) |>
tab_header(
title = "Offensive form: last 150 plays vs the 150 before",
subtitle = paste("EPA per play, 2026 season, as of", as_of)
) |>
tab_source_note("Data: sportsdataverse-data release cfb_rolling_windows") |>
gt_theme_sdv(density = "compact")| Offensive form: last 150 plays vs the 150 before | |||||
| EPA per play, 2026 season, as of 2026-10-10 | |||||
| Team | Previous 150 plays | Last 150 plays | Change | Last 150, percentile | Change rank |
|---|---|---|---|---|---|
| Risers | |||||
Louisiana Tech Bulldogs |
−0.264 | 0.340 (n = 150) | +0.603 | 98
|
1 |
Kansas Jayhawks |
−0.177 | 0.328 (n = 150) | +0.505 | 97
|
2 |
UL Monroe Warhawks |
−0.075 | 0.270 (n = 150) | +0.344 | 96
|
3 |
Texas Southern Tigers |
−0.342 | −0.023 (n = 150) | +0.318 | 52
|
4 |
Southern Miss Golden Eagles |
−0.074 | 0.231 (n = 150) | +0.306 | 91
|
5 |
| Fallers | |||||
Northern Iowa Panthers |
0.270 | −0.273 (n = 150) | −0.544 | 9
|
228 |
Holy Cross Crusaders |
0.301 | −0.204 (n = 150) | −0.505 | 18
|
227 |
Eastern Washington Eagles |
0.146 | −0.272 (n = 150) | −0.418 | 10
|
226 |
Northwestern State Demons |
−0.132 | −0.543 (n = 150) | −0.412 | 0
|
225 |
Texas State Bobcats |
0.387 | −0.008 (n = 150) | −0.394 | 54
|
224 |
| Data: sportsdataverse-data release cfb_rolling_windows | |||||
Related SportsDataverse packages
- sdvplot - the Python plotting package
- sdvplot-js - the JavaScript / TypeScript plotting packages
- cfbfastR - college football
- hoopR - men’s basketball
- wehoop - women’s basketball
- baseballr - baseball
- fastRhockey - hockey
- oddsapiR - betting odds
- sportyR - playing surfaces
- sportsdataverse-py - the Python package
- sportsdataverse-R - the R meta-package

Louisiana Tech Bulldogs
Kansas Jayhawks
UL Monroe Warhawks
Texas Southern Tigers
Southern Miss Golden Eagles
Northern Iowa Panthers
Holy Cross Crusaders
Eastern Washington Eagles
Northwestern State Demons
Texas State Bobcats