Get started with nflseedR
Sebastian Carl and Lee Sharpe
Source:vignettes/articles/nflseedR.Rmd
nflseedR.Rmd
Preface
nflseedR is designed to efficiently take over the sophisticated and complex rule set of the NFL regarding division ranks, postseason seeding and draft order. It is intended to be used for NFL season simulations to help modelers focus on their models rather than the tie-breaking procedures. The NFL’s official procedures for breaking ties for postseason playoffs can be found here and this site explains the assigning of draft picks.
However, it must be mentioned that nflseedR does not support all levels of tie-breakers at the moment. The deepest tie-breaker possible at the moment is the strength of schedule. After that, the decision is made at random. It should be noted, however, that the need for additional levels is extremely unlikely in reality.
Using In-Simulation Functions
You can get NFL game data from this function:
-
load_sharpe_games()
to collect game information and results
And if you prefer, you can take or generate any set of game outcomes and let nflseedR handle all of the NFL seeding and tiebreaker math for you with three in-simulation functions (each can handle thousands of seasons at once):
-
compute_division_ranks()
to find all division winners, -
compute_conference_seeds()
to get the playoff participants, and -
compute_draft_order()
to find the resulting draft pick for each team.
The following sections will demonstrate how to use them and what input is required.
Loading the package is obligatory, so it is done first (along with
dplyr
for data wrangling and the pipe
):
Load Sharpe Games
games <- nflseedR::load_sharpe_games()
games %>% dplyr::slice_tail(n = 20) %>% knitr::kable()
game_id | season | game_type | week | gameday | weekday | gametime | away_team | away_score | home_team | home_score | location | result | total | overtime | old_game_id | gsis | nfl_detail_id | pfr | pff | espn | ftn | away_rest | home_rest | away_moneyline | home_moneyline | spread_line | away_spread_odds | home_spread_odds | total_line | under_odds | over_odds | div_game | roof | surface | temp | wind | away_qb_id | home_qb_id | away_qb_name | home_qb_name | away_coach | home_coach | referee | stadium_id | stadium |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
2023_18_ATL_NO | 2023 | REG | 18 | 2024-01-07 | Sunday | 13:00 | ATL | 17 | NO | 48 | Home | 31 | 65 | 0 | 2024010700 | 59440 | NA | 202401070nor | NA | 401547649 | NA | 7 | 7 | 145 | -175 | 3.5 | -122 | 102 | 41.5 | -108 | -112 | 1 | dome | sportturf | NA | NA | 00-0038122 | 00-0031280 | Desmond Ridder | Derek Carr | Arthur Smith | Dennis Allen | John Hussey | NOR00 | Mercedes-Benz Superdome |
2023_18_JAX_TEN | 2023 | REG | 18 | 2024-01-07 | Sunday | 13:00 | JAX | 20 | TEN | 28 | Home | 8 | 48 | 0 | 2024010702 | 59443 | NA | 202401070oti | NA | 401547652 | NA | 7 | 7 | -185 | 154 | -3.5 | -102 | -118 | 41.5 | -112 | -108 | 1 | outdoors | grass | 41 | 11 | 00-0036971 | 00-0029701 | Trevor Lawrence | Ryan Tannehill | Doug Pederson | Mike Vrabel | Tra Blake | NAS00 | Nissan Stadium |
2023_18_SEA_ARI | 2023 | REG | 18 | 2024-01-07 | Sunday | 16:25 | SEA | 21 | ARI | 20 | Home | -1 | 41 | 0 | 2024010712 | 59429 | NA | 202401070crd | NA | 401547638 | NA | 7 | 7 | -155 | 130 | -2.5 | -122 | 102 | 48.0 | -110 | -110 | 1 | closed | grass | NA | NA | 00-0030565 | 00-0035228 | Geno Smith | Kyler Murray | Pete Carroll | Jonathan Gannon | Adrian Hill | PHO00 | State Farm Stadium |
2023_18_CHI_GB | 2023 | REG | 18 | 2024-01-07 | Sunday | 16:25 | CHI | 9 | GB | 17 | Home | 8 | 26 | 0 | 2024010706 | 59434 | NA | 202401070gnb | NA | 401547643 | NA | 7 | 7 | 124 | -148 | 2.5 | -102 | -118 | 45.5 | -108 | -112 | 1 | outdoors | grass | 34 | 7 | 00-0036945 | 00-0036264 | Justin Fields | Jordan Love | Matt Eberflus | Matt LaFleur | Carl Cheffers | GNB00 | Lambeau Field |
2023_18_KC_LAC | 2023 | REG | 18 | 2024-01-07 | Sunday | 16:25 | KC | 13 | LAC | 12 | Home | -1 | 25 | 0 | 2024010709 | 59436 | NA | 202401070sdg | NA | 401547645 | NA | 7 | 7 | 154 | -185 | 3.5 | -115 | -105 | 35.0 | -108 | -115 | 1 | dome | matrixturf | NA | NA | 00-0027948 | 00-0035282 | Blaine Gabbert | Easton Stick | Andy Reid | Brandon Staley | Scott Novak | LAX01 | SoFi Stadium |
2023_18_DEN_LV | 2023 | REG | 18 | 2024-01-07 | Sunday | 16:25 | DEN | 14 | LV | 27 | Home | 13 | 41 | 0 | 2024010708 | 59437 | NA | 202401070rai | NA | 401547646 | NA | 7 | 7 | 145 | -175 | 3.5 | -118 | -102 | 37.5 | -115 | -105 | 1 | dome | grass | NA | NA | 00-0035264 | 00-0038579 | Jarrett Stidham | Aidan O’Connell | Sean Payton | Antonio Pierce | Shawn Hochuli | VEG00 | Allegiant Stadium |
2023_18_PHI_NYG | 2023 | REG | 18 | 2024-01-07 | Sunday | 16:25 | PHI | 10 | NYG | 27 | Home | 17 | 37 | 0 | 2024010711 | 59441 | NA | 202401070nyg | NA | 401547650 | NA | 7 | 7 | -238 | 190 | -4.5 | -112 | -108 | 43.0 | -105 | -115 | 1 | outdoors | fieldturf | 36 | 12 | 00-0036389 | 00-0028118 | Jalen Hurts | Tyrod Taylor | Nick Sirianni | Brian Daboll | Craig Wrolstad | NYC01 | MetLife Stadium |
2023_18_LA_SF | 2023 | REG | 18 | 2024-01-07 | Sunday | 16:25 | LA | 21 | SF | 20 | Home | -1 | 41 | 0 | 2024010710 | 59442 | NA | 202401070sfo | NA | 401547651 | NA | 7 | 7 | 200 | -245 | 5.5 | -108 | -112 | 40.0 | -108 | -112 | 1 | outdoors | grass | 52 | 11 | 00-0032950 | 00-0034869 | Carson Wentz | Sam Darnold | Sean McVay | Kyle Shanahan | Clay Martin | SFO01 | Levi’s Stadium |
2023_18_DAL_WAS | 2023 | REG | 18 | 2024-01-07 | Sunday | 16:25 | DAL | 38 | WAS | 10 | Home | -28 | 48 | 0 | 2024010707 | 59444 | NA | 202401070was | NA | 401547653 | NA | 8 | 7 | -850 | 575 | -13.0 | -115 | -105 | 47.5 | -110 | -110 | 1 | outdoors | grass | 48 | 13 | 00-0033077 | 00-0037077 | Dak Prescott | Sam Howell | Mike McCarthy | Ron Rivera | Shawn Smith | WAS00 | FedExField |
2023_18_BUF_MIA | 2023 | REG | 18 | 2024-01-07 | Sunday | 20:20 | BUF | 21 | MIA | 14 | Home | -7 | 35 | 0 | 2024010713 | 59438 | NA | 202401070mia | NA | 401547647 | NA | 7 | 7 | -155 | 130 | -2.5 | -125 | 105 | 47.5 | -110 | -110 | 1 | outdoors | grass | 63 | 6 | 00-0034857 | 00-0036212 | Josh Allen | Tua Tagovailoa | Sean McDermott | Mike McDaniel | Alex Kemp | MIA00 | Hard Rock Stadium |
2023_19_CLE_HOU | 2023 | WC | 19 | 2024-01-13 | Saturday | 16:30 | CLE | 14 | HOU | 45 | Home | 31 | 59 | 0 | 2024011300 | 59494 | NA | 202401130htx | NA | 401547749 | NA | 6 | 7 | -148 | 124 | -2.5 | -110 | -110 | 45.0 | -105 | -115 | 0 | closed | astroturf | NA | NA | 00-0026158 | 00-0039163 | Joe Flacco | C.J. Stroud | Kevin Stefanski | DeMeco Ryans | Clay Martin | HOU00 | NRG Stadium |
2023_19_MIA_KC | 2023 | WC | 19 | 2024-01-13 | Saturday | 20:00 | MIA | 7 | KC | 26 | Home | 19 | 33 | 0 | 2024011301 | 59495 | NA | 202401130kan | NA | 401547750 | NA | 6 | 6 | 190 | -230 | 4.5 | -102 | -118 | 43.5 | -118 | -102 | 0 | outdoors | grass | -4 | 19 | 00-0036212 | 00-0033873 | Tua Tagovailoa | Patrick Mahomes | Mike McDaniel | Andy Reid | Brad Rogers | KAN00 | GEHA Field at Arrowhead Stadium |
2023_19_GB_DAL | 2023 | WC | 19 | 2024-01-14 | Sunday | 16:30 | GB | 48 | DAL | 32 | Home | -16 | 80 | 0 | 2024011401 | 59497 | NA | 202401140dal | NA | 401547752 | NA | 7 | 7 | 275 | -345 | 7.0 | 102 | -122 | 52.5 | -105 | -115 | 0 | closed | matrixturf | NA | NA | 00-0036264 | 00-0033077 | Jordan Love | Dak Prescott | Matt LaFleur | Mike McCarthy | Ron Torbert | DAL00 | AT&T Stadium |
2023_19_LA_DET | 2023 | WC | 19 | 2024-01-14 | Sunday | 20:00 | LA | 23 | DET | 24 | Home | 1 | 47 | 0 | 2024011402 | 59498 | NA | 202401140det | NA | 401547753 | NA | 7 | 7 | 136 | -162 | 3.5 | -122 | 102 | 52.5 | -102 | -118 | 0 | dome | fieldturf | NA | NA | 00-0026498 | 00-0033106 | Matthew Stafford | Jared Goff | Sean McVay | Dan Campbell | Craig Wrolstad | DET00 | Ford Field |
2023_19_PIT_BUF | 2023 | WC | 19 | 2024-01-15 | Monday | 16:30 | PIT | 17 | BUF | 31 | Home | 14 | 48 | 0 | 2024011501 | 59496 | NA | 202401150buf | NA | 401547751 | NA | 9 | 8 | 370 | -485 | 10.0 | -108 | -112 | 39.5 | -115 | -105 | 0 | outdoors | a_turf | 17 | 10 | 00-0034771 | 00-0034857 | Mason Rudolph | Josh Allen | Mike Tomlin | Sean McDermott | Carl Cheffers | BUF00 | New Era Field |
2023_19_PHI_TB | 2023 | WC | 19 | 2024-01-15 | Monday | 20:00 | PHI | 9 | TB | 32 | Home | 23 | 41 | 0 | 2024011500 | 59499 | NA | 202401150tam | NA | 401547754 | NA | 8 | 8 | -162 | 136 | -2.5 | -125 | 105 | 43.0 | -102 | -118 | 0 | outdoors | grass | 65 | 2 | 00-0036389 | 00-0034855 | Jalen Hurts | Baker Mayfield | Nick Sirianni | Todd Bowles | Adrian Hill | TAM00 | Raymond James Stadium |
2023_20_HOU_BAL | 2023 | DIV | 20 | 2024-01-20 | Saturday | 16:30 | HOU | NA | BAL | NA | Home | NA | NA | NA | 2024012001 | NA | NA | 202401200rav | NA | NA | NA | 7 | 14 | 340 | -440 | 9.5 | -110 | -110 | 43.5 | -105 | -115 | 0 | outdoors | grass | NA | NA | 00-0039163 | 00-0034796 | C.J. Stroud | Lamar Jackson | DeMeco Ryans | John Harbaugh | NA | BAL00 | M&T Bank Stadium |
2023_20_GB_SF | 2023 | DIV | 20 | 2024-01-20 | Saturday | 20:15 | GB | NA | SF | NA | Home | NA | NA | NA | 2024012002 | NA | NA | 202401200sfo | NA | NA | NA | 6 | 13 | 370 | -485 | 10.0 | -110 | -110 | 50.5 | -105 | -115 | 0 | outdoors | grass | NA | NA | 00-0036264 | 00-0037834 | Jordan Love | Brock Purdy | Matt LaFleur | Kyle Shanahan | NA | SFO01 | Levi’s Stadium |
2023_20_TB_DET | 2023 | DIV | 20 | 2024-01-21 | Sunday | 15:00 | TB | NA | DET | NA | Home | NA | NA | NA | 2024012101 | NA | NA | 202401210det | NA | NA | NA | 6 | 7 | 230 | -285 | 6.0 | -110 | -110 | 49.5 | -110 | -110 | 0 | dome | fieldturf | NA | NA | 00-0034855 | 00-0033106 | Baker Mayfield | Jared Goff | Todd Bowles | Dan Campbell | NA | DET00 | Ford Field |
2023_20_KC_BUF | 2023 | DIV | 20 | 2024-01-21 | Sunday | 18:30 | KC | NA | BUF | NA | Home | NA | NA | NA | 2024012102 | NA | NA | 202401210buf | NA | NA | NA | 8 | 6 | 120 | -142 | 2.5 | -105 | -115 | 45.5 | -110 | -110 | 0 | outdoors | NA | NA | 00-0033873 | 00-0034857 | Patrick Mahomes | Josh Allen | Andy Reid | Sean McDermott | NA | BUF00 | New Era Field |
This pulls game information from the games.rds file (equivalent to the games.csv file) from Lee Sharpe’s NFL Data Github
Find Division Ranks
This functions computes division ranks based on a data frame containing game results of one or more NFL seasons. So let’s load some game data first (this example uses the game data of the 2012 and 2019 seasons):
games <- nflseedR::load_sharpe_games() %>%
dplyr::filter(season %in% c(2012, 2019)) %>%
dplyr::select(sim = season, game_type, week, away_team, home_team, result)
dplyr::glimpse(games)
#> Rows: 534
#> Columns: 6
#> $ sim <int> 2012, 2012, 2012, 2012, 2012, 2012, 2012, 2012, 2012, 2012, …
#> $ game_type <chr> "REG", "REG", "REG", "REG", "REG", "REG", "REG", "REG", "REG…
#> $ week <int> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, …
#> $ away_team <chr> "DAL", "IND", "PHI", "STL", "MIA", "ATL", "JAX", "WAS", "BUF…
#> $ home_team <chr> "NYG", "CHI", "CLE", "DET", "HOU", "KC", "MIN", "NO", "NYJ",…
#> $ result <int> -7, 20, -1, 4, 20, -16, 3, -8, 20, -21, 4, -8, 6, 12, 31, -8…
Please note the required column names:
sim
: A simulation ID. Normally 1 - n simulated seasons or (like in this case) just the year.game_type
: One of ‘REG’, ‘WC’, ‘DIV’, ‘CON’, ‘SB’ indicating if a game was a regular season game or one of the playoff rounds.week
: The week of the corresponding NFL season.away_team
: Team abbreviation of the away team.home_team
: Team abbreviation of the home team.result
: Equals home score - away score.
Now the games data frame can be used to compute the division ranks
(the parameter .debug
is set to TRUE
to show
what the function is doing).
div_standings <- nflseedR::compute_division_ranks(games, .debug = TRUE)
#> ℹ 19:16:07 | Calculating team data
#> ℹ 19:16:07 | Calculating head to head
#> ℹ 19:16:07 | Calculating division rank #1
#> ℹ 19:16:07 | DIV (2): Head-to-head
#> ℹ 19:16:07 | DIV (2): Division Record
#> ℹ 19:16:07 | Calculating division rank #2
#> ℹ 19:16:07 | DIV (3): Head-to-head
#> ℹ 19:16:07 | DIV (3): Division Record
#> ℹ 19:16:07 | DIV (3): Common Record
#> ℹ 19:16:07 | DIV (2): Head-to-head
#> ℹ 19:16:07 | DIV (2): Division Record
#> ℹ 19:16:07 | DIV (2): Common Record
#> ℹ 19:16:07 | DIV (2): Conference Record
#> ℹ 19:16:07 | Calculating division rank #3
#> ℹ 19:16:07 | DIV (2): Head-to-head
#> ℹ 19:16:07 | DIV (2): Division Record
#> ℹ 19:16:07 | DIV (2): Common Record
#> ℹ 19:16:07 | Calculating division rank #4
dplyr::glimpse(div_standings)
#> List of 2
#> $ standings: tibble [64 × 16] (S3: tbl_df/tbl/data.frame)
#> ..$ sim : int [1:64] 2012 2012 2012 2012 2012 2012 2012 2012 2012 2012 ...
#> ..$ conf : chr [1:64] "AFC" "AFC" "AFC" "AFC" ...
#> ..$ division : chr [1:64] "AFC East" "AFC East" "AFC East" "AFC East" ...
#> ..$ team : chr [1:64] "BUF" "MIA" "NE" "NYJ" ...
#> ..$ games : int [1:64] 16 16 16 16 16 16 16 16 16 16 ...
#> ..$ wins : num [1:64] 6 7 12 6 10 10 5 8 12 11 ...
#> ..$ true_wins : int [1:64] 6 7 12 6 10 10 5 8 12 11 ...
#> ..$ losses : int [1:64] 10 9 4 10 6 6 11 8 4 5 ...
#> ..$ ties : int [1:64] 0 0 0 0 0 0 0 0 0 0 ...
#> ..$ win_pct : num [1:64] 0.375 0.438 0.75 0.375 0.625 ...
#> ..$ div_pct : num [1:64] 0.333 0.333 1 0.333 0.667 ...
#> ..$ conf_pct : num [1:64] 0.417 0.417 0.917 0.333 0.667 ...
#> ..$ sov : num [1:64] 0.281 0.415 0.466 0.401 0.438 ...
#> ..$ sos : num [1:64] 0.48 0.5 0.496 0.512 0.496 ...
#> ..$ div_rank : num [1:64] 4 2 1 3 1 2 4 3 1 2 ...
#> ..$ max_reg_week: int [1:64] 17 17 17 17 17 17 17 17 17 17 ...
#> $ h2h : tibble [2,048 × 6] (S3: tbl_df/tbl/data.frame)
#> ..$ sim : int [1:2048] 2012 2012 2012 2012 2012 2012 2012 2012 2012 2012 ...
#> ..$ team : chr [1:2048] "ARI" "ARI" "ARI" "ARI" ...
#> ..$ opp : chr [1:2048] "ARI" "ATL" "BAL" "BUF" ...
#> ..$ h2h_games : int [1:2048] 0 1 0 1 0 1 0 0 0 0 ...
#> ..$ h2h_wins : num [1:2048] 0 0 0 0 0 0 0 0 0 0 ...
#> ..$ h2h_played: num [1:2048] 0 1 0 1 0 1 0 0 0 0 ...
Please note that the function outputs a list of data frames, the
actual division standings as well as a data frame named
h2h
. The latter is an important input in the other
functions (as it is used to break head-to-head ties) and can only be
computed with compute_division_ranks()
.
So here is the resulting division standings data frame for the 2012 season
div_standings %>%
purrr::pluck("standings") %>%
dplyr::filter(sim == 2012) %>%
dplyr::select(division:div_rank) %>%
knitr::kable()
division | team | games | wins | true_wins | losses | ties | win_pct | div_pct | conf_pct | sov | sos | div_rank |
---|---|---|---|---|---|---|---|---|---|---|---|---|
AFC East | BUF | 16 | 6.0 | 6 | 10 | 0 | 0.375 | 0.333 | 0.417 | 0.281 | 0.480 | 4 |
AFC East | MIA | 16 | 7.0 | 7 | 9 | 0 | 0.438 | 0.333 | 0.417 | 0.415 | 0.500 | 2 |
AFC East | NE | 16 | 12.0 | 12 | 4 | 0 | 0.750 | 1.000 | 0.917 | 0.466 | 0.496 | 1 |
AFC East | NYJ | 16 | 6.0 | 6 | 10 | 0 | 0.375 | 0.333 | 0.333 | 0.401 | 0.512 | 3 |
AFC North | BAL | 16 | 10.0 | 10 | 6 | 0 | 0.625 | 0.667 | 0.667 | 0.438 | 0.496 | 1 |
AFC North | CIN | 16 | 10.0 | 10 | 6 | 0 | 0.625 | 0.500 | 0.583 | 0.381 | 0.438 | 2 |
AFC North | CLE | 16 | 5.0 | 5 | 11 | 0 | 0.312 | 0.333 | 0.417 | 0.388 | 0.508 | 4 |
AFC North | PIT | 16 | 8.0 | 8 | 8 | 0 | 0.500 | 0.500 | 0.417 | 0.438 | 0.465 | 3 |
AFC South | HOU | 16 | 12.0 | 12 | 4 | 0 | 0.750 | 0.833 | 0.833 | 0.432 | 0.496 | 1 |
AFC South | IND | 16 | 11.0 | 11 | 5 | 0 | 0.688 | 0.667 | 0.667 | 0.403 | 0.441 | 2 |
AFC South | JAX | 16 | 2.0 | 2 | 14 | 0 | 0.125 | 0.333 | 0.167 | 0.531 | 0.539 | 4 |
AFC South | TEN | 16 | 6.0 | 6 | 10 | 0 | 0.375 | 0.167 | 0.417 | 0.344 | 0.512 | 3 |
AFC West | DEN | 16 | 13.0 | 13 | 3 | 0 | 0.812 | 1.000 | 0.833 | 0.385 | 0.457 | 1 |
AFC West | KC | 16 | 2.0 | 2 | 14 | 0 | 0.125 | 0.000 | 0.000 | 0.438 | 0.516 | 4 |
AFC West | OAK | 16 | 4.0 | 4 | 12 | 0 | 0.250 | 0.333 | 0.333 | 0.219 | 0.469 | 3 |
AFC West | SD | 16 | 7.0 | 7 | 9 | 0 | 0.438 | 0.667 | 0.583 | 0.286 | 0.457 | 2 |
NFC East | DAL | 16 | 8.0 | 8 | 8 | 0 | 0.500 | 0.500 | 0.417 | 0.422 | 0.523 | 3 |
NFC East | NYG | 16 | 9.0 | 9 | 7 | 0 | 0.562 | 0.500 | 0.667 | 0.490 | 0.521 | 2 |
NFC East | PHI | 16 | 4.0 | 4 | 12 | 0 | 0.250 | 0.167 | 0.167 | 0.484 | 0.508 | 4 |
NFC East | WAS | 16 | 10.0 | 10 | 6 | 0 | 0.625 | 0.833 | 0.667 | 0.450 | 0.494 | 1 |
NFC North | CHI | 16 | 10.0 | 10 | 6 | 0 | 0.625 | 0.500 | 0.583 | 0.403 | 0.512 | 3 |
NFC North | DET | 16 | 4.0 | 4 | 12 | 0 | 0.250 | 0.000 | 0.250 | 0.383 | 0.566 | 4 |
NFC North | GB | 16 | 11.0 | 11 | 5 | 0 | 0.688 | 0.833 | 0.667 | 0.440 | 0.508 | 1 |
NFC North | MIN | 16 | 10.0 | 10 | 6 | 0 | 0.625 | 0.667 | 0.583 | 0.456 | 0.520 | 2 |
NFC South | ATL | 16 | 13.0 | 13 | 3 | 0 | 0.812 | 0.500 | 0.750 | 0.418 | 0.422 | 1 |
NFC South | CAR | 16 | 7.0 | 7 | 9 | 0 | 0.438 | 0.500 | 0.417 | 0.464 | 0.516 | 2 |
NFC South | NO | 16 | 7.0 | 7 | 9 | 0 | 0.438 | 0.500 | 0.417 | 0.446 | 0.521 | 3 |
NFC South | TB | 16 | 7.0 | 7 | 9 | 0 | 0.438 | 0.500 | 0.333 | 0.446 | 0.502 | 4 |
NFC West | ARI | 16 | 5.0 | 5 | 11 | 0 | 0.312 | 0.167 | 0.250 | 0.475 | 0.559 | 4 |
NFC West | SEA | 16 | 11.0 | 11 | 5 | 0 | 0.688 | 0.500 | 0.667 | 0.534 | 0.504 | 2 |
NFC West | SF | 16 | 11.5 | 11 | 4 | 1 | 0.719 | 0.583 | 0.625 | 0.477 | 0.504 | 1 |
NFC West | STL | 16 | 7.5 | 7 | 8 | 1 | 0.469 | 0.750 | 0.542 | 0.496 | 0.539 | 3 |
In that season the seconds division rank of the NFC South required a
three way tie-breaker between the Panthers, Saints and Bucs. It was
broken with the three-way Conference Record. This can be seen in the
above given console output: ...DIV (3): Common Record
for
the division rank number 2. The Bucs lost this tie-breaker with a 0.333
win percentage in the conference and the tie-breaking procedure goes on
with a 2-way head-to-head comparison.
Find Conference Seedings
This functions computes conference seedings based on the above
computed division standings data frame. For efficiency reasons the above
computed h2h
data frame has to be passed to the function.
The easiest way is to pass the list of data frames that is computed in
the first step so we can do this (please note the number of playoff
seeds):
seeds <- div_standings %>%
nflseedR::compute_conference_seeds(h2h = .$h2h, playoff_seeds = 6, .debug = TRUE)
#> ℹ 19:16:07 | Calculating seed #1
#> ℹ 19:16:07 | CONF (3): Head-to-head Sweep
#> ℹ 19:16:07 | Calculating seed #2
#> ℹ 19:16:07 | CONF (2): Head-to-head Sweep
#> ℹ 19:16:07 | CONF (2): Conference Record
#> ℹ 19:16:07 | Calculating seed #3
#> ℹ 19:16:08 | Calculating seed #4
#> ℹ 19:16:08 | Calculating seed #5
#> ℹ 19:16:08 | Calculating seed #6
#> ℹ 19:16:08 | CONF (2): Best-in-division reduction
dplyr::glimpse(seeds)
#> List of 2
#> $ standings: tibble [64 × 17] (S3: tbl_df/tbl/data.frame)
#> ..$ sim : int [1:64] 2012 2012 2012 2012 2012 2012 2012 2012 2012 2012 ...
#> ..$ conf : chr [1:64] "AFC" "AFC" "AFC" "AFC" ...
#> ..$ division : chr [1:64] "AFC East" "AFC East" "AFC East" "AFC East" ...
#> ..$ team : chr [1:64] "BUF" "MIA" "NE" "NYJ" ...
#> ..$ games : int [1:64] 16 16 16 16 16 16 16 16 16 16 ...
#> ..$ wins : num [1:64] 6 7 12 6 10 10 5 8 12 11 ...
#> ..$ true_wins: int [1:64] 6 7 12 6 10 10 5 8 12 11 ...
#> ..$ losses : int [1:64] 10 9 4 10 6 6 11 8 4 5 ...
#> ..$ ties : int [1:64] 0 0 0 0 0 0 0 0 0 0 ...
#> ..$ win_pct : num [1:64] 0.375 0.438 0.75 0.375 0.625 ...
#> ..$ div_pct : num [1:64] 0.333 0.333 1 0.333 0.667 ...
#> ..$ conf_pct : num [1:64] 0.417 0.417 0.917 0.333 0.667 ...
#> ..$ sov : num [1:64] 0.281 0.415 0.466 0.401 0.438 ...
#> ..$ sos : num [1:64] 0.48 0.5 0.496 0.512 0.496 ...
#> ..$ div_rank : num [1:64] 4 2 1 3 1 2 4 3 1 2 ...
#> ..$ seed : num [1:64] NA NA 2 NA 4 6 NA NA 3 5 ...
#> ..$ exit : num [1:64] 17 17 NA 17 NA NA 17 17 NA NA ...
#> $ h2h : tibble [2,048 × 6] (S3: tbl_df/tbl/data.frame)
#> ..$ sim : int [1:2048] 2012 2012 2012 2012 2012 2012 2012 2012 2012 2012 ...
#> ..$ team : chr [1:2048] "ARI" "ARI" "ARI" "ARI" ...
#> ..$ opp : chr [1:2048] "ARI" "ATL" "BAL" "BUF" ...
#> ..$ h2h_games : int [1:2048] 0 1 0 1 0 1 0 0 0 0 ...
#> ..$ h2h_wins : num [1:2048] 0 0 0 0 0 0 0 0 0 0 ...
#> ..$ h2h_played: num [1:2048] 0 1 0 1 0 1 0 0 0 0 ...
Just like compute_division_ranks()
, this function
returns a list of two data frames so we can use it within a pipe. The
resulting seeds for the 2012 season are given below.
seeds %>%
purrr::pluck("standings") %>%
dplyr::filter(sim == 2012) %>%
dplyr::select(division:seed) %>%
knitr::kable()
division | team | games | wins | true_wins | losses | ties | win_pct | div_pct | conf_pct | sov | sos | div_rank | seed |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
AFC East | BUF | 16 | 6.0 | 6 | 10 | 0 | 0.375 | 0.333 | 0.417 | 0.281 | 0.480 | 4 | NA |
AFC East | MIA | 16 | 7.0 | 7 | 9 | 0 | 0.438 | 0.333 | 0.417 | 0.415 | 0.500 | 2 | NA |
AFC East | NE | 16 | 12.0 | 12 | 4 | 0 | 0.750 | 1.000 | 0.917 | 0.466 | 0.496 | 1 | 2 |
AFC East | NYJ | 16 | 6.0 | 6 | 10 | 0 | 0.375 | 0.333 | 0.333 | 0.401 | 0.512 | 3 | NA |
AFC North | BAL | 16 | 10.0 | 10 | 6 | 0 | 0.625 | 0.667 | 0.667 | 0.438 | 0.496 | 1 | 4 |
AFC North | CIN | 16 | 10.0 | 10 | 6 | 0 | 0.625 | 0.500 | 0.583 | 0.381 | 0.438 | 2 | 6 |
AFC North | CLE | 16 | 5.0 | 5 | 11 | 0 | 0.312 | 0.333 | 0.417 | 0.388 | 0.508 | 4 | NA |
AFC North | PIT | 16 | 8.0 | 8 | 8 | 0 | 0.500 | 0.500 | 0.417 | 0.438 | 0.465 | 3 | NA |
AFC South | HOU | 16 | 12.0 | 12 | 4 | 0 | 0.750 | 0.833 | 0.833 | 0.432 | 0.496 | 1 | 3 |
AFC South | IND | 16 | 11.0 | 11 | 5 | 0 | 0.688 | 0.667 | 0.667 | 0.403 | 0.441 | 2 | 5 |
AFC South | JAX | 16 | 2.0 | 2 | 14 | 0 | 0.125 | 0.333 | 0.167 | 0.531 | 0.539 | 4 | NA |
AFC South | TEN | 16 | 6.0 | 6 | 10 | 0 | 0.375 | 0.167 | 0.417 | 0.344 | 0.512 | 3 | NA |
AFC West | DEN | 16 | 13.0 | 13 | 3 | 0 | 0.812 | 1.000 | 0.833 | 0.385 | 0.457 | 1 | 1 |
AFC West | KC | 16 | 2.0 | 2 | 14 | 0 | 0.125 | 0.000 | 0.000 | 0.438 | 0.516 | 4 | NA |
AFC West | OAK | 16 | 4.0 | 4 | 12 | 0 | 0.250 | 0.333 | 0.333 | 0.219 | 0.469 | 3 | NA |
AFC West | SD | 16 | 7.0 | 7 | 9 | 0 | 0.438 | 0.667 | 0.583 | 0.286 | 0.457 | 2 | NA |
NFC East | DAL | 16 | 8.0 | 8 | 8 | 0 | 0.500 | 0.500 | 0.417 | 0.422 | 0.523 | 3 | NA |
NFC East | NYG | 16 | 9.0 | 9 | 7 | 0 | 0.562 | 0.500 | 0.667 | 0.490 | 0.521 | 2 | NA |
NFC East | PHI | 16 | 4.0 | 4 | 12 | 0 | 0.250 | 0.167 | 0.167 | 0.484 | 0.508 | 4 | NA |
NFC East | WAS | 16 | 10.0 | 10 | 6 | 0 | 0.625 | 0.833 | 0.667 | 0.450 | 0.494 | 1 | 4 |
NFC North | CHI | 16 | 10.0 | 10 | 6 | 0 | 0.625 | 0.500 | 0.583 | 0.403 | 0.512 | 3 | NA |
NFC North | DET | 16 | 4.0 | 4 | 12 | 0 | 0.250 | 0.000 | 0.250 | 0.383 | 0.566 | 4 | NA |
NFC North | GB | 16 | 11.0 | 11 | 5 | 0 | 0.688 | 0.833 | 0.667 | 0.440 | 0.508 | 1 | 3 |
NFC North | MIN | 16 | 10.0 | 10 | 6 | 0 | 0.625 | 0.667 | 0.583 | 0.456 | 0.520 | 2 | 6 |
NFC South | ATL | 16 | 13.0 | 13 | 3 | 0 | 0.812 | 0.500 | 0.750 | 0.418 | 0.422 | 1 | 1 |
NFC South | CAR | 16 | 7.0 | 7 | 9 | 0 | 0.438 | 0.500 | 0.417 | 0.464 | 0.516 | 2 | NA |
NFC South | NO | 16 | 7.0 | 7 | 9 | 0 | 0.438 | 0.500 | 0.417 | 0.446 | 0.521 | 3 | NA |
NFC South | TB | 16 | 7.0 | 7 | 9 | 0 | 0.438 | 0.500 | 0.333 | 0.446 | 0.502 | 4 | NA |
NFC West | ARI | 16 | 5.0 | 5 | 11 | 0 | 0.312 | 0.167 | 0.250 | 0.475 | 0.559 | 4 | NA |
NFC West | SEA | 16 | 11.0 | 11 | 5 | 0 | 0.688 | 0.500 | 0.667 | 0.534 | 0.504 | 2 | 5 |
NFC West | SF | 16 | 11.5 | 11 | 4 | 1 | 0.719 | 0.583 | 0.625 | 0.477 | 0.504 | 1 | 2 |
NFC West | STL | 16 | 7.5 | 7 | 8 | 1 | 0.469 | 0.750 | 0.542 | 0.496 | 0.539 | 3 | NA |
Find Draft Order
This function computes the draft order based on the playoff outcome
and the regular season games. It requires all playoff results in the
games
data frame and the game_type
of the
Super Bowl has to be "SB"
. For efficiency reasons the above
computed h2h
data frame has to be passed to the function as
well. The easiest way is to pass the list of data frames that is
computed in the above steps:
draft <- seeds %>%
nflseedR::compute_draft_order(games = games, h2h = .$h2h, .debug = TRUE)
#> ℹ 19:16:08 | Calculating draft order #32
#> ℹ 19:16:08 | Calculating draft order #31
#> ℹ 19:16:08 | Calculating draft order #30
#> ℹ 19:16:08 | Calculating draft order #29
#> ℹ 19:16:08 | Calculating draft order #28
#> ℹ 19:16:08 | Calculating draft order #27
#> ℹ 19:16:08 | Calculating draft order #26
#> ℹ 19:16:08 | Calculating draft order #25
#> ℹ 19:16:08 | Calculating draft order #24
#> ℹ 19:16:08 | Calculating draft order #23
#> ℹ 19:16:08 | Calculating draft order #22
#> ℹ 19:16:08 | Calculating draft order #21
#> ℹ 19:16:08 | Calculating draft order #20
#> ℹ 19:16:08 | Calculating draft order #19
#> ℹ 19:16:08 | Calculating draft order #18
#> ℹ 19:16:08 | Calculating draft order #17
#> ℹ 19:16:08 | Calculating draft order #16
#> ℹ 19:16:08 | Calculating draft order #15
#> ℹ 19:16:08 | Calculating draft order #14
#> ℹ 19:16:08 | Calculating draft order #13
#> ℹ 19:16:08 | Calculating draft order #12
#> ℹ 19:16:08 | Calculating draft order #11
#> ℹ 19:16:08 | Calculating draft order #10
#> ℹ 19:16:08 | DRAFT: Divisional Rank
#> ℹ 19:16:08 | DRAFT: Conference Rank
#> ℹ 19:16:08 | CONF (2): Best-in-division reduction
#> ℹ 19:16:08 | CONF (2): Head-to-head Sweep
#> ℹ 19:16:08 | Calculating draft order #9
#> ℹ 19:16:08 | Calculating draft order #8
#> ℹ 19:16:09 | Calculating draft order #7
#> ℹ 19:16:09 | Calculating draft order #6
#> ℹ 19:16:09 | Calculating draft order #5
#> ℹ 19:16:09 | Calculating draft order #4
#> ℹ 19:16:09 | Calculating draft order #3
#> ℹ 19:16:09 | Calculating draft order #2
#> ℹ 19:16:09 | Calculating draft order #1
dplyr::glimpse(draft)
#> Rows: 64
#> Columns: 18
#> $ sim <int> 2012, 2012, 2012, 2012, 2012, 2012, 2012, 2012, 2012, 2012…
#> $ team <chr> "BUF", "MIA", "NE", "NYJ", "BAL", "CIN", "CLE", "PIT", "HO…
#> $ conf <chr> "AFC", "AFC", "AFC", "AFC", "AFC", "AFC", "AFC", "AFC", "A…
#> $ division <chr> "AFC East", "AFC East", "AFC East", "AFC East", "AFC North…
#> $ games <int> 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16…
#> $ wins <dbl> 6, 7, 12, 6, 10, 10, 5, 8, 12, 11, 2, 6, 13, 2, 4, 7, 8, 9…
#> $ true_wins <int> 6, 7, 12, 6, 10, 10, 5, 8, 12, 11, 2, 6, 13, 2, 4, 7, 8, 9…
#> $ losses <int> 10, 9, 4, 10, 6, 6, 11, 8, 4, 5, 14, 10, 3, 14, 12, 9, 8, …
#> $ ties <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0…
#> $ win_pct <dbl> 0.375, 0.438, 0.750, 0.375, 0.625, 0.625, 0.312, 0.500, 0.…
#> $ div_pct <dbl> 0.333, 0.333, 1.000, 0.333, 0.667, 0.500, 0.333, 0.500, 0.…
#> $ conf_pct <dbl> 0.417, 0.417, 0.917, 0.333, 0.667, 0.583, 0.417, 0.417, 0.…
#> $ sov <dbl> 0.281, 0.415, 0.466, 0.401, 0.438, 0.381, 0.388, 0.438, 0.…
#> $ sos <dbl> 0.480, 0.500, 0.496, 0.512, 0.496, 0.438, 0.508, 0.465, 0.…
#> $ div_rank <dbl> 4, 2, 1, 3, 1, 2, 4, 3, 1, 2, 4, 3, 1, 4, 3, 2, 3, 2, 4, 1…
#> $ seed <dbl> NA, NA, 2, NA, 4, 6, NA, NA, 3, 5, NA, NA, 1, NA, NA, NA, …
#> $ exit <dbl> 17, 17, 20, 17, 22, 18, 17, 17, 19, 18, 17, 17, 19, 17, 17…
#> $ draft_order <dbl> 8, 12, 29, 9, 32, 21, 6, 17, 27, 24, 2, 10, 28, 1, 3, 11, …
As this is the final step, the function
compute_draft_order
does not output h2h
again.
Instead it directly outputs the final standings including the draft
order and the variable exit
which indicates the week number
of each team’s final game (the Super Bowl Winner’s exit
equals 22):
division | games | wins | true_wins | losses | ties | win_pct | div_pct | conf_pct | sov | sos | div_rank | seed | exit | draft_order |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
AFC East | 16 | 6.0 | 6 | 10 | 0 | 0.375 | 0.333 | 0.417 | 0.281 | 0.480 | 4 | NA | 17 | 8 |
AFC East | 16 | 7.0 | 7 | 9 | 0 | 0.438 | 0.333 | 0.417 | 0.415 | 0.500 | 2 | NA | 17 | 12 |
AFC East | 16 | 12.0 | 12 | 4 | 0 | 0.750 | 1.000 | 0.917 | 0.466 | 0.496 | 1 | 2 | 20 | 29 |
AFC East | 16 | 6.0 | 6 | 10 | 0 | 0.375 | 0.333 | 0.333 | 0.401 | 0.512 | 3 | NA | 17 | 9 |
AFC North | 16 | 10.0 | 10 | 6 | 0 | 0.625 | 0.667 | 0.667 | 0.438 | 0.496 | 1 | 4 | 22 | 32 |
AFC North | 16 | 10.0 | 10 | 6 | 0 | 0.625 | 0.500 | 0.583 | 0.381 | 0.438 | 2 | 6 | 18 | 21 |
AFC North | 16 | 5.0 | 5 | 11 | 0 | 0.312 | 0.333 | 0.417 | 0.388 | 0.508 | 4 | NA | 17 | 6 |
AFC North | 16 | 8.0 | 8 | 8 | 0 | 0.500 | 0.500 | 0.417 | 0.438 | 0.465 | 3 | NA | 17 | 17 |
AFC South | 16 | 12.0 | 12 | 4 | 0 | 0.750 | 0.833 | 0.833 | 0.432 | 0.496 | 1 | 3 | 19 | 27 |
AFC South | 16 | 11.0 | 11 | 5 | 0 | 0.688 | 0.667 | 0.667 | 0.403 | 0.441 | 2 | 5 | 18 | 24 |
AFC South | 16 | 2.0 | 2 | 14 | 0 | 0.125 | 0.333 | 0.167 | 0.531 | 0.539 | 4 | NA | 17 | 2 |
AFC South | 16 | 6.0 | 6 | 10 | 0 | 0.375 | 0.167 | 0.417 | 0.344 | 0.512 | 3 | NA | 17 | 10 |
AFC West | 16 | 13.0 | 13 | 3 | 0 | 0.812 | 1.000 | 0.833 | 0.385 | 0.457 | 1 | 1 | 19 | 28 |
AFC West | 16 | 2.0 | 2 | 14 | 0 | 0.125 | 0.000 | 0.000 | 0.438 | 0.516 | 4 | NA | 17 | 1 |
AFC West | 16 | 4.0 | 4 | 12 | 0 | 0.250 | 0.333 | 0.333 | 0.219 | 0.469 | 3 | NA | 17 | 3 |
AFC West | 16 | 7.0 | 7 | 9 | 0 | 0.438 | 0.667 | 0.583 | 0.286 | 0.457 | 2 | NA | 17 | 11 |
NFC East | 16 | 8.0 | 8 | 8 | 0 | 0.500 | 0.500 | 0.417 | 0.422 | 0.523 | 3 | NA | 17 | 18 |
NFC East | 16 | 9.0 | 9 | 7 | 0 | 0.562 | 0.500 | 0.667 | 0.490 | 0.521 | 2 | NA | 17 | 19 |
NFC East | 16 | 4.0 | 4 | 12 | 0 | 0.250 | 0.167 | 0.167 | 0.484 | 0.508 | 4 | NA | 17 | 4 |
NFC East | 16 | 10.0 | 10 | 6 | 0 | 0.625 | 0.833 | 0.667 | 0.450 | 0.494 | 1 | 4 | 18 | 22 |
NFC North | 16 | 10.0 | 10 | 6 | 0 | 0.625 | 0.500 | 0.583 | 0.403 | 0.512 | 3 | NA | 17 | 20 |
NFC North | 16 | 4.0 | 4 | 12 | 0 | 0.250 | 0.000 | 0.250 | 0.383 | 0.566 | 4 | NA | 17 | 5 |
NFC North | 16 | 11.0 | 11 | 5 | 0 | 0.688 | 0.833 | 0.667 | 0.440 | 0.508 | 1 | 3 | 19 | 26 |
NFC North | 16 | 10.0 | 10 | 6 | 0 | 0.625 | 0.667 | 0.583 | 0.456 | 0.520 | 2 | 6 | 18 | 23 |
NFC South | 16 | 13.0 | 13 | 3 | 0 | 0.812 | 0.500 | 0.750 | 0.418 | 0.422 | 1 | 1 | 20 | 30 |
NFC South | 16 | 7.0 | 7 | 9 | 0 | 0.438 | 0.500 | 0.417 | 0.464 | 0.516 | 2 | NA | 17 | 14 |
NFC South | 16 | 7.0 | 7 | 9 | 0 | 0.438 | 0.500 | 0.417 | 0.446 | 0.521 | 3 | NA | 17 | 15 |
NFC South | 16 | 7.0 | 7 | 9 | 0 | 0.438 | 0.500 | 0.333 | 0.446 | 0.502 | 4 | NA | 17 | 13 |
NFC West | 16 | 5.0 | 5 | 11 | 0 | 0.312 | 0.167 | 0.250 | 0.475 | 0.559 | 4 | NA | 17 | 7 |
NFC West | 16 | 11.0 | 11 | 5 | 0 | 0.688 | 0.500 | 0.667 | 0.534 | 0.504 | 2 | 5 | 19 | 25 |
NFC West | 16 | 11.5 | 11 | 4 | 1 | 0.719 | 0.583 | 0.625 | 0.477 | 0.504 | 1 | 2 | 21 | 31 |
NFC West | 16 | 7.5 | 7 | 8 | 1 | 0.469 | 0.750 | 0.542 | 0.496 | 0.539 | 3 | NA | 17 | 16 |