Get FPL Review data.

list.files()
[1] "fpl_review_optimizaton.html" "fpl_review_optimizaton.Rmd" 
[3] "fplreview_1659427467.csv"    "rsconnect"                  
fpl_review <- read.csv("fplreview_1659427467.csv")

Load packages.

library(tidyverse)
library(lpSolve)

Team formation

Choose a strong team of 11 players with one good substitute. Defenders are best values so pick five of them. The absence of one cheap goalkeeper (4.0 million), a midfielder (4.5 million), and a forward (4.5 million) should enable this optimization for a price of 87 million.

Num_G = 1
Num_D = 5
Num_M = 4
Num_F = 2

Squad value

team_value = 87

Create vectors for each position.

fpl_review$Goalkeeper = ifelse(fpl_review$Pos == "G", 1, 0)
fpl_review$Defender = ifelse(fpl_review$Pos == "D", 1, 0)
fpl_review$Midfielder = ifelse(fpl_review$Pos == "M", 1, 0)
fpl_review$Forward = ifelse(fpl_review$Pos == "F", 1, 0)

Create team constraints.

team_constraint = unlist(lapply(unique(fpl_review$Team), function(x, fpl_review){
ifelse(fpl_review$Team == x, 1, 0)
}, fpl_review = fpl_review))

Objective function

objective.fn = fpl_review$X1_Pts + fpl_review$X1_Pts + fpl_review$X2_Pts + fpl_review$X3_Pts + fpl_review$X4_Pts + fpl_review$X5_Pts

Constraints matrix

const.mat = matrix(c(fpl_review$Goalkeeper, fpl_review$Defender, fpl_review$Midfielder, fpl_review$Forward,
fpl_review$BV, team_constraint),
nrow=(5 + length(unique(fpl_review$Team))),
byrow=TRUE)

Constraint directions

const.dir <- c("=", "=", "=", "=", "<=", rep("<=", 20))

Right hand side of equation

const.rhs = c(Num_G, Num_D, Num_M, Num_F, team_value, rep(3, 20))

Solve the linear equation.

mod = lp(direction = "max", objective.fn, const.mat, const.dir, const.rhs, all.bin=TRUE, all.int=TRUE)

Dream Squad

dream_squad <- fpl_review[which(mod$solution==1),]
dream_squad %>% 
  arrange(desc(Goalkeeper), desc(Defender), desc(Midfielder), desc(Forward)) %>%
  summarise(Name, Team, Pos, BV, X1_Pts, X2_Pts, X3_Pts, X4_Pts, X5_Pts)
               Name      Team Pos   BV X1_Pts X2_Pts X3_Pts X4_Pts X5_Pts
1           Ederson  Man City   G  5.5   4.22   4.77   4.17   4.54   4.57
2             James   Chelsea   D  6.0   4.43   3.64   4.07   4.42   4.02
3  Alexander-Arnold Liverpool   D  7.5   5.77   6.01   3.98   6.26   5.44
4           Cancelo  Man City   D  7.0   4.56   5.64   4.37   5.19   5.30
5              Dias  Man City   D  6.0   4.10   5.12   4.08   4.77   4.90
6           Perišić     Spurs   D  5.5   4.24   2.56   4.39   4.06   3.34
7              Saka   Arsenal   M  8.0   4.51   4.84   4.44   5.11   4.71
8        Martinelli   Arsenal   M  6.0   4.13   4.29   4.03   4.52   3.87
9             Salah Liverpool   M 13.0   7.75   7.32   5.25   7.82   6.95
10        Luis Díaz Liverpool   M  8.0   5.21   5.03   3.59   5.08   4.57
11            Jesus   Arsenal   F  8.0   4.69   4.95   4.52   5.31   4.77
12         Mitrović    Fulham   F  6.5   3.32   3.94   4.59   3.05   4.15

Week One Starting Eleven

week_1 <- dream_squad %>% top_n(11, X1_Pts) %>%
  arrange(-X1_Pts) %>%
  summarise(Name, Team, Pos, X1_Pts)
week_1
               Name      Team Pos X1_Pts
1             Salah Liverpool   M   7.75
2  Alexander-Arnold Liverpool   D   5.77
3         Luis Díaz Liverpool   M   5.21
4             Jesus   Arsenal   F   4.69
5           Cancelo  Man City   D   4.56
6              Saka   Arsenal   M   4.51
7             James   Chelsea   D   4.43
8           Perišić     Spurs   D   4.24
9           Ederson  Man City   G   4.22
10       Martinelli   Arsenal   M   4.13
11             Dias  Man City   D   4.10

Week One Substitute

dream_squad %>% top_n(-1, X1_Pts) %>% select(Name, X1_Pts)
      Name X1_Pts
1 Mitrović   3.32

Week One Predicted Points

week_1 %>% select(X1_Pts) %>% summarise(team = sum(X1_Pts),
                                        captain = max(X1_Pts),
                                        total = team + captain)
   team captain total
1 53.61    7.75 61.36

Week Two Starting Eleven

week_2 <- dream_squad %>% top_n(11, X2_Pts) %>%
  arrange(-X2_Pts) %>%
  summarise(Name, Team, Pos, X2_Pts)
week_2
               Name      Team Pos X2_Pts
1             Salah Liverpool   M   7.32
2  Alexander-Arnold Liverpool   D   6.01
3           Cancelo  Man City   D   5.64
4              Dias  Man City   D   5.12
5         Luis Díaz Liverpool   M   5.03
6             Jesus   Arsenal   F   4.95
7              Saka   Arsenal   M   4.84
8           Ederson  Man City   G   4.77
9        Martinelli   Arsenal   M   4.29
10         Mitrović    Fulham   F   3.94
11            James   Chelsea   D   3.64

Week Two Substitute

dream_squad %>% top_n(-1, X2_Pts) %>% select(Name, X2_Pts)
     Name X2_Pts
1 Perišić   2.56

Week Two Predicted Points

week_2 %>% select(X2_Pts) %>% summarise(team = sum(X2_Pts),
                                        captain = max(X2_Pts),
                                        total = team + captain)
   team captain total
1 55.55    7.32 62.87


Comment: It’s just a template but it’s a start and I’m very happy that it looks better than any of my manual selections. To beat the template, watch the games or highlights and listen to managers for updates about players’ availability, fitness, form. Optimize weekly and take a punt at your peril.