
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 | 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 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
2022_18_CLE_PIT | 2022 | REG | 18 | 2023-01-08 | Sunday | 13:00 | CLE | 14 | PIT | 28 | Home | 14 | 42 | 0 | 2023010810 | NA | NA | 202301080pit | NA | 401437958 | 7 | 7 | 128 | -142 | 2.5 | -101 | -109 | 40.0 | -106 | -106 | 1 | outdoors | grass | 36 | 8 | 00-0033537 | 00-0038102 | Deshaun Watson | Kenny Pickett | Kevin Stefanski | Mike Tomlin | Clete Blakeman | PIT00 | Acrisure Stadium |
2022_18_LAC_DEN | 2022 | REG | 18 | 2023-01-08 | Sunday | 16:25 | LAC | 28 | DEN | 31 | Home | 3 | 59 | 0 | 2023010812 | NA | NA | 202301080den | NA | 401437960 | 7 | 7 | 222 | -254 | 6.0 | -104 | -106 | 38.5 | -103 | -110 | 1 | outdoors | grass | 43 | 4 | 00-0036355 | 00-0029263 | Justin Herbert | Russell Wilson | Brandon Staley | Jay Rosburg | Shawn Hochuli | DEN00 | Empower Field at Mile High |
2022_18_NYG_PHI | 2022 | REG | 18 | 2023-01-08 | Sunday | 16:25 | NYG | 16 | PHI | 22 | Home | 6 | 38 | 0 | 2023010809 | NA | NA | 202301080phi | NA | 401437957 | 7 | 7 | 858 | -1252 | 16.5 | -103 | -107 | 42.5 | -105 | -107 | 1 | outdoors | grass | 43 | 12 | 00-0033550 | 00-0036389 | Davis Webb | Jalen Hurts | Brian Daboll | Nick Sirianni | Carl Cheffers | PHI00 | Lincoln Financial Field |
2022_18_LA_SEA | 2022 | REG | 18 | 2023-01-08 | Sunday | 16:25 | LA | 16 | SEA | 19 | Home | 3 | 35 | 1 | 2023010814 | NA | NA | 202301080sea | NA | 401437963 | 7 | 7 | 198 | -224 | 5.5 | -112 | 102 | 41.5 | -101 | -111 | 1 | outdoors | fieldturf | 45 | 4 | 00-0034855 | 00-0030565 | Baker Mayfield | Geno Smith | Sean McVay | Pete Carroll | Craig Wrolstad | SEA00 | Lumen Field |
2022_18_ARI_SF | 2022 | REG | 18 | 2023-01-08 | Sunday | 16:25 | ARI | 13 | SF | 38 | Home | 25 | 51 | 0 | 2023010815 | NA | NA | 202301080sfo | NA | 401437962 | 7 | 7 | 753 | -1061 | 14.0 | 100 | -111 | 40.0 | -107 | -105 | 1 | outdoors | grass | 57 | 2 | 00-0035040 | 00-0037834 | David Blough | Brock Purdy | Kliff Kingsbury | Kyle Shanahan | Adrian Hill | SFO01 | Levi’s Stadium |
2022_18_DAL_WAS | 2022 | REG | 18 | 2023-01-08 | Sunday | 16:25 | DAL | 6 | WAS | 26 | Home | 20 | 32 | 0 | 2023010811 | NA | NA | 202301080was | NA | 401437959 | 10 | 7 | -320 | 274 | -7.5 | -100 | -110 | 40.5 | -104 | -108 | 1 | outdoors | grass | 42 | 7 | 00-0033077 | 00-0037077 | Dak Prescott | Sam Howell | Mike McCarthy | Ron Rivera | Tra Blake | WAS00 | FedExField |
2022_18_DET_GB | 2022 | REG | 18 | 2023-01-08 | Sunday | 20:20 | DET | 20 | GB | 16 | Home | -4 | 36 | 0 | 2023010804 | NA | NA | 202301080gnb | NA | 401437952 | 7 | 7 | 237 | -273 | 5.5 | -110 | -100 | 49.0 | -113 | 101 | 1 | outdoors | grass | 21 | 4 | 00-0033106 | 00-0023459 | Jared Goff | Aaron Rodgers | Dan Campbell | Matt LaFleur | Brad Rogers | GNB00 | Lambeau Field |
2022_19_SEA_SF | 2022 | WC | 19 | 2023-01-14 | Saturday | 16:30 | SEA | 23 | SF | 41 | Home | 18 | 64 | 0 | 2023011400 | NA | NA | 202301140sfo | NA | 401438000 | 6 | 6 | 367 | -447 | 10.0 | -123 | 112 | 42.0 | -102 | -110 | 1 | outdoors | grass | 57 | 11 | 00-0030565 | 00-0037834 | Geno Smith | Brock Purdy | Pete Carroll | Kyle Shanahan | Alex Kemp | SFO01 | Levi’s Stadium |
2022_19_LAC_JAX | 2022 | WC | 19 | 2023-01-14 | Saturday | 20:15 | LAC | 30 | JAX | 31 | Home | 1 | 61 | 0 | 2023011401 | NA | NA | 202301140jax | NA | 401437998 | 6 | 7 | -126 | 114 | -2.0 | -102 | -108 | 46.5 | -105 | -107 | 0 | outdoors | grass | 37 | 4 | 00-0036355 | 00-0036971 | Justin Herbert | Trevor Lawrence | Brandon Staley | Doug Pederson | Shawn Smith | JAX00 | TIAA Bank Stadium |
2022_19_MIA_BUF | 2022 | WC | 19 | 2023-01-15 | Sunday | 13:00 | MIA | 31 | BUF | 34 | Home | 3 | 65 | 0 | 2023011500 | NA | NA | 202301150buf | NA | 401438002 | 7 | 7 | 649 | -882 | 14.0 | -116 | 105 | 44.0 | -105 | -107 | 1 | outdoors | a_turf | 27 | 4 | 00-0037327 | 00-0034857 | Skylar Thompson | Josh Allen | Mike McDaniel | Sean McDermott | Brad Allen | BUF00 | New Era Field |
2022_19_NYG_MIN | 2022 | WC | 19 | 2023-01-15 | Sunday | 16:50 | NYG | 31 | MIN | 24 | Home | -7 | 55 | 0 | 2023011501 | NA | NA | 202301150min | NA | 401438001 | 7 | 7 | 129 | -142 | 2.5 | 103 | -113 | 48.0 | -104 | -108 | 0 | dome | sportturf | NA | NA | 00-0035710 | 00-0029604 | Daniel Jones | Kirk Cousins | Brian Daboll | Kevin O’Connell | Adrian Hill | MIN01 | U.S. Bank Stadium |
2022_19_BAL_CIN | 2022 | WC | 19 | 2023-01-15 | Sunday | 20:15 | BAL | 17 | CIN | 24 | Home | 7 | 41 | 0 | 2023011502 | NA | NA | 202301150cin | NA | 401437999 | 7 | 7 | 311 | -370 | 7.5 | -104 | -106 | 40.0 | -104 | -108 | 1 | outdoors | fieldturf | 30 | 4 | 00-0035993 | 00-0036442 | Tyler Huntley | Joe Burrow | John Harbaugh | Zac Taylor | Clay Martin | CIN00 | Paycor Stadium |
2022_19_DAL_TB | 2022 | WC | 19 | 2023-01-16 | Monday | 20:15 | DAL | 31 | TB | 14 | Home | -17 | 45 | 0 | 2023011600 | NA | NA | 202301160tam | NA | 401438003 | 8 | 8 | -135 | 122 | -2.5 | -108 | -103 | 45.5 | -105 | -107 | 0 | outdoors | grass | 58 | 2 | 00-0033077 | 00-0019596 | Dak Prescott | Tom Brady | Mike McCarthy | Todd Bowles | Craig Wrolstad | TAM00 | Raymond James Stadium |
2022_20_JAX_KC | 2022 | DIV | 20 | 2023-01-21 | Saturday | 16:30 | JAX | 20 | KC | 27 | Home | 7 | 47 | 0 | 2023012100 | NA | NA | 202301210kan | NA | 401438005 | 7 | 14 | 377 | -461 | 10.0 | -119 | 108 | 52.5 | -116 | 103 | 0 | outdoors | grass | 36 | 6 | 00-0036971 | 00-0033873 | Trevor Lawrence | Patrick Mahomes | Doug Pederson | Andy Reid | Shawn Hochuli | KAN00 | GEHA Field at Arrowhead Stadium |
2022_20_NYG_PHI | 2022 | DIV | 20 | 2023-01-21 | Saturday | 20:15 | NYG | 7 | PHI | 38 | Home | 31 | 45 | 0 | 2023012101 | NA | NA | 202301210phi | NA | 401438004 | 6 | 13 | 304 | -360 | 8.0 | 101 | -111 | 48.0 | -113 | 101 | 1 | outdoors | grass | 40 | 6 | 00-0035710 | 00-0036389 | Daniel Jones | Jalen Hurts | Brian Daboll | Nick Sirianni | Clete Blakeman | PHI00 | Lincoln Financial Field |
2022_20_CIN_BUF | 2022 | DIV | 20 | 2023-01-22 | Sunday | 15:00 | CIN | 27 | BUF | 10 | Home | -17 | 37 | 0 | 2023012200 | NA | NA | 202301220buf | NA | 401438007 | 7 | 7 | 226 | -259 | 6.0 | -107 | -103 | 48.5 | -107 | -105 | 0 | outdoors | a_turf | 32 | 4 | 00-0036442 | 00-0034857 | Joe Burrow | Josh Allen | Zac Taylor | Sean McDermott | Carl Cheffers | BUF00 | New Era Field |
2022_20_DAL_SF | 2022 | DIV | 20 | 2023-01-22 | Sunday | 18:30 | DAL | 12 | SF | 19 | Home | 7 | 31 | 0 | 2023012201 | NA | NA | 202301220sfo | NA | 401438006 | 6 | 8 | 164 | -183 | 3.5 | -107 | -103 | 46.5 | -105 | -107 | 0 | outdoors | grass | 55 | 19 | 00-0033077 | 00-0037834 | Dak Prescott | Brock Purdy | Mike McCarthy | Kyle Shanahan | Bill Vinovich | SFO01 | Levi’s Stadium |
2022_21_SF_PHI | 2022 | CON | 21 | 2023-01-29 | Sunday | 15:00 | SF | 7 | PHI | 31 | Home | 24 | 38 | 0 | 2023012900 | NA | NA | 202301290phi | NA | 401438009 | 7 | 8 | 133 | -147 | 2.5 | 105 | -116 | 45.0 | -114 | 101 | 0 | outdoors | grass | 52 | 14 | 00-0037834 | 00-0036389 | Brock Purdy | Jalen Hurts | Kyle Shanahan | Nick Sirianni | John Hussey | PHI00 | Lincoln Financial Field |
2022_21_CIN_KC | 2022 | CON | 21 | 2023-01-29 | Sunday | 18:30 | CIN | 20 | KC | 23 | Home | 3 | 43 | 0 | 2023012901 | NA | NA | 202301290kan | NA | 401438008 | 7 | 8 | 119 | -131 | 2.0 | -103 | -107 | 48.5 | -106 | -106 | 0 | outdoors | grass | 22 | 13 | 00-0036442 | 00-0033873 | Joe Burrow | Patrick Mahomes | Zac Taylor | Andy Reid | Ron Torbert | KAN00 | GEHA Field at Arrowhead Stadium |
2022_22_KC_PHI | 2022 | SB | 22 | 2023-02-12 | Sunday | 18:30 | KC | 38 | PHI | 35 | Neutral | -3 | 73 | 0 | 2023021200 | NA | NA | 202302120phi | NA | 401438030 | 14 | 14 | 104 | -115 | 1.0 | -103 | -107 | 51.0 | -104 | -108 | 0 | closed | grass | NA | NA | 00-0033873 | 00-0036389 | Patrick Mahomes | Jalen Hurts | Andy Reid | Nick Sirianni | Carl Cheffers | PHO00 | State Farm 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)
#> ℹ 13:10:57 | Calculating team data
#> ℹ 13:10:57 | Calculating head to head
#> ℹ 13:10:57 | Calculating division rank #1
#> ℹ 13:10:57 | DIV (2): Head-to-head
#> ℹ 13:10:58 | DIV (2): Division Record
#> ℹ 13:10:58 | Calculating division rank #2
#> ℹ 13:10:58 | DIV (3): Head-to-head
#> ℹ 13:10:58 | DIV (3): Division Record
#> ℹ 13:10:58 | DIV (3): Common Record
#> ℹ 13:10:58 | DIV (2): Head-to-head
#> ℹ 13:10:59 | DIV (2): Division Record
#> ℹ 13:10:59 | DIV (2): Common Record
#> ℹ 13:10:59 | DIV (2): Conference Record
#> ℹ 13:10:59 | Calculating division rank #3
#> ℹ 13:10:59 | DIV (2): Head-to-head
#> ℹ 13:10:59 | DIV (2): Division Record
#> ℹ 13:10:59 | DIV (2): Common Record
#> ℹ 13:11:00 | 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)
#> ℹ 13:11:00 | Calculating seed #1
#> ℹ 13:11:00 | CONF (3): Head-to-head Sweep
#> ℹ 13:11:00 | Calculating seed #2
#> ℹ 13:11:00 | CONF (2): Head-to-head Sweep
#> ℹ 13:11:01 | CONF (2): Conference Record
#> ℹ 13:11:01 | Calculating seed #3
#> ℹ 13:11:01 | Calculating seed #4
#> ℹ 13:11:01 | Calculating seed #5
#> ℹ 13:11:01 | Calculating seed #6
#> ℹ 13:11:01 | 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)
#> ℹ 13:11:02 | Calculating draft order #32
#> ℹ 13:11:02 | Calculating draft order #31
#> ℹ 13:11:02 | Calculating draft order #30
#> ℹ 13:11:02 | Calculating draft order #29
#> ℹ 13:11:02 | Calculating draft order #28
#> ℹ 13:11:02 | Calculating draft order #27
#> ℹ 13:11:02 | Calculating draft order #26
#> ℹ 13:11:02 | Calculating draft order #25
#> ℹ 13:11:02 | Calculating draft order #24
#> ℹ 13:11:02 | Calculating draft order #23
#> ℹ 13:11:02 | Calculating draft order #22
#> ℹ 13:11:02 | Calculating draft order #21
#> ℹ 13:11:02 | Calculating draft order #20
#> ℹ 13:11:02 | Calculating draft order #19
#> ℹ 13:11:02 | Calculating draft order #18
#> ℹ 13:11:02 | Calculating draft order #17
#> ℹ 13:11:03 | Calculating draft order #16
#> ℹ 13:11:03 | Calculating draft order #15
#> ℹ 13:11:03 | Calculating draft order #14
#> ℹ 13:11:03 | Calculating draft order #13
#> ℹ 13:11:03 | Calculating draft order #12
#> ℹ 13:11:03 | Calculating draft order #11
#> ℹ 13:11:03 | Calculating draft order #10
#> ℹ 13:11:03 | DRAFT: Divisional Rank
#> ℹ 13:11:03 | DRAFT: Conference Rank
#> ℹ 13:11:03 | CONF (2): Best-in-division reduction
#> ℹ 13:11:03 | CONF (2): Head-to-head Sweep
#> ℹ 13:11:03 | Calculating draft order #9
#> ℹ 13:11:03 | Calculating draft order #8
#> ℹ 13:11:03 | Calculating draft order #7
#> ℹ 13:11:03 | Calculating draft order #6
#> ℹ 13:11:03 | Calculating draft order #5
#> ℹ 13:11:03 | Calculating draft order #4
#> ℹ 13:11:03 | Calculating draft order #3
#> ℹ 13:11:04 | Calculating draft order #2
#> ℹ 13:11:04 | 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 |