New Manager Bounce

Here I want to see if there is any truth that a new manager makes a team perform better. To do this I am going to look at data from the current Premier League season, and summarise overall team statistics before and after a new manager is brought in!

Getting Data

I downloaded Premier League data from the FPL API that I am going to read in here:

# Packages
library(tidyverse)
library(extrafont)
library(ggrepel)
library(dplyr)
library(ggimage)
library(Metrics)
source('Prediction-Functions.R')

# Read data
PlayerData <- read_csv("FPL-Gameweeks-28.csv")
TeamColours <- read_csv("Team-Colours.csv")

I also want to get fixture information, which is available from Vaastav’s FPL GitHub repository.

# Set github
Github <- "https://raw.githubusercontent.com/vaastav/Fantasy-Premier-League/master/data/2024-25/"

# Get fixture data
Fixtures <- read_csv(url(paste0(Github, "fixtures.csv"))) %>% 
  select(event, id, team_a, team_h) %>% unique()

Teams <- read_csv(url(paste0(Github, "teams.csv"))) %>% select(id, name)

Next I am just adding the fixture information for each player, so I know which team each player plays every week.

# Merge
PlayerData <- addFixtures(Fixtures, PlayerData)

# Add team names
Fixtures <- Fixtures %>% merge(Teams, by.x='team_a', by.y='id') %>% 
  rename('name_a'='name') %>% 
  merge(Teams, by.x='team_h', by.y='id') %>% 
  rename('name_h'='name', 'fixture'='id', 'gameweek'='event') 

# Add double gameweek for Man City and Aston Villa
Fixtures[233,3] <- 33

Next I am going to summarise attacking and defensive data for each team that brought in a new manager - this includes Everton, West Ham, Southampton, Wolves, Leicester and Man Utd.

# Summarise data
TeamData <- PlayerData  %>% 
  filter(team_name %in% c('Everton', 'West Ham', 'Southampton', 'Wolves', 'Leicester', 'Man Utd'))  %>% 
  group_by(team_name, gameweek, opponent)  %>% 
  summarise(match_xG=sum(expected_goals),
            match_xGC=max(expected_goals_conceded),
            match_G=sum(goals_scored),
            match_GC=max(goals_conceded))

# Modify totals for Everton double gameweek
TeamData$match_xG <- ifelse(TeamData$team_name=='Everton'&TeamData$gameweek==24, TeamData$match_xG/2, TeamData$match_xG)
TeamData$match_xGC <- ifelse(TeamData$team_name=='Everton'&TeamData$gameweek==24, TeamData$match_xGC/2, TeamData$match_xGC)
TeamData$match_G <- ifelse(TeamData$team_name=='Everton'&TeamData$gameweek==24, TeamData$match_G/2, TeamData$match_G)
TeamData$match_GC <- ifelse(TeamData$team_name=='Everton'&TeamData$gameweek==24, TeamData$match_GC/2, TeamData$match_GC)

Summarising Data

Next I want to adjust these scores by opponent difficulty. To do this I will summarise team xGC and xG over a season for each team to adjust each gameweek!

# Summarise data over season
TeamDataSeason <- PlayerData  %>% 
  group_by(team_name, gameweek)  %>% 
  summarise(match_xG=sum(expected_goals),
            match_xGC=max(expected_goals_conceded),
            games=max(starts))  %>% 
  group_by(team_name)  %>% 
  summarise(total_xG=sum(match_xG),
            total_xGC=sum(match_xGC),
            total_games=sum(games))  %>% 
  group_by(team_name)  %>% 
  summarise(mean_xG=total_xG/total_games,
            mean_xGC=total_xGC/total_games)  %>% 
  rename('opponent'='team_name')

# Merge with TeamData
TeamData <- merge(TeamData, TeamDataSeason)

# Adjust xG and xGC
TeamData$match_xG <- TeamData$match_xG/TeamData$mean_xGC
TeamData$match_xGC <- TeamData$match_xGC/TeamData$mean_xG
TeamData$match_G <- TeamData$match_G/TeamData$mean_xGC
TeamData$match_GC <- TeamData$match_GC/TeamData$mean_xG

Plotting Data

Now I can plot a performance ‘score’ which I will calculate by finding the mean of (xG - xGC) and (actual G - actual GC).

# Performance score
TeamData$score <- ((TeamData$match_xG-TeamData$match_xGC)+(TeamData$match_G-TeamData$match_GC))/2

# Summarise for each gameweek (discounts double gameweeks)
TeamData <- TeamData  %>% 
  group_by(team_name, gameweek)  %>% 
  summarise(match_xG=mean(match_xG),
            match_xGC=mean(match_xGC),
            match_G=mean(match_G),
            match_GC=mean(match_GC),
            mean_xG=mean(mean_xG),
            mean_xGC=mean(mean_xGC),
            score=mean(score))

# Add team colours
TeamDataPlot <- merge(TeamData, TeamColours, by.x='team_name', by.y='team')
col <- as.character(TeamDataPlot$colour1)
names(col) <- as.character(TeamDataPlot$team_name)

# Plot
CreatePlot <- function(Team){
  
  # Plot
  plot <- ggplot(TeamDataPlot %>% filter(team_name==Team), aes(x=gameweek, y=score, group=team_name, fill=team_name, colour=team_name))+
    theme_void()+
    geom_ribbon(data=TeamDataPlot %>% filter(team_name==Team), 
                aes(group=team_name, ymin=0, ymax=score), alpha=0.3, linewidth=1)+
    geom_point(size=3)+
    geom_point(size=1, colour='white')+
    scale_color_manual(values=col) +
    scale_fill_manual(values=col) +
    scale_x_continuous(n.breaks=28) +
    guides(colour='none', fill='none')+
    scale_y_continuous(expand=c(0.05,0.05))
  
  # Return
  return(plot)
  
}

# One plot
CreatePlot('Everton')

# Save all plots
ggsave(plot=CreatePlot('Leicester'), filename="LeicesterNewManager.png", bg="transparent", device="png")
ggsave(plot=CreatePlot('Wolves'), filename="WolvesNewManager.png", bg="transparent", device="png")
ggsave(plot=CreatePlot('Man Utd'), filename="ManUtdNewManager.png", bg="transparent", device="png")
ggsave(plot=CreatePlot('Southampton'), filename="SouthamptonNewManager.png", bg="transparent", device="png")
ggsave(plot=CreatePlot('Everton'), filename="EvertonNewManager.png", bg="transparent", device="png")
ggsave(plot=CreatePlot('West Ham'), filename="WestHamNewManager.png", bg="transparent", device="png")

Here I am just extracting some extra info that I can use on my infographic!

# Get means
M1 <- TeamDataPlot %>% filter(team_name=='West Ham', gameweek<21) %>% summarise(mean=mean(score))
M2 <- TeamDataPlot %>% filter(team_name=='West Ham', gameweek>20, gameweek<27) %>% summarise(mean=mean(score))
top3 <- TeamDataPlot %>% filter(team_name=='West Ham') %>% slice_max(score, n=3)

Making a Graphic

Next I put the 6 output graphs into Adobe Illustrator and annotated them with the mean score for the first manager, and the mean score for the first 6 weeks of the second manager.

You can see from looking at my made up ‘score’ metric, while West Ham have slightly improved with Graham Potter, it is only really Everton who have shown a big improvement after being taken over by David Moyes - although this is probably distorted by their fabulous performances against Liverpool (2-2) and Leicester (4-0) in week 24.