Learn R Programming

⚠️There's a newer version (0.9.5) of this package.Take me there.

soccermatics

soccermatics provides tools to visualise spatial tracking and event data from football (soccer) matches. There are currently functions to visualise shot maps (with xG), average positions, heatmaps, and individual player trajectories. There are also helper functions to smooth, interpolate, and prepare TRACAB-style x,y-coordinate data for plotting and calculating further metrics.

Many more functions are planned - see To Do List, suggestions and/or help welcomed!

The sample x,y-coordinate data in tromso and tromso_extra were made available by Pettersen et al. (2014), whilst the event data in statsbomb is taken from the World Cup 2018 data made public by StatsBomb.

Use of the name soccermatics kindly permitted by the eponymous book's author, David Sumpter.

soccermatics is built on R v3.4.2.


Installation

You can install soccermatics from GitHub in R using devtools:

if (!require("devtools")) install.packages("devtools")
devtools::install_github("jogall/soccermatics")

library(soccermatics)

Examples

Below are some sample visualisations produced by soccermetrics with code snippets underneath. See the individual help files for each function (e.g. ?soccerHeatmap) for more information.

Shotmaps (showing xG)

Dark theme:

statsbomb %>%
  filter(team.name == "France") %>%
  soccerShotmap(theme = "dark")

Grass theme with custom colours:

statsbomb %>%
  filter(team.name == "Argentina") %>%
  soccerShotmap(theme = "grass", colGoal = "yellow", colMiss = "blue", legend = T)
Passing networks

Default aesthetics:

statsbomb %>%
  filter(team.name == "Argentina") %>%
  soccerPassmap(fill = "lightblue", arrow = "r",
                title = "Argentina (vs France, 30th June 2018)")

Grass background, non-transparent edges:

statsbomb %>%
  filter(team.name == "France") %>%
  soccerPassmap(fill = "blue", minPass = 3,
                edge_max_width = 30, edge_col = "grey40", edge_alpha = 1,
                title = "France (vs Argentina, 30th June 2018)")
Heatmaps

Passing heatmap with approx 10x10m bins:

statsbomb %>%
  filter(type.name == "Pass" & team.name == "France") %>% 
  soccerHeatmap(x = "location.x", y = "location.y",
                title = "France (vs Argentina, 30th June 2016)", 
                subtitle = "Passing heatmap")

Defensive pressure heatmap with approx 5x5m bins:

statsbomb %>%
  filter(type.name == "Pressure" & team.name == "France") %>% 
  soccerHeatmap(x = "location.x", y = "location.y", xBins = 21, yBins = 14,
                title = "France (vs Argentina, 30th June 2016)", 
                subtitle = "Defensive pressure heatmap")

Player position heatmaps also possible using TRACAB-style x,y-location data.

Average position

Average pass position:

statsbomb %>% 
  filter(type.name == "Pass" & team.name == "France" & minute < 43) %>% 
  soccerPositionMap(id = "player.name", x = "location.x", y = "location.y", 
                    fill1 = "blue", grass = T,
                    arrow = "r", 
                    title = "France (vs Argentina, 30th June 2016)", 
                    subtitle = "Average pass position (1' - 42')")

Average pass position (both teams):

statsbomb %>% 
  filter(type.name == "Pass" & minute < 43) %>% 
  soccerPositionMap(id = "player.name", team = "team.name", x = "location.x", y = "location.y",
    fill1 = "lightblue", fill2 = "blue", label_col = "black",
    repel = T, teamToFlip = 2,
    title = "France vs Argentina, 30th June 2018",
    subtitle = "Average pass position (1' - 42')")

Average player position using TRACAB-style x,y-location data:

tromso_extra[1:11,] %>% 
  soccerPositionMap(grass = T, title = "Tromsø IL (vs. Strømsgodset, 3rd Nov 2013)", subtitle = "Average player position (1' - 16')")
Custom plots

Inbuilt functions for many of these will be added soon.

