Premier League Standings Flow Chart

ggplot
soccer
Bump charts with ggbump
Author

Andrew Weatherman

Published

May 19, 2024

Plot

This plot attempts to visualize the “standings flow” in the English Premier League during the 2023-24 campaign, with a focus on champions Manchester City and runners-up Arsenal.

What we will be creating

Full source code

library(tidyverse)
library(worldfootballR)
library(ggbump)
library(ggtext)
library(showtext)

## add Cairo font from google fonts
font_add_google("Cairo", "cairo")
showtext_auto()

## get the data from worldfootball R
## use purrr and weeks 1:38 to loop over all standings and weeks
data <- map_dfr(1:38, \(week) tm_matchday_table("England", start_year = "2023", matchday = week))

p <- data %>% 
  select(team = squad, week = matchday, place = rk) %>% 
  ## add fill colors and alpha levels based on whether teams are man city/arsenal or not
  mutate(
    fill_color = case_when(
      team == 'Man City' ~ '#6CABDD',
      team == 'Arsenal' ~ '#EF0107',
      .default = 'grey50'
  ),
    alpha = ifelse(team %in% c('Man City', 'Arsenal'), 1, 0.5)
  ) %>% 
  ggplot(aes(week, place, color = fill_color, group = team)) +
  geom_point(size = 1.7, aes(alpha = alpha)) +
  ## geom_bump from ggbump
  geom_bump(aes(alpha = alpha), linewidth = 0.7) +
  scale_color_identity() +
  ## customize our weeks lables
  scale_x_continuous(breaks = c(1, seq(10, 30, 10), 38),
                     labels = c("1st week", "10th", "20th", "30th", 'Final week')) +
  ## reverse the y-axis so 1st is plotted at the top and customize the labels
  scale_y_reverse(breaks = seq(1, 20, 1), labels = c("1st", seq(2, 19, 1), 'Last')) +
  theme_void() +
  theme(legend.position = 'none', # remove legend
        plot.title.position = 'plot',
        ## add the cairo font and change some sizes for saving
        plot.title = element_text(family = 'cairo', hjust = 0.5, size = 46, face = 'bold', vjust = 0),
        plot.subtitle = element_markdown(family = 'cairo', hjust = 0.5, size = 24),
        plot.caption.position = 'plot',
        plot.caption = element_text(family = 'cairo', hjust = 0.5, vjust = -2, size = 18),
        axis.text = element_text(family = 'cairo', size = 20),
        axis.text.x = element_text(vjust = -1),
        ## add light dotted major gridlines for viewing
        panel.grid.major.x = element_line(color = 'grey70', linetype = 'dotted'),
        panel.grid.major.y = element_line(color = 'grey70', linetype = 'dotted'),
        ## set margins
        plot.margin = unit(c(0.25, 0.5, 0.5, 0.5), "cm"),
        ## make background off-white
        plot.background = element_rect(fill = "#F6F7F2")) +
  labs(title = '2023-24 English Premier League Table Flow',
       ## with ggtext, we can use minor HTML to change color and weight of our subtitle
       subtitle = "<p>The fight between <span style='color:#6CABDD;'><b>Manchester City</b></span> and <span style='color:#EF0107;'><b>Arsenal</b></span> throughout the 2023-24 campaign</p>",
       caption = "Data by worldfootballR || Viz. by @andreweatherman")

## save
ggsave(plot = p, w = 6.16, h = 4.81, "premier_league_flow.png")