
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 %>% 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 | 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_17_NYJ_SEA | 2022 | REG | 17 | 2023-01-01 | Sunday | 16:05 | NYJ | NA | SEA | NA | Home | NA | NA | NA | 2023010111 | NA | NA | 202301010sea | NA | NA | 10 | 8 | 110 | -130 | 1.5 | -110 | -110 | NA | NA | NA | 0 | outdoors | fieldturf | NA | NA | NA | NA | NA | NA | Robert Saleh | Pete Carroll | NA | SEA00 | Lumen Field |
2022_17_MIN_GB | 2022 | REG | 17 | 2023-01-01 | Sunday | 16:25 | MIN | NA | GB | NA | Home | NA | NA | NA | 2023010112 | NA | NA | 202301010gnb | NA | NA | 8 | 7 | 205 | -245 | 5.5 | -110 | -110 | NA | NA | NA | 1 | outdoors | grass | NA | NA | NA | NA | NA | NA | Kevin O’Connell | Matt LaFleur | NA | GNB00 | Lambeau Field |
2022_17_LA_LAC | 2022 | REG | 17 | 2023-01-01 | Sunday | 20:20 | LA | NA | LAC | NA | Home | NA | NA | NA | 2023010113 | NA | NA | 202301010sdg | NA | NA | 7 | 6 | 110 | -130 | 1.5 | -110 | -110 | NA | NA | NA | 0 | dome | matrixturf | NA | NA | NA | NA | NA | NA | Sean McVay | Brandon Staley | NA | LAX01 | SoFi Stadium |
2022_17_BUF_CIN | 2022 | REG | 17 | 2023-01-02 | Monday | 20:30 | BUF | NA | CIN | NA | Home | NA | NA | NA | 2023010200 | NA | NA | 202301020cin | NA | NA | 9 | 9 | -110 | -110 | 0.0 | -110 | -110 | NA | NA | NA | 0 | outdoors | grass | NA | NA | NA | NA | NA | NA | Sean McDermott | Zac Taylor | NA | CIN00 | Paul Brown Stadium |
2022_18_TB_ATL | 2022 | REG | 18 | 2023-01-08 | Sunday | 13:00 | TB | NA | ATL | NA | Home | NA | NA | NA | 2023010800 | NA | NA | 202301080atl | NA | NA | 7 | 7 | -350 | 290 | -7.5 | -110 | -110 | NA | NA | NA | 1 | NA | fieldturf | NA | NA | NA | NA | NA | NA | Todd Bowles | Arthur Smith | NA | ATL97 | Mercedes-Benz Stadium |
2022_18_NE_BUF | 2022 | REG | 18 | 2023-01-08 | Sunday | 13:00 | NE | NA | BUF | NA | Home | NA | NA | NA | 2023010801 | NA | NA | 202301080buf | NA | NA | 7 | 6 | 255 | -305 | 7.0 | -110 | -110 | NA | NA | NA | 1 | outdoors | astroturf | NA | NA | NA | NA | NA | NA | Bill Belichick | Sean McDermott | NA | BUF00 | New Era Field |
2022_18_MIN_CHI | 2022 | REG | 18 | 2023-01-08 | Sunday | 13:00 | MIN | NA | CHI | NA | Home | NA | NA | NA | 2023010802 | NA | NA | 202301080chi | NA | NA | 7 | 7 | -130 | 110 | -1.5 | -110 | -110 | NA | NA | NA | 1 | outdoors | grass | NA | NA | NA | NA | NA | NA | Kevin O’Connell | Matt Eberflus | NA | CHI98 | Soldier Field |
2022_18_BAL_CIN | 2022 | REG | 18 | 2023-01-08 | Sunday | 13:00 | BAL | NA | CIN | NA | Home | NA | NA | NA | 2023010803 | NA | NA | 202301080cin | NA | NA | 7 | 6 | 140 | -165 | 3.0 | 100 | -120 | NA | NA | NA | 1 | outdoors | grass | NA | NA | NA | NA | NA | NA | John Harbaugh | Zac Taylor | NA | CIN00 | Paul Brown Stadium |
2022_18_LAC_DEN | 2022 | REG | 18 | 2023-01-08 | Sunday | 13:00 | LAC | NA | DEN | NA | Home | NA | NA | NA | 2023010812 | NA | NA | 202301080den | NA | NA | 7 | 7 | -110 | -110 | 0.0 | -110 | -110 | NA | NA | NA | 1 | outdoors | grass | NA | NA | NA | NA | NA | NA | Brandon Staley | Nathaniel Hackett | NA | DEN00 | Empower Field at Mile High |
2022_18_DET_GB | 2022 | REG | 18 | 2023-01-08 | Sunday | 13:00 | DET | NA | GB | NA | Home | NA | NA | NA | 2023010804 | NA | NA | 202301080gnb | NA | NA | 7 | 7 | 330 | -410 | 8.0 | -110 | -110 | NA | NA | NA | 1 | outdoors | grass | NA | NA | NA | NA | NA | NA | Dan Campbell | Matt LaFleur | NA | GNB00 | Lambeau Field |
2022_18_HOU_IND | 2022 | REG | 18 | 2023-01-08 | Sunday | 13:00 | HOU | NA | IND | NA | Home | NA | NA | NA | 2023010805 | NA | NA | 202301080clt | NA | NA | 7 | 7 | 420 | -540 | 10.0 | -110 | -110 | NA | NA | NA | 1 | NA | fieldturf | NA | NA | NA | NA | NA | NA | Lovie Smith | Frank Reich | NA | IND00 | Lucas Oil Stadium |
2022_18_TEN_JAX | 2022 | REG | 18 | 2023-01-08 | Sunday | 13:00 | TEN | NA | JAX | NA | Home | NA | NA | NA | 2023010806 | NA | NA | 202301080jax | NA | NA | 10 | 7 | -150 | 130 | -3.0 | -110 | -110 | NA | NA | NA | 1 | outdoors | grass | NA | NA | NA | NA | NA | NA | Mike Vrabel | Doug Pederson | NA | JAX00 | TIAA Bank Stadium |
2022_18_KC_LV | 2022 | REG | 18 | 2023-01-08 | Sunday | 13:00 | KC | NA | LV | NA | Home | NA | NA | NA | 2023010813 | NA | NA | 202301080rai | NA | NA | 7 | 7 | -130 | 110 | -2.0 | -110 | -110 | NA | NA | NA | 1 | dome | grass | NA | NA | NA | NA | NA | NA | Andy Reid | Josh McDaniels | NA | VEG00 | Allegiant Stadium |
2022_18_NYJ_MIA | 2022 | REG | 18 | 2023-01-08 | Sunday | 13:00 | NYJ | NA | MIA | NA | Home | NA | NA | NA | 2023010807 | NA | NA | 202301080mia | NA | NA | 7 | 7 | 205 | -245 | 5.5 | -110 | -110 | NA | NA | NA | 1 | outdoors | grass | NA | NA | NA | NA | NA | NA | Robert Saleh | Mike McDaniel | NA | MIA00 | Hard Rock Stadium |
2022_18_CAR_NO | 2022 | REG | 18 | 2023-01-08 | Sunday | 13:00 | CAR | NA | NO | NA | Home | NA | NA | NA | 2023010808 | NA | NA | 202301080nor | NA | NA | 7 | 7 | 135 | -155 | 3.0 | -110 | -110 | NA | NA | NA | 1 | dome | astroturf | NA | NA | NA | NA | NA | NA | Matt Rhule | Dennis Allen | NA | NOR00 | Mercedes-Benz Superdome |
2022_18_NYG_PHI | 2022 | REG | 18 | 2023-01-08 | Sunday | 13:00 | NYG | NA | PHI | NA | Home | NA | NA | NA | 2023010809 | NA | NA | 202301080phi | NA | NA | 7 | 7 | 190 | -225 | 5.0 | -110 | -110 | NA | NA | NA | 1 | outdoors | grass | NA | NA | NA | NA | NA | NA | Brian Daboll | Nick Sirianni | NA | PHI00 | Lincoln Financial Field |
2022_18_CLE_PIT | 2022 | REG | 18 | 2023-01-08 | Sunday | 13:00 | CLE | NA | PIT | NA | Home | NA | NA | NA | 2023010810 | NA | NA | 202301080pit | NA | NA | 7 | 7 | NA | NA | NA | NA | NA | NA | NA | NA | 1 | outdoors | grass | NA | NA | NA | NA | NA | NA | Kevin Stefanski | Mike Tomlin | NA | PIT00 | Heinz Field |
2022_18_LA_SEA | 2022 | REG | 18 | 2023-01-08 | Sunday | 13:00 | LA | NA | SEA | NA | Home | NA | NA | NA | 2023010814 | NA | NA | 202301080sea | NA | NA | 7 | 7 | -245 | 205 | -5.5 | -110 | -110 | NA | NA | NA | 1 | outdoors | fieldturf | NA | NA | NA | NA | NA | NA | Sean McVay | Pete Carroll | NA | SEA00 | Lumen Field |
2022_18_ARI_SF | 2022 | REG | 18 | 2023-01-08 | Sunday | 13:00 | ARI | NA | SF | NA | Home | NA | NA | NA | 2023010815 | NA | NA | 202301080sfo | NA | NA | 7 | 7 | 135 | -155 | 3.0 | 100 | -120 | NA | NA | NA | 1 | outdoors | grass | NA | NA | NA | NA | NA | NA | Kliff Kingsbury | Kyle Shanahan | NA | SFO01 | Levi’s Stadium |
2022_18_DAL_WAS | 2022 | REG | 18 | 2023-01-08 | Sunday | 13:00 | DAL | NA | WAS | NA | Home | NA | NA | NA | 2023010811 | NA | NA | 202301080was | NA | NA | 10 | 7 | -120 | 100 | -1.0 | -110 | -110 | NA | NA | NA | 1 | outdoors | grass | NA | NA | NA | NA | NA | NA | Mike McCarthy | Ron Rivera | NA | WAS00 | FedExField |
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)
#> • 2022-07-17 13:47:03: Calculating team data
#> • 2022-07-17 13:47:03: Calculating head to head
#> • 2022-07-17 13:47:03: Calculating division rank #1
#> • 2022-07-17 13:47:03: DIV (2): Head-to-head
#> • 2022-07-17 13:47:03: DIV (2): Division Record
#> • 2022-07-17 13:47:03: Calculating division rank #2
#> • 2022-07-17 13:47:03: DIV (3): Head-to-head
#> • 2022-07-17 13:47:03: DIV (3): Division Record
#> • 2022-07-17 13:47:03: DIV (3): Common Record
#> • 2022-07-17 13:47:03: DIV (2): Head-to-head
#> • 2022-07-17 13:47:04: DIV (2): Division Record
#> • 2022-07-17 13:47:04: DIV (2): Common Record
#> • 2022-07-17 13:47:04: DIV (2): Conference Record
#> • 2022-07-17 13:47:04: Calculating division rank #3
#> • 2022-07-17 13:47:04: DIV (2): Head-to-head
#> • 2022-07-17 13:47:04: DIV (2): Division Record
#> • 2022-07-17 13:47:04: DIV (2): Common Record
#> • 2022-07-17 13:47:04: 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)
#> • 2022-07-17 13:47:04: Calculating seed #1
#> • 2022-07-17 13:47:04: CONF (3): Head-to-head Sweep
#> • 2022-07-17 13:47:04: Calculating seed #2
#> • 2022-07-17 13:47:04: CONF (2): Head-to-head Sweep
#> • 2022-07-17 13:47:04: CONF (2): Conference Record
#> • 2022-07-17 13:47:05: Calculating seed #3
#> • 2022-07-17 13:47:05: Calculating seed #4
#> • 2022-07-17 13:47:05: Calculating seed #5
#> • 2022-07-17 13:47:05: Calculating seed #6
#> • 2022-07-17 13:47:05: 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)
#> • 2022-07-17 13:47:05: Calculating draft order #32
#> • 2022-07-17 13:47:05: Calculating draft order #31
#> • 2022-07-17 13:47:06: Calculating draft order #30
#> • 2022-07-17 13:47:06: Calculating draft order #29
#> • 2022-07-17 13:47:06: Calculating draft order #28
#> • 2022-07-17 13:47:06: Calculating draft order #27
#> • 2022-07-17 13:47:06: Calculating draft order #26
#> • 2022-07-17 13:47:06: Calculating draft order #25
#> • 2022-07-17 13:47:06: Calculating draft order #24
#> • 2022-07-17 13:47:06: Calculating draft order #23
#> • 2022-07-17 13:47:06: Calculating draft order #22
#> • 2022-07-17 13:47:06: Calculating draft order #21
#> • 2022-07-17 13:47:06: Calculating draft order #20
#> • 2022-07-17 13:47:06: Calculating draft order #19
#> • 2022-07-17 13:47:06: Calculating draft order #18
#> • 2022-07-17 13:47:06: Calculating draft order #17
#> • 2022-07-17 13:47:06: Calculating draft order #16
#> • 2022-07-17 13:47:06: Calculating draft order #15
#> • 2022-07-17 13:47:06: Calculating draft order #14
#> • 2022-07-17 13:47:06: Calculating draft order #13
#> • 2022-07-17 13:47:06: Calculating draft order #12
#> • 2022-07-17 13:47:06: Calculating draft order #11
#> • 2022-07-17 13:47:06: Calculating draft order #10
#> • 2022-07-17 13:47:06: DRAFT: Divisional Rank
#> • 2022-07-17 13:47:06: DRAFT: Conference Rank
#> • 2022-07-17 13:47:06: CONF (2): Best-in-division reduction
#> • 2022-07-17 13:47:07: CONF (2): Head-to-head Sweep
#> • 2022-07-17 13:47:07: Calculating draft order #9
#> • 2022-07-17 13:47:07: Calculating draft order #8
#> • 2022-07-17 13:47:07: Calculating draft order #7
#> • 2022-07-17 13:47:07: Calculating draft order #6
#> • 2022-07-17 13:47:07: Calculating draft order #5
#> • 2022-07-17 13:47:07: Calculating draft order #4
#> • 2022-07-17 13:47:07: Calculating draft order #3
#> • 2022-07-17 13:47:07: Calculating draft order #2
#> • 2022-07-17 13:47:07: 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 |