We are BACK with optimal lineups from week 7 simulations!

It was a rough week last week, but that’s going to happen, let’s get back in the driver’s seat this week.

Again, no real changes since last week. If you want to review the overall code for scraping and optimizing projections, the initial post is here.

Setup

library(data.table)
library(dtplyr)
library(tidyverse)
library(rPref)
library(kableExtra)

week <- 7

proj <- readRDS(paste0('week_', week, '_proj.RDS'))

sal <- read_csv(paste0('DKSalaries_wk_', week, '.csv'))

I’ll start with the optimized lineups pulled for week 4, with the same details as last time: 10,000 lineups, using the standard deviation of projections, completely individually based (still working on that).

sim_lu <- readRDS(paste0('sim_lineups_week_', week, '.RDS')) %>%
  rename(pts_base=points) %>%
  select(lineup, Name, team, position, pts_base, pts_pred, sd_pts, Salary)

glimpse(sim_lu)
## Observations: 90,000
## Variables: 8
## Groups: Name [141]
## $ lineup   <int> 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2,...
## $ Name     <chr> "Dolphins", "Tevin Coleman", "Tyler Boyd", "Dalvin Co...
## $ team     <chr> "MIA", "SFO", "CIN", "MIN", "JAC", "NYG", "DET", "BAL...
## $ position <chr> "DST", "RB", "WR", "RB", "RB", "TE", "WR", "QB", "WR"...
## $ pts_base <dbl> 5.644063, 12.685534, 14.962621, 20.578049, 21.115060,...
## $ pts_pred <dbl> 7.085018, 17.527696, 15.747588, 21.363833, 24.120519,...
## $ sd_pts   <dbl> 1.0239833, 1.8186888, 1.1493671, 0.9237673, 2.0700289...
## $ Salary   <dbl> 1500, 5600, 5600, 8000, 7000, 6500, 5800, 6800, 3000,...
sim_lu %>%
  filter(lineup<=3) %>%
  arrange(lineup, position, desc(pts_pred)) %>%
  mutate_at(vars(pts_base, pts_pred, sd_pts), function(x) round(x, 2)) %>%
  knitr::kable() %>%
  kable_styling() %>%
  column_spec(1, bold=TRUE) %>%
  collapse_rows(columns = 1, valign = 'top') %>%
  scroll_box(height = '600px', width = '100%')
lineup Name team position pts_base pts_pred sd_pts Salary
1 Dolphins MIA DST 5.64 7.09 1.02 1500
Lamar Jackson BAL QB 22.67 23.04 1.01 6800
Leonard Fournette JAC RB 21.12 24.12 2.07 7000
Dalvin Cook MIN RB 20.58 21.36 0.92 8000
Tevin Coleman SFO RB 12.69 17.53 1.82 5600
Evan Engram NYG TE 15.65 17.63 2.33 6500
Kenny Golladay DET WR 15.40 16.64 2.07 5800
Tyler Boyd CIN WR 14.96 15.75 1.15 5600
Allen Lazard GBP WR 9.80 10.98 1.74 3000
2 Colts IND DST 6.44 6.90 1.06 2000
Deshaun Watson HOU QB 22.24 23.34 0.98 7000
Leonard Fournette JAC RB 21.12 22.89 2.07 7000
Chris Carson SEA RB 16.97 17.84 1.32 6500
Latavius Murray NOS RB 11.35 15.92 3.07 5100
Darren Waller OAK TE 13.53 17.19 3.21 4700
Tyler Lockett SEA WR 16.26 20.04 2.02 6600
Cooper Kupp LAR WR 19.25 19.31 1.64 7400
Chris Conley JAC WR 7.86 12.27 1.68 3500
3 Lions DET DST 6.37 8.02 0.69 2300
Lamar Jackson BAL QB 22.67 23.25 1.01 6800
Latavius Murray NOS RB 11.35 16.31 3.07 5100
David Montgomery CHI RB 12.09 15.11 1.99 4800
Darren Waller OAK TE 13.53 16.47 3.21 4700
DeAndre Hopkins HOU WR 18.33 21.86 2.44 7800
Keenan Allen LAC WR 17.17 19.56 2.27 6700
T.Y. Hilton IND WR 16.98 18.05 1.77 5900
Tyler Boyd CIN WR 14.96 17.35 1.15 5600

Who is in Optimal Lineups?