Locations of multiple events:

d2 <- statsbomb %>% 
  filter(type.name %in% c("Pressure", "Interception", "Block", "Dispossessed", "Ball Recovery") & team.name == "France")

soccerPitch(arrow = "r", 
            title = "France (vs Argentina, 30th June 2016)", 
            subtitle = "Defensive actions") +
  geom_point(data = d2, aes(x = location.x, y = location.y, col = type.name), size = 3, alpha = 0.5)

Start and end locations of passes:

d3 <- statsbomb %>% 
  filter(type.name == "Pass" & team.name == "France") %>% 
  mutate(pass.outcome = as.factor(if_else(is.na(pass.outcome.name), 1, 0)))

soccerPitch(arrow = "r",
            title = "France (vs Argentina, 30th June 2016)", 
            subtitle = "Pass map") +
  geom_segment(data = d3, aes(x = location.x, xend = pass.end_location.x, y = location.y, yend = pass.end_location.y, col = pass.outcome), alpha = 0.75) +
  geom_point(data = d3, aes(x = location.x, y = location.y, col = pass.outcome), alpha = 0.5) +
  guides(colour = FALSE)
Player paths

Path of a single player:

subset(tromso, id == 8)[1:1800,] %>%
  soccerPath(col = "red", grass = TRUE, arrow = "r",
             title = "Tromsø IL (vs. Strømsgodset, 3rd Nov 2013)",
             subtitle = "Player #8 path (1' - 3')")

Path of multiple players:

tromso %>%
  dplyr::group_by(id) %>%
  dplyr::slice(1:1200) %>%
  soccerPath(id = "id", arrow = "r", 
             title = "Tromsø IL (vs. Strømsgodset, 3rd Nov 2013)", 
             subtitle = "Player paths (1')")

Updates

The package is constantly getting a makeover and may occassionally break. Should installation fail at any time, please install the last stable version (v0.8.4) from this tarball like so:

install.packages("https://github.com/JoGall/soccermatics/blob/master/soccermatics_0.8.4.tar.gz", repo=NULL, type="source")

Copy Link

Version

Version

0.9.0

License

GPL (>=3.0) Note: Use of the name 'soccermatics' was kindly permitted by David Sumpter and is protected from commercial use under EU copyright law.

Maintainer

Joe Gallagher

Last Published

August 9th, 2021

Functions in soccermatics (0.9.0)

soccerFlipHoriz

Flips x,y-coordinates horizontally in one half to account for changing sides at half-time
soccerPositionMap

Plot average player position
soccerHeatmap

Draw a heatmap on a soccer pitch.
soccerFlow

Draw a flow field on a soccer pitch.
soccerPassmap

Draw a passing network on a pitch from StatsBomb data
soccerSpokes

Visualise movement direction on a soccer pitch.
tromso

x,y-coordinates of 11 soccer players over 12000 frames each
tromso_extra

x,y-coordinates and additional positional information on 11 soccer players over 12000 frames each
soccerTransformSB

Normalises all x,y-coordinate data from StatsBomb data
soccerTransform

Normalises x,y-coordinates to metres units for use with soccermatics functions
soccerVelocity

Compute instantaneous distance, speed and direction from x,y-coordinates
soccerPath

Draw a path of player trajectory on a soccer pitch.
soccerPitchBG

Plot a soccer pitch ggplot object
soccerResample

Resample the frequency of x,y,t- time series with linear interpolation of x,y-coordinates.
soccerShotmap

Draw a shotmap on a half pitch from StatsBomb data
soccerPitchFG

Helper function to add soccer pitch outlines to an existing ggplot object
soccerFlipDirection

Flips x,y-coordinates horizontally in one half to account for changing sides at half-time
soccerShortenName

Extract shortened player names
soccerPitch

Plot a soccer pitch ggplot object
statsbomb

Sample StatsBomb event data containing the x,y-locations and identity of players involved in pass events, shot events, defensive actions, and more.