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:

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):

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):

library(nflseedR)
library(dplyr, warn.conflicts = FALSE)
options(digits = 3)
options(warn = -1)

Load Sharpe Games

games <- nflseedR::load_sharpe_games()
games %>% utils::tail(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 espn 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
2020_17_LV_DEN 2020 REG 17 2021-01-03 Sunday 16:25 LV 32 DEN 31 Home -1 63 0 2021010311 401220211 8 7 -144 130 -2.5 -115 104 50.5 -103 -108 1 outdoors grass 53 10 00-0031280 00-0035704 Derek Carr Drew Lock Jon Gruden Vic Fangio Scott Novak DEN00 Empower Field at Mile High
2020_17_TEN_HOU 2020 REG 17 2021-01-03 Sunday 16:25 TEN 41 HOU 38 Home -3 79 0 2021010312 401220180 7 7 -301 259 -7.0 101 -111 55.5 -113 101 1 closed grass NA NA 00-0029701 00-0033537 Ryan Tannehill Deshaun Watson Mike Vrabel Romeo Crennel Shawn Hochuli HOU00 NRG Stadium
2020_17_JAX_IND 2020 REG 17 2021-01-03 Sunday 16:25 JAX 14 IND 28 Home 14 42 0 2021010313 401220187 7 7 906 -1350 15.5 104 -115 48.0 -112 100 1 closed fieldturf NA NA 00-0030520 00-0022942 Mike Glennon Philip Rivers Doug Marrone Frank Reich Shawn Smith IND00 Lucas Oil Stadium
2020_17_LAC_KC 2020 REG 17 2021-01-03 Sunday 16:25 LAC 38 KC 21 Home -17 59 0 2021010306 401220220 7 7 -282 244 -7.0 106 -117 43.0 -103 -108 1 outdoors astroturf 35 6 00-0036355 00-0026197 Justin Herbert Chad Henne Anthony Lynn Andy Reid Clete Blakeman KAN00 Arrowhead Stadium
2020_17_ARI_LA 2020 REG 17 2021-01-03 Sunday 16:25 ARI 7 LA 18 Home 11 25 0 2021010314 401220344 8 7 113 -125 1.0 105 -116 42.0 -107 -104 1 dome matrixturf NA NA 00-0035752 00-0034899 Kyler Murray John Wolford Kliff Kingsbury Sean McVay Carl Cheffers LAX01 SoFi Stadium
2020_17_SEA_SF 2020 REG 17 2021-01-03 Sunday 16:25 SEA 26 SF 23 Neutral -3 49 0 2021010315 401220354 7 8 -310 266 -7.0 101 -112 45.0 -113 102 1 closed grass NA NA 00-0029263 00-0033936 Russell Wilson C.J. Beathard Pete Carroll Kyle Shanahan Tony Corrente PHO00 State Farm Stadium
2020_17_WAS_PHI 2020 REG 17 2021-01-03 Sunday 20:20 WAS 20 PHI 14 Home -6 34 0 2021010309 401220260 7 7 -283 245 -6.5 -109 -101 43.5 101 -112 1 outdoors grass 38 10 00-0023436 00-0036389 Alex Smith Jalen Hurts Ron Rivera Doug Pederson Ronald Torbert PHI00 Lincoln Financial Field
2020_18_IND_BUF 2020 WC 18 2021-01-09 Saturday 13:05 IND 24 BUF 27 Home 3 51 0 2021010900 401220393 6 6 277 -325 7.0 -118 107 50.5 -106 -105 0 outdoors astroturf 34 6 00-0022942 00-0034857 Philip Rivers Josh Allen Frank Reich Sean McDermott Brad Allen BUF00 New Era Field
2020_18_LA_SEA 2020 WC 18 2021-01-09 Saturday 16:40 LA 30 SEA 20 Home -10 50 0 2021010901 401220372 6 6 154 -172 3.0 102 -113 42.0 -101 -111 1 outdoors fieldturf 39 1 00-0034899 00-0029263 John Wolford Russell Wilson Sean McVay Pete Carroll John Hussey SEA00 Lumen Field
2020_18_TB_WAS 2020 WC 18 2021-01-09 Saturday 20:15 TB 31 WAS 23 Home -8 54 0 2021010902 401220371 6 6 -456 373 -10.0 -101 -109 45.0 -104 -107 0 outdoors grass 40 10 00-0019596 00-0031800 Tom Brady Taylor Heinicke Bruce Arians Ron Rivera Scott Novak WAS00 FedExField
2020_18_BAL_TEN 2020 WC 18 2021-01-10 Sunday 13:05 BAL 20 TEN 13 Home -7 33 0 2021011000 401220396 7 7 -182 163 -3.5 -103 -107 53.0 100 -112 0 outdoors grass 33 1 00-0034796 00-0029701 Lamar Jackson Ryan Tannehill John Harbaugh Mike Vrabel Jerome Boger NAS00 Nissan Stadium
2020_18_CHI_NO 2020 WC 18 2021-01-10 Sunday 16:40 CHI 9 NO 21 Home 12 30 0 2021011001 401220395 7 7 443 -558 11.0 102 -113 48.0 -109 -102 0 dome astroturf NA NA 00-0033869 00-0020531 Mitch Trubisky Drew Brees Matt Nagy Sean Payton Alex Kemp NOR00 Mercedes-Benz Superdome
2020_18_CLE_PIT 2020 WC 18 2021-01-10 Sunday 20:15 CLE 48 PIT 37 Home -11 85 0 2021011002 401220394 7 7 210 -239 5.0 -100 -110 47.5 -110 -101 1 outdoors grass 34 1 00-0034855 00-0022924 Baker Mayfield Ben Roethlisberger Kevin Stefanski Mike Tomlin Shawn Smith PIT00 Heinz Field
2020_19_LA_GB 2020 DIV 19 2021-01-16 Saturday 16:35 LA 18 GB 32 Home 14 50 0 2021011600 401220398 7 13 296 -351 7.0 -109 -101 45.0 -107 -105 0 outdoors grass 35 13 00-0033106 00-0023459 Jared Goff Aaron Rodgers Sean McVay Matt LaFleur Ronald Torbert GNB00 Lambeau Field
2020_19_BAL_BUF 2020 DIV 19 2021-01-16 Saturday 20:15 BAL 3 BUF 17 Home 14 20 0 2021011601 401220397 6 7 124 -137 2.5 103 -114 50.0 -108 -103 0 outdoors astroturf 34 13 00-0034796 00-0034857 Lamar Jackson Josh Allen John Harbaugh Sean McDermott Carl Cheffers BUF00 New Era Field
2020_19_CLE_KC 2020 DIV 19 2021-01-17 Sunday 15:05 CLE 17 KC 22 Home 5 39 0 2021011700 401220400 7 14 316 -376 7.5 -105 -105 55.5 -106 -105 0 outdoors astroturf 40 13 00-0034855 00-0033873 Baker Mayfield Patrick Mahomes Kevin Stefanski Andy Reid Clay Martin KAN00 Arrowhead Stadium
2020_19_TB_NO 2020 DIV 19 2021-01-17 Sunday 18:40 TB 30 NO 20 Home -10 50 0 2021011701 401220399 8 7 120 -133 2.5 -104 -106 53.0 -108 -103 1 dome astroturf NA NA 00-0019596 00-0020531 Tom Brady Drew Brees Bruce Arians Sean Payton Shawn Hochuli NOR00 Mercedes-Benz Superdome
2020_20_TB_GB 2020 CON 20 2021-01-24 Sunday 15:05 TB 31 GB 26 Home -5 57 0 2021012400 401220402 7 8 157 -176 3.0 108 -119 53.0 -102 -109 0 outdoors grass 29 10 00-0019596 00-0023459 Tom Brady Aaron Rodgers Bruce Arians Matt LaFleur Clete Blakeman GNB00 Lambeau Field
2020_20_BUF_KC 2020 CON 20 2021-01-24 Sunday 18:40 BUF 24 KC 38 Home 14 62 0 2021012401 401220401 8 7 142 -158 3.0 -108 -102 54.5 102 -114 0 outdoors astroturf 40 7 00-0034857 00-0033873 Josh Allen Patrick Mahomes Sean McDermott Andy Reid Bill Vinovich KAN00 Arrowhead Stadium
2020_21_KC_TB 2020 SB 21 2021-02-07 Sunday 18:30 KC 9 TB 31 Neutral 22 40 0 2021020700 401220403 14 14 -161 145 -3.0 -107 -103 55.0 -112 101 0 outdoors grass 63 9 00-0033873 00-0019596 Patrick Mahomes Tom Brady Andy Reid Bruce Arians Carl Cheffers TAM00 Raymond James Stadium

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)
#> ● 2021-04-17 18:35:58: Calculating team data
#> ● 2021-04-17 18:35:58: Calculating head to head
#> ● 2021-04-17 18:35:58: Calculating division rank #1
#> ● 2021-04-17 18:35:58: DIV (2): Head-to-head
#> ● 2021-04-17 18:35:58: DIV (2): Division Record
#> ● 2021-04-17 18:35:58: Calculating division rank #2
#> ● 2021-04-17 18:35:58: DIV (3): Head-to-head
#> ● 2021-04-17 18:35:59: DIV (3): Division Record
#> ● 2021-04-17 18:35:59: DIV (3): Common Record
#> ● 2021-04-17 18:35:59: DIV (2): Head-to-head
#> ● 2021-04-17 18:35:59: DIV (2): Division Record
#> ● 2021-04-17 18:35:59: DIV (2): Common Record
#> ● 2021-04-17 18:35:59: DIV (2): Conference Record
#> ● 2021-04-17 18:35:59: Calculating division rank #3
#> ● 2021-04-17 18:35:59: DIV (2): Head-to-head
#> ● 2021-04-17 18:35:59: DIV (2): Division Record
#> ● 2021-04-17 18:36:00: DIV (2): Common Record
#> ● 2021-04-17 18:36:00: Calculating division rank #4
dplyr::glimpse(div_standings)
#> List of 2
#>  $ standings: tibble[,14] [64 × 14] (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 ...
#>   ..$ 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[,6] [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 win_pct div_pct conf_pct sov sos div_rank
AFC East BUF 16 6.0 6 0.375 0.333 0.417 0.281 0.480 4
AFC East MIA 16 7.0 7 0.438 0.333 0.417 0.415 0.500 2
AFC East NE 16 12.0 12 0.750 1.000 0.917 0.466 0.496 1
AFC East NYJ 16 6.0 6 0.375 0.333 0.333 0.401 0.512 3
AFC North BAL 16 10.0 10 0.625 0.667 0.667 0.438 0.496 1
AFC North CIN 16 10.0 10 0.625 0.500 0.583 0.381 0.438 2
AFC North CLE 16 5.0 5 0.312 0.333 0.417 0.388 0.508 4
AFC North PIT 16 8.0 8 0.500 0.500 0.417 0.438 0.465 3
AFC South HOU 16 12.0 12 0.750 0.833 0.833 0.432 0.496 1
AFC South IND 16 11.0 11 0.688 0.667 0.667 0.403 0.441 2
AFC South JAX 16 2.0 2 0.125 0.333 0.167 0.531 0.539 4
AFC South TEN 16 6.0 6 0.375 0.167 0.417 0.344 0.512 3
AFC West DEN 16 13.0 13 0.812 1.000 0.833 0.385 0.457 1
AFC West KC 16 2.0 2 0.125 0.000 0.000 0.438 0.516 4
AFC West OAK 16 4.0 4 0.250 0.333 0.333 0.219 0.469 3
AFC West SD 16 7.0 7 0.438 0.667 0.583 0.286 0.457 2
NFC East DAL 16 8.0 8 0.500 0.500 0.417 0.422 0.523 3
NFC East NYG 16 9.0 9 0.562 0.500 0.667 0.490 0.521 2
NFC East PHI 16 4.0 4 0.250 0.167 0.167 0.484 0.508 4
NFC East WAS 16 10.0 10 0.625 0.833 0.667 0.450 0.494 1
NFC North CHI 16 10.0 10 0.625 0.500 0.583 0.403 0.512 3
NFC North DET 16 4.0 4 0.250 0.000 0.250 0.383 0.566 4
NFC North GB 16 11.0 11 0.688 0.833 0.667 0.440 0.508 1
NFC North MIN 16 10.0 10 0.625 0.667 0.583 0.456 0.520 2
NFC South ATL 16 13.0 13 0.812 0.500 0.750 0.418 0.422 1
NFC South CAR 16 7.0 7 0.438 0.500 0.417 0.464 0.516 2
NFC South NO 16 7.0 7 0.438 0.500 0.417 0.446 0.521 3
NFC South TB 16 7.0 7 0.438 0.500 0.333 0.446 0.502 4
NFC West ARI 16 5.0 5 0.312 0.167 0.250 0.475 0.559 4
NFC West SEA 16 11.0 11 0.688 0.500 0.667 0.534 0.504 2
NFC West SF 16 11.5 11 0.719 0.583 0.625 0.477 0.504 1
NFC West STL 16 7.5 7 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)
#> ● 2021-04-17 18:36:00: Calculating seed #1
#> ● 2021-04-17 18:36:00: CONF (3): Head-to-head Sweep
#> ● 2021-04-17 18:36:00: Calculating seed #2
#> ● 2021-04-17 18:36:00: CONF (2): Head-to-head Sweep
#> ● 2021-04-17 18:36:00: CONF (2): Conference Record
#> ● 2021-04-17 18:36:00: Calculating seed #3
#> ● 2021-04-17 18:36:01: Calculating seed #4
#> ● 2021-04-17 18:36:01: Calculating seed #5
#> ● 2021-04-17 18:36:01: Calculating seed #6
#> ● 2021-04-17 18:36:01: CONF (2): Best-in-division reduction
dplyr::glimpse(seeds)
#> List of 2
#>  $ standings: tibble[,15] [64 × 15] (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 ...
#>   ..$ 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[,6] [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 win_pct div_pct conf_pct sov sos div_rank seed
AFC East BUF 16 6.0 6 0.375 0.333 0.417 0.281 0.480 4 NA
AFC East MIA 16 7.0 7 0.438 0.333 0.417 0.415 0.500 2 NA
AFC East NE 16 12.0 12 0.750 1.000 0.917 0.466 0.496 1 2
AFC East NYJ 16 6.0 6 0.375 0.333 0.333 0.401 0.512 3 NA
AFC North BAL 16 10.0 10 0.625 0.667 0.667 0.438 0.496 1 4
AFC North CIN 16 10.0 10 0.625 0.500 0.583 0.381 0.438 2 6
AFC North CLE 16 5.0 5 0.312 0.333 0.417 0.388 0.508 4 NA
AFC North PIT 16 8.0 8 0.500 0.500 0.417 0.438 0.465 3 NA
AFC South HOU 16 12.0 12 0.750 0.833 0.833 0.432 0.496 1 3
AFC South IND 16 11.0 11 0.688 0.667 0.667 0.403 0.441 2 5
AFC South JAX 16 2.0 2 0.125 0.333 0.167 0.531 0.539 4 NA
AFC South TEN 16 6.0 6 0.375 0.167 0.417 0.344 0.512 3 NA
AFC West DEN 16 13.0 13 0.812 1.000 0.833 0.385 0.457 1 1
AFC West KC 16 2.0 2 0.125 0.000 0.000 0.438 0.516 4 NA
AFC West OAK 16 4.0 4 0.250 0.333 0.333 0.219 0.469 3 NA
AFC West SD 16 7.0 7 0.438 0.667 0.583 0.286 0.457 2 NA
NFC East DAL 16 8.0 8 0.500 0.500 0.417 0.422 0.523 3 NA
NFC East NYG 16 9.0 9 0.562 0.500 0.667 0.490 0.521 2 NA
NFC East PHI 16 4.0 4 0.250 0.167 0.167 0.484 0.508 4 NA
NFC East WAS 16 10.0 10 0.625 0.833 0.667 0.450 0.494 1 4
NFC North CHI 16 10.0 10 0.625 0.500 0.583 0.403 0.512 3 NA
NFC North DET 16 4.0 4 0.250 0.000 0.250 0.383 0.566 4 NA
NFC North GB 16 11.0 11 0.688 0.833 0.667 0.440 0.508 1 3
NFC North MIN 16 10.0 10 0.625 0.667 0.583 0.456 0.520 2 6
NFC South ATL 16 13.0 13 0.812 0.500 0.750 0.418 0.422 1 1
NFC South CAR 16 7.0 7 0.438 0.500 0.417 0.464 0.516 2 NA
NFC South NO 16 7.0 7 0.438 0.500 0.417 0.446 0.521 3 NA
NFC South TB 16 7.0 7 0.438 0.500 0.333 0.446 0.502 4 NA
NFC West ARI 16 5.0 5 0.312 0.167 0.250 0.475 0.559 4 NA
NFC West SEA 16 11.0 11 0.688 0.500 0.667 0.534 0.504 2 5
NFC West SF 16 11.5 11 0.719 0.583 0.625 0.477 0.504 1 2
NFC West STL 16 7.5 7 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)
#> ● 2021-04-17 18:36:02: Calculating draft order #32
#> ● 2021-04-17 18:36:02: Calculating draft order #31
#> ● 2021-04-17 18:36:02: Calculating draft order #30
#> ● 2021-04-17 18:36:02: Calculating draft order #29
#> ● 2021-04-17 18:36:02: Calculating draft order #28
#> ● 2021-04-17 18:36:02: Calculating draft order #27
#> ● 2021-04-17 18:36:02: Calculating draft order #26
#> ● 2021-04-17 18:36:02: Calculating draft order #25
#> ● 2021-04-17 18:36:02: Calculating draft order #24
#> ● 2021-04-17 18:36:02: Calculating draft order #23
#> ● 2021-04-17 18:36:02: Calculating draft order #22
#> ● 2021-04-17 18:36:02: Calculating draft order #21
#> ● 2021-04-17 18:36:02: Calculating draft order #20
#> ● 2021-04-17 18:36:02: Calculating draft order #19
#> ● 2021-04-17 18:36:02: Calculating draft order #18
#> ● 2021-04-17 18:36:02: Calculating draft order #17
#> ● 2021-04-17 18:36:02: Calculating draft order #16
#> ● 2021-04-17 18:36:02: Calculating draft order #15
#> ● 2021-04-17 18:36:02: Calculating draft order #14
#> ● 2021-04-17 18:36:02: Calculating draft order #13
#> ● 2021-04-17 18:36:02: Calculating draft order #12
#> ● 2021-04-17 18:36:02: Calculating draft order #11
#> ● 2021-04-17 18:36:02: Calculating draft order #10
#> ● 2021-04-17 18:36:02: DRAFT: Divisional Rank
#> ● 2021-04-17 18:36:02: DRAFT: Conference Rank
#> ● 2021-04-17 18:36:02: CONF (2): Best-in-division reduction
#> ● 2021-04-17 18:36:02: CONF (2): Head-to-head Sweep
#> ● 2021-04-17 18:36:03: Calculating draft order #9
#> ● 2021-04-17 18:36:03: Calculating draft order #8
#> ● 2021-04-17 18:36:03: Calculating draft order #7
#> ● 2021-04-17 18:36:03: Calculating draft order #6
#> ● 2021-04-17 18:36:03: Calculating draft order #5
#> ● 2021-04-17 18:36:03: Calculating draft order #4
#> ● 2021-04-17 18:36:03: Calculating draft order #3
#> ● 2021-04-17 18:36:03: Calculating draft order #2
#> ● 2021-04-17 18:36:03: Calculating draft order #1
dplyr::glimpse(draft)
#> Rows: 64
#> Columns: 16
#> $ 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…
#> $ 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):