sim_lu %>%
  group_by(Name, position, Salary) %>%
  dplyr::summarize(lu=n_distinct(lineup)) %>%
  ungroup() %>%
  group_by(position) %>%
  top_n(10, lu) %>%
  ungroup() %>%
  arrange(position, desc(lu)) %>%
  mutate(Name=factor(Name),
         Name=fct_reorder(Name, lu)) %>%
  ggplot(aes(x=Name, y=lu/1000, fill=Salary)) +
  geom_bar(stat='identity') +
  facet_wrap(~position, ncol = 3, scales='free') +
  coord_flip() +
  scale_y_continuous(labels = scales::comma) +
  scale_fill_viridis_c() +
  xlab('') +
  ylab('Lineups (Thousands)') +
  ggtitle('Top 10 Players Present by Position') 

Some of my observations:

  • Lots of parity at the QB spot. Lamar Jackson and Kyler Murray are most present, but there’s a linear decline.

  • Leonard Fournette is a heavy favorite at RB, showing up in almost 80% of lineups. Kenyan Drake appears to be the value play again (lets hope he gets a better play call for that 2 pt conversion this time).

  • T.Y. Hilton is the favorite at WR, showing up in almost 50% of lineups, Cooper Kupp comes in second by a fair margin (He was a dud last week, but hey, that means my Niners are awesome, so I’ll take it.). Allen Lazard appears to be the value play

  • It’s the usual story at TE, there are only a few worth playing.

  • Redskins, Dolphins, and Colts are the most common defenses most likely due to their price. Over the last few weeks, the model has selected the Defenses with the lowest prices.

Who is getting placed in Lineups?

DraftKings provides scoring for 391 players this week, but only 141 make it into optimized lineups. Why is that? To determine, I’ll plot projected points vs salary, colored by whether or not they make it into optimized lineups, and sized by their projection standard deviation

plyr_lu <- sim_lu %>%
  group_by(Name, position) %>%
  dplyr::summarize(lu=n_distinct(lineup)) %>%
  ungroup() 

proj %>% 
  filter(avg_type=='weighted') %>%
  mutate(Name = ifelse(pos=="DST", last_name, paste(first_name, last_name))) %>%
  inner_join(sal, by=c("Name")) %>%
  select(Name, team, position, points, Salary, sd_pts) %>%
  left_join(plyr_lu, by='Name') %>%
  replace_na(list(lu=0)) %>%
  mutate(lu_bin=ifelse(lu==0, '0 Lineups', '>=1 Lineups'),
         lu_5=cut(lu,5, labels = FALSE)) %>%
  ggplot(aes(x=Salary, y=points, color=lu_bin, size=sd_pts)) +
  geom_point() +
  scale_color_manual(values = c('red', 'blue'), name="") +
  geom_smooth(inherit.aes = FALSE, aes(x=Salary, y=points), method = 'lm', se=FALSE) +
  ylab('Projected Points') +
  xlab('Salary') +
  ggtitle('Who makes it into Optimized Lineups?') +
  scale_x_continuous(labels=scales::dollar)

This week, not many players below the line get into lineups, but some above get excluded due to their small uncertainty. Remember, this method takes players who have the potential to blow up rather than players with solid floors.

Flex Configurations

In DFS lineups, you have an extra spot to use on an RB, WR, and TE of your chosing

sim_lu %>%
  group_by(lineup) %>%
  mutate(lineup_pts=sum(pts_pred)) %>%
  group_by(lineup, position) %>%
  mutate(n=n()) %>%
  select(lineup, position, n, lineup_pts) %>%
  distinct() %>%
  spread(key=position, value=n) %>%
  filter(RB>=2, TE>=1, WR>=3) %>%
  mutate(flex=case_when(RB==3 ~ 'RB',
                        TE==2 ~ 'TE',
                        WR==4 ~ 'WR')) %>%
  group_by(flex) %>%
  dplyr::summarize(pts=median(lineup_pts),
                   cases=n()) %>%
  knitr::kable() %>%
  kable_styling(full_width = FALSE)
flex pts cases
RB 157.0205 3887
TE 158.4635 3681
WR 157.8967 2432

Pretty even flex configurations, with RBs being the most popular TE’s the secons, and WR’s a distance third

Pareto Lineups

lu_df <- sim_lu %>%
  group_by(lineup) %>%
  dplyr::summarize(lineup_pts=sum(pts_pred),
                   lineup_sd=sum(sd_pts)) %>%
  ungroup()

pto <- psel(lu_df, low(lineup_sd) * high(lineup_pts))


ggplot(lu_df, aes(y=lineup_pts, x=lineup_sd)) +
  geom_point() +
  geom_point(data=pto, size=5) +
  ylab('Lineup Points') +
  xlab('Lineup Points St Dev') +
  ggtitle('Lineup Points vs Uncertainty',
          subtitle = 'Pareto Lineups Bolded')

