Every fall, fantasy football managers across the world always hit and miss on rookie wide receivers being added to the league. Here is a statistical model that values college production, as well as current NFL team situations, to predict what rookie wide receivers will produce the biggest point value for a fantasy team this fall.
So who are the top 10?
Code
library(tidyverse)library(cfbfastR)library(tidymodels)library(zoo)library(bonsai)library(gt)set.seed(1234)wrpicks <-read_csv("https://mattwaite.github.io/sportsdatafiles/wrpicks1423.csv") |>mutate(college_year = year -1)wrstats <-read_csv("https://mattwaite.github.io/sportsdatafiles/receiving1323.csv")wrusage <-read_csv("https://mattwaite.github.io/sportsdatafiles/usage1323.csv")wrfantasy <-read_csv("https://mattwaite.github.io/sportsdatafiles/fantasystats1423.csv") |>mutate(nfl_team =case_when( tm =="ARI"~"Arizona Cardinals", tm =="ATL"~"Atlanta Falcons", tm =="BAL"~"Baltimore Ravens", tm =="BUF"~"Buffalo Bills", tm =="CAR"~"Carolina Panthers", tm =="CHI"~"Chicago Bears", tm =="CIN"~"Cincinnati Bengals", tm =="CLE"~"Cleveland Browns", tm =="DAL"~"Dallas Cowboys", tm =="DEN"~"Denver Broncos", tm =="DET"~"Detroit Lions", tm =="GNB"~"Green Bay Packers", tm =="HOU"~"Houston Texans", tm =="IND"~"Indianapolis Colts", tm =="JAX"~"Jacksonville Jaguars", tm =="KAN"~"Kansas City Chiefs", tm =="LAC"~"Los Angeles Chargers", tm =="LAR"~"Los Angeles Rams", tm =="LVR"~"Las Vegas Raiders", tm =="MIA"~"Miami Dolphins", tm =="MIN"~"Minnesota Vikings", tm =="NOR"~"New Orleans Saints", tm =="NWE"~"New England Patriots", tm =="NYG"~"New York Giants", tm =="NYJ"~"New York Jets", tm =="OAK"~"Las Vegas Raiders", tm =="PHI"~"Philadelphia Eagles", tm =="PIT"~"Pittsburgh Steelers", tm =="SDG"~"Los Angeles Chargers", tm =="SEA"~"Seattle Seahawks", tm =="SFO"~"San Francisco 49ers", tm =="STL"~"Los Angeles Rams", tm =="TAM"~"Tampa Bay Buccaneers", tm =="TEN"~"Tennessee Titans", tm =="WAS"~"Washington Commanders", ))nflstats <-read_csv("https://mattwaite.github.io/sportsdatafiles/nfl_passing_offense0023.csv") |>filter(season >=2009) |>mutate(nfl_team =case_when( tm =="Oakland Raiders"~"Las Vegas Raiders", tm =="San Diego Chargers"~"Los Angeles Chargers", tm =="St. Louis Rams"~"Los Angeles Rams", tm =="Washington Football Team"~"Washington Commanders", tm =="Washington Redskins"~"Washington Commanders",TRUE~ tm ))wrpicksselected <- wrpicks |>select( college_athlete_id, nfl_athlete_id, college_id, name, college_team, college_conference, nfl_team, year, college_year, overall, pre_draft_grade )wrstatsselected <- wrstats |>select( athlete_id, season, receiving_yds, receiving_td, receiving_ypr )wrfantasyselected <- wrfantasy |>filter(fant_pos =="WR") |>select( season, player, nfl_team, fant_pos, ppr )nflpassingselected <- nflstats |>mutate(rolling_mean_passing_yards =rollmean(yds, k=3, align ="right", fill=NA),rolling_mean_passing_tds =rollmean(td, k=3, align ="right", fill=NA),rolling_mean_td_percent =rollmean(td_percent, k=3, align ="right", fill=NA),rolling_mean_cmp =rollmean(cmp, k=3, align ="right", fill=NA) ) |>filter(season >=2014) |>select( season, nfl_team, rolling_mean_passing_yards, rolling_mean_passing_tds, rolling_mean_td_percent, rolling_mean_cmp )wrpicksstats <- wrpicksselected |>inner_join(wrstatsselected, by=c("college_athlete_id"="athlete_id", "college_year"="season"))wrpicksandfantasy <- wrfantasyselected |>inner_join(wrpicksstats, by=c("player"="name", "season"="year")) wrmodeling <- wrpicksandfantasy |>left_join(nflpassingselected, by=c("season"="season", "nfl_team.x"="nfl_team")) |>na.omit() |>select(-nfl_team.y)wrmodelingselected <- wrmodeling |>select( season, player, nfl_team.x, overall, rolling_mean_passing_yards, rolling_mean_passing_tds, ppr, rolling_mean_td_percent, rolling_mean_cmp, receiving_yds, receiving_td, receiving_ypr ) |>rename(nfl_team = nfl_team.x )player_split <-initial_split(wrmodelingselected, prop = .8)player_train <-training(player_split)player_test <-testing(player_split)player_recipe <-recipe(ppr ~ ., data = player_train) |>update_role(player, season, nfl_team, new_role ="ID")linear_mod <-linear_reg() |>set_engine("lm") |>set_mode("regression")linear_workflow <-workflow() %>%add_model(linear_mod) %>%add_recipe(player_recipe)linear_fit <- linear_workflow %>%fit(data = player_train)# Start the prediction for this season. The NFL team names are a mess because of choices made by the picks data provider. They just list them by city name, which creates problems in Los Angeles and New York. wrpicks <-cfbd_draft_picks(year =2024) |>filter(position =="Wide Receiver") |>mutate(college_year = year -1) |>mutate(college_athlete_id =as.character(college_athlete_id)) |>mutate(nfl_team =case_when( nfl_team =="Arizona"~"Arizona Cardinals", nfl_team =="Atlanta"~"Atlanta Falcons", nfl_team =="Baltimore"~"Baltimore Ravens", nfl_team =="Buffalo"~"Buffalo Bills", nfl_team =="Carolina"~"Carolina Panthers", nfl_team =="Chicago"~"Chicago Bears", nfl_team =="Cincinnati"~"Cincinnati Bengals", nfl_team =="Cleveland"~"Cleveland Browns", nfl_team =="Dallas"~"Dallas Cowboys", nfl_team =="Denver"~"Denver Broncos", nfl_team =="Detroit"~"Detroit Lions", nfl_team =="Green Bay"~"Green Bay Packers", nfl_team =="Houston"~"Houston Texans", nfl_team =="Indianapolis"~"Indianapolis Colts", nfl_team =="Jacksonville"~"Jacksonville Jaguars", nfl_team =="Kansas City"~"Kansas City Chiefs", name =="Ladd McConkey"~"Los Angeles Chargers", name =="Brenden Rice"~"Los Angeles Chargers", name =="Cornelius Johnson"~"Los Angeles Chargers", name =="Jordan Whittington"~"Los Angeles Rams", nfl_team =="Las Vegas"~"Las Vegas Raiders", nfl_team =="Miami"~"Miami Dolphins", nfl_team =="Minnesota"~"Minnesota Vikings", nfl_team =="New Orleans"~"New Orleans Saints", nfl_team =="New England"~"New England Patriots", name =="Malik Nabers"~"New York Giants", nfl_team =="New York"~"New York Jets", nfl_team =="Philadelphia"~"Philadelphia Eagles", nfl_team =="Pittsburgh"~"Pittsburgh Steelers", nfl_team =="Seattle"~"Seattle Seahawks", nfl_team =="San Francisco"~"San Francisco 49ers", nfl_team =="St Louis"~"Los Angeles Rams", nfl_team =="Tampa Bay"~"Tampa Bay Buccaneers", nfl_team =="Tennessee"~"Tennessee Titans", nfl_team =="Washington"~"Washington Commanders", ))wrstats <-cfbd_stats_season_player(2023, category ="receiving") |>mutate(season =2023)wrpicksselected <- wrpicks |>select( college_athlete_id, nfl_athlete_id, college_id, name, college_team, college_conference, nfl_team, year, college_year, overall, pre_draft_grade )wrstatsselected <- wrstats |>select( athlete_id, season, receiving_yds, receiving_td, receiving_ypr )wrpicksstats <- wrpicksselected |>inner_join(wrstatsselected, by=c("college_athlete_id"="athlete_id", "college_year"="season"))wrmodeling <- wrpicksstats |>left_join(nflpassingselected, by=c("college_year"="season", "nfl_team"="nfl_team")) |>select( year, name, nfl_team, overall, rolling_mean_passing_yards, rolling_mean_passing_tds, rolling_mean_td_percent, rolling_mean_cmp, receiving_yds, receiving_td, receiving_ypr ) |>rename(player = name,season = year )linearpredict <- linear_fit %>%predict(new_data = wrmodeling) %>%bind_cols(wrmodeling) # now that we have predictions, make the tablelinearpredict |>select(player, nfl_team, overall, .pred) |>top_n(10, wt=.pred) |>arrange(desc(.pred)) |>gt() |>cols_label(player ="Player",nfl_team ="Team",overall ="Pick",.pred ="Predicted PPR fantasy points" ) |>tab_header(title ="Predicting the top fantasy rookie wide receivers",subtitle ="Using draft grades, where they were drafted and who they were drafted by, these receivers could be the most valuable rookie wide receiver for your fantasy team this season. Call the predicted points a safe bet -- an average outcome -- not a ceiling." ) |>tab_style(style =cell_text(color ="black", weight ="bold", align ="left"),locations =cells_title("title") ) |>tab_style(style =cell_text(color ="black", align ="left"),locations =cells_title("subtitle") ) |>tab_source_note(source_note =md("**By:** Greg Johnson | **Source:** CFDB, Pro-Football Reference") ) |>tab_style(locations =cells_column_labels(columns =everything()),style =list(cell_borders(sides ="bottom", weight =px(3)),cell_text(weight ="bold", size=12) ) ) |>opt_row_striping() |>opt_table_lines("none")
Predicting the top fantasy rookie wide receivers
Using draft grades, where they were drafted and who they were drafted by, these receivers could be the most valuable rookie wide receiver for your fantasy team this season. Call the predicted points a safe bet -- an average outcome -- not a ceiling.
Player
Team
Pick
Predicted PPR fantasy points
Xavier Worthy
Kansas City Chiefs
28
132.0069
Ricky Pearsall
San Francisco 49ers
31
126.3248
Malik Nabers
New York Giants
6
124.9170
Rome Odunze
Chicago Bears
9
122.2718
Marvin Harrison Jr.
Arizona Cardinals
4
122.2656
Brian Thomas Jr.
Jacksonville Jaguars
23
122.1768
Keon Coleman
Buffalo Bills
33
119.7812
Ladd McConkey
Los Angeles Chargers
34
116.9061
Xavier Legette
Carolina Panthers
32
115.8175
Ja'Lynn Polk
New England Patriots
37
107.9342
By: Greg Johnson | Source: CFDB, Pro-Football Reference
1. Xavier Worthy, Kansas City Chiefs, Drafted #28
The fastset rookie in NFL history is looking to fit great with the Chiefs high flying offense. With last year’s leading receiver Rashee Rice in some legal trouble, Worthy could be a regular player in the rotation come week one.
2. Ricky Pearsall, San Francisco 49ers, Drafted #31
The 49ers led the league in yards per attempt and were second in total passing yards in 2023. The well rounded receiver out of Florida might not start right away, but after some growth with the team, he could be a huge factor later in the season.
3. Malik Nabers, New York Giants, Drafted #6
LSU’s career leader in receptions and receiving yards heads to a struggling Giants team. Inconsistent quarterback play may hurt Nabers’ fantasy success.
4. Rome Odunze, Chicago Bears, Drafted #9
Odunze may fill the role of Darnell Mooney in the Bears offense. He will be catching passes from a rookie quarterback in Caleb Williams, which could result in a lot of variability through the season.
5. Marvin Harrison Jr., Arizona Cardinals, Drafted #4
The Ohio State standout looks to be a strong add to a team who ranked in the bottom 10 in passing touchdowns, yards per attempt and passing yards last year. Harrison should be a lock with the team. The bigger question however is will the team be able to get itslef together to give Harrison success.
6. Brian Thomas Jr., Jacksonville Jaguars, Drafted #23
Thomas led the nation with 17 touchdown receptions last season. With the Jaguars losing their number one yards and touchdowns leader from last year in Calvin Ridley, look for a lot of Trevor Lawrence passes being thrown Thomas’ way.
7. Keon Coleman, Buffalo Bills, Drafted #33
Coleman is prime to be a key factor in the Bills offense with th departure of Stefon Diggs and Gabe Davis. Those two combines for nearly 50% of the Bills’ receiving touchdowns and yards, leaving much room for targets to fly Coleman’s way.