draft %>% 
  dplyr::filter(sim == 2012) %>% 
  dplyr::select(division:draft_order) %>% 
  knitr::kable()
division games wins true_wins win_pct div_pct conf_pct sov sos div_rank seed exit draft_order
AFC East 16 6.0 6 0.375 0.333 0.417 0.281 0.480 4 NA 17 8
AFC East 16 7.0 7 0.438 0.333 0.417 0.415 0.500 2 NA 17 12
AFC East 16 12.0 12 0.750 1.000 0.917 0.466 0.496 1 2 20 29
AFC East 16 6.0 6 0.375 0.333 0.333 0.401 0.512 3 NA 17 9
AFC North 16 10.0 10 0.625 0.667 0.667 0.438 0.496 1 4 22 32
AFC North 16 10.0 10 0.625 0.500 0.583 0.381 0.438 2 6 18 21
AFC North 16 5.0 5 0.312 0.333 0.417 0.388 0.508 4 NA 17 6
AFC North 16 8.0 8 0.500 0.500 0.417 0.438 0.465 3 NA 17 17
AFC South 16 12.0 12 0.750 0.833 0.833 0.432 0.496 1 3 19 27
AFC South 16 11.0 11 0.688 0.667 0.667 0.403 0.441 2 5 18 24
AFC South 16 2.0 2 0.125 0.333 0.167 0.531 0.539 4 NA 17 2
AFC South 16 6.0 6 0.375 0.167 0.417 0.344 0.512 3 NA 17 10
AFC West 16 13.0 13 0.812 1.000 0.833 0.385 0.457 1 1 19 28
AFC West 16 2.0 2 0.125 0.000 0.000 0.438 0.516 4 NA 17 1
AFC West 16 4.0 4 0.250 0.333 0.333 0.219 0.469 3 NA 17 3
AFC West 16 7.0 7 0.438 0.667 0.583 0.286 0.457 2 NA 17 11
NFC East 16 8.0 8 0.500 0.500 0.417 0.422 0.523 3 NA 17 18
NFC East 16 9.0 9 0.562 0.500 0.667 0.490 0.521 2 NA 17 19
NFC East 16 4.0 4 0.250 0.167 0.167 0.484 0.508 4 NA 17 4
NFC East 16 10.0 10 0.625 0.833 0.667 0.450 0.494 1 4 18 22
NFC North 16 10.0 10 0.625 0.500 0.583 0.403 0.512 3 NA 17 20
NFC North 16 4.0 4 0.250 0.000 0.250 0.383 0.566 4 NA 17 5
NFC North 16 11.0 11 0.688 0.833 0.667 0.440 0.508 1 3 19 26
NFC North 16 10.0 10 0.625 0.667 0.583 0.456 0.520 2 6 18 23
NFC South 16 13.0 13 0.812 0.500 0.750 0.418 0.422 1 1 20 30
NFC South 16 7.0 7 0.438 0.500 0.417 0.464 0.516 2 NA 17 14
NFC South 16 7.0 7 0.438 0.500 0.417 0.446 0.521 3 NA 17 15
NFC South 16 7.0 7 0.438 0.500 0.333 0.446 0.502 4 NA 17 13
NFC West 16 5.0 5 0.312 0.167 0.250 0.475 0.559 4 NA 17 7
NFC West 16 11.0 11 0.688 0.500 0.667 0.534 0.504 2 5 19 25
NFC West 16 11.5 11 0.719 0.583 0.625 0.477 0.504 1 2 21 31
NFC West 16 7.5 7 0.469 0.750 0.542 0.496 0.539 3 NA 17 16