Here’s a look at the pareto lineups.

psel(lu_df, low(lineup_sd) * high(lineup_pts)) %>%
  left_join(sim_lu, by='lineup') %>%
  group_by(lineup) %>%
  arrange(lineup_pts, position, desc(pts_pred)) %>%
  select(lineup, lineup_pts, lineup_sd, Name, team, position, pts_pred, sd_pts, Salary) %>%
  mutate_at(vars(lineup_pts, lineup_sd, pts_pred, sd_pts), function(x) round(x, 2)) %>%
  knitr::kable() %>%
  kable_styling(fixed_thead = T) %>%
  column_spec(1:3, bold=TRUE) %>%
  collapse_rows(columns = 1:3, valign = 'top') %>%
  scroll_box(height = '500px', width = '100%')
lineup lineup_pts lineup_sd Name team position pts_pred sd_pts Salary
8896 152.69 10.69 Ravens BAL DST 7.27 0.92 2200
Matt Ryan ATL QB 22.62 0.89 6300
Dalvin Cook MIN RB 22.17 0.92 8000
Leonard Fournette JAC RB 20.61 2.07 7000
Devonta Freeman ATL RB 16.44 1.10 5400
Hunter Henry LAC TE 16.11 1.59 4000
Tyler Boyd CIN WR 15.91 1.15 5600
Larry Fitzgerald ARI WR 15.86 0.98 6100
Calvin Ridley ATL WR 15.69 1.07 5300
95 155.26 11.99 Dolphins MIA DST 5.82 1.02 1500
Lamar Jackson BAL QB 24.47 1.01 6800
Leonard Fournette JAC RB 24.87 2.07 7000
Dalvin Cook MIN RB 21.26 0.92 8000
Kerryon Johnson DET RB 15.99 1.61 5100
Hunter Henry LAC TE 12.63 1.59 4000
T.Y. Hilton IND WR 18.34 1.77 5900
Stefon Diggs MIN WR 16.73 0.93 6300
Calvin Ridley ATL WR 15.16 1.07 5300
4225 160.51 12.21 Dolphins MIA DST 6.87 1.02 1500
Russell Wilson SEA QB 21.65 0.45 6600
Leonard Fournette JAC RB 25.57 2.07 7000
Chris Carson SEA RB 21.97 1.32 6500
Devonta Freeman ATL RB 16.46 1.10 5400
Hunter Henry LAC TE 13.05 1.59 4000
Keenan Allen LAC WR 20.62 2.27 6700
Robert Woods LAR WR 18.18 1.47 5900
Stefon Diggs MIN WR 16.13 0.93 6300
7601 160.55 12.80 Redskins WAS DST 7.24 1.35 1700
Lamar Jackson BAL QB 22.49 1.01 6800
Leonard Fournette JAC RB 24.24 2.07 7000
Dalvin Cook MIN RB 21.67 0.92 8000
Devonta Freeman ATL RB 17.38 1.10 5400
Hunter Henry LAC TE 13.89 1.59 4000
Keenan Allen LAC WR 21.47 2.27 6700
T.Y. Hilton IND WR 19.98 1.77 5900
Auden Tate CIN WR 12.20 0.74 4500
8770 164.73 13.21 Dolphins MIA DST 6.98 1.02 1500
Lamar Jackson BAL QB 23.62 1.01 6800
Dalvin Cook MIN RB 20.61 0.92 8000
Devonta Freeman ATL RB 17.73 1.10 5400
Kenyan Drake MIA RB 15.72 2.03 4100
Hunter Henry LAC TE 13.04 1.59 4000
Adam Thielen MIN WR 22.69 2.14 6900
T.Y. Hilton IND WR 22.39 1.77 5900
Cooper Kupp LAR WR 21.95 1.64 7400
1388 166.16 14.07 Giants NYG DST 7.18 0.25 2500
Matt Ryan ATL QB 24.05 0.89 6300
Leonard Fournette JAC RB 25.33 2.07 7000
Saquon Barkley NYG RB 24.64 3.31 8900
Josh Jacobs OAK RB 15.51 0.81 5000
Hunter Henry LAC TE 13.70 1.59 4000
T.Y. Hilton IND WR 22.84 1.77 5900
Cooper Kupp LAR WR 21.77 1.64 7400
Allen Lazard GBP WR 11.13 1.74 3000
507 167.32 14.40 Cardinals ARI DST 9.36 1.15 2400
Josh Allen BUF QB 23.67 2.07 6500
Leonard Fournette JAC RB 27.58 2.07 7000
Dalvin Cook MIN RB 22.26 0.92 8000
Mark Andrews BAL TE 18.61 2.51 4900
T.Y. Hilton IND WR 20.29 1.77 5900
Robert Woods LAR WR 17.41 1.47 5900
Tyler Boyd CIN WR 16.23 1.15 5600
Jake Kumerow GBP WR 11.90 1.30 3600
4923 170.09 14.66 Redskins WAS DST 9.34 1.35 1700
Deshaun Watson HOU QB 24.32 0.98 7000
Leonard Fournette JAC RB 23.97 2.07 7000
Devonta Freeman ATL RB 16.09 1.10 5400
Evan Engram NYG TE 22.20 2.33 6500
Hunter Henry LAC TE 15.03 1.59 4000
T.Y. Hilton IND WR 22.00 1.77 5900
Robert Woods LAR WR 19.34 1.47 5900
Tyler Lockett SEA WR 17.82 2.02 6600
9355 170.95 16.71 Dolphins MIA DST 7.32 1.02 1500
Lamar Jackson BAL QB 23.26 1.01 6800
Leonard Fournette JAC RB 24.80 2.07 7000
Dalvin Cook MIN RB 20.80 0.92 8000
Austin Hooper ATL TE 22.73 2.30 5300
Darren Waller OAK TE 15.27 3.21 4700
Michael Thomas NOS WR 25.68 2.37 7900
Kenny Golladay DET WR 18.28 2.07 5800
Allen Lazard GBP WR 12.81 1.74 3000
4991 172.08 17.11 Colts IND DST 7.53 1.06 2000
Josh Allen BUF QB 24.51 2.07 6500
Leonard Fournette JAC RB 22.31 2.07 7000
Kerryon Johnson DET RB 15.43 1.61 5100
Austin Hooper ATL TE 22.00 2.30 5300
Mark Andrews BAL TE 20.40 2.51 4900
Cooper Kupp LAR WR 21.20 1.64 7400
T.Y. Hilton IND WR 19.87 1.77 5900
Kenny Golladay DET WR 18.84 2.07 5800
7477 173.02 17.71 Colts IND DST 8.66 1.06 2000
Kyler Murray ARI QB 26.10 2.28 6700
Leonard Fournette JAC RB 23.52 2.07 7000
Devonta Freeman ATL RB 16.50 1.10 5400
Darren Waller OAK TE 21.40 3.21 4700
Mark Andrews BAL TE 16.38 2.51 4900
Cooper Kupp LAR WR 20.55 1.64 7400
Kenny Golladay DET WR 20.03 2.07 5800
T.Y. Hilton IND WR 19.88 1.77 5900
6284 173.79 18.10 Dolphins MIA DST 6.55 1.02 1500
Jared Goff LAR QB 21.13 0.60 6200
Leonard Fournette JAC RB 24.20 2.07 7000
Chris Carson SEA RB 19.14 1.32 6500
Austin Hooper ATL TE 17.76 2.30 5300
Marquez Valdes-Scantling GBP WR 27.61 5.42 5200
Adam Thielen MIN WR 23.50 2.14 6900
Kenny Golladay DET WR 17.44 2.07 5800
Tyler Boyd CIN WR 16.46 1.15 5600
8512 174.84 20.49 Redskins WAS DST 8.72 1.35 1700
Lamar Jackson BAL QB 24.37 1.01 6800
Saquon Barkley NYG RB 33.16 3.31 8900
Leonard Fournette JAC RB 21.35 2.07 7000
Chris Carson SEA RB 19.19 1.32 6500
Mark Andrews BAL TE 18.81 2.51 4900
Marquez Valdes-Scantling GBP WR 19.56 5.42 5200
T.Y. Hilton IND WR 18.48 1.77 5900
Allen Lazard GBP WR 11.21 1.74 3000
1184 177.66 21.29 Dolphins MIA DST 7.62 1.02 1500
Matt Ryan ATL QB 22.76 0.89 6300
Saquon Barkley NYG RB 24.13 3.31 8900
Devonta Freeman ATL RB 17.73 1.10 5400
Austin Hooper ATL TE 18.28 2.30 5300
Darren Waller OAK TE 16.33 3.21 4700
Marquez Valdes-Scantling GBP WR 28.55 5.42 5200
T.Y. Hilton IND WR 21.89 1.77 5900
Keenan Allen LAC WR 20.37 2.27 6700

Week 7 optimal lineups can be found here