Introducing SPER: A way of rating teams based on Expected Goals Difference from Set Pieces

Marc Lamberts
7 min readDec 20, 2024

--

This year would be the year that I would immerse myself in set pieces. I know that is something I’ve said a lot and it was one of my goals this year — but life has a funny way of disrupting all plans. Now, this year I’ve done a lot on metric development and before the year closes I wanted to share one last metric development/methodology with you that concerns set pieces.

I’ve done a few things on set pieces:

But, I want to do a final one that goes further and proceeds on the thought pattern of the Individual Header Rating (IHR). I have looked at an individual level what players can contribute in terms of headers, but how do teams rate in set pieces? That’s what I’m trying to illustrate by introducing SPER. A way of rating Set Piece Expected Goals Differences between teams.

Why this metric for set piece analysis?

There isn’t a great necessity for this specific metric. One of the reasons is for me to try and make a power ranking based on expected goals for set pieces. However, with this insight we can create a way of rating team’s on their expected goals performance on set pieces and evaluate whether to rely on them.

In other words, with this metric, we can draw conclusions on how well teams are doing with their set piece xG. This can lead us to a few conclusions as to why teams need to rely on their set piece routines or to improve their open play, as to spread their win chances.

With this metric, we can combine this with the Individual Header Rating and gain meaningful analysis for set pieces, both on individual and team level.

Data collection and representation

The data used for this project comes from Opta/Statsperform and was collected on Thursday 18th of December 2024. All of the data is raw event data and from that XY-data, all the metrics have been developed, plotted, manipulated and calculated.

The data is from the Eredivisie 2024–2025 season and both contains match-level data as well as season-level data. There aren’t any filters used for value, but this is something that can be done in the next implementation of the score, as I will explain further on in this article.

This focuses on how teams are doing so that’s why the set piece xG are generated for each team and not for the individual players. We can split them for players, but it will not be as representative. The xG generated from set pieces often is the consequence of a good delivery as well, which would be nullified if we look at it from an individual angle.

There are different providers out there offering the XY-data, but I am sticking to Opta data for event data as all my research with event data has been done with Opta and therefore the continuity will improve the credibility of this work in line with my earlier work.

What is categorised as set piece?

This might seem like a very straightforward question, but one we need to talk about regardless. In the data there are different filters for our xG:

So, we need to make a distinction between different plays. We will focus on set pieces, but as you can see there are different variables:

  • SetPiece: Shot occurred from a crossed free kick
  • FromCorner: Shot occurred from a corner
  • DirectFreeKick: Shot occurred directly from a free kick
  • ThrowinSetPiece: Shot came from a throw-in set piece

These definitions come from Tom: https://github.com/tomh05/football-scores/blob/master/data/reference/opta-qualifiers.csv

I am excluding penalty. By all means it is a set piece, but the isolation of the play means that it’s such a big impact on the expected goals, that I will exclude it. It doesn’t say anything about the quality of play, but rather about the quality of kicktacking.

Methodology

There are a few steps I need to take before I get the SPER from my original raw data. The first step is to convert the shots I have into shots with an expected goal value. Which shots are listed?

  • Miss: Any shot on goal which goes wide or over the goal
  • Post: Whenever the ball hits the frame of the goal
  • Attempt saved: Shot saved — this event is for the player who made the shot.
  • Goal: all goals

We take these 4 events and convert them to shots with added value, by putting them through my own xG model that’s trained on 400.000 shots in the Eredivisie. We then get an excel/csv file like this:

This is the core we are working with, but the next step is to also calculate and generate what that means per game for each side. This will add to the xG values, but also win chance in % and the Expected Points given based on that expected goals.

So, now I have the two Excel files that form the base of my methodology and calculation. From here on, I’m going to focus on creating a new rating: SPER.

That has to happen in Python, because that’s my coding language of choice, and will need a few things.

This analysis combines match results and expected goals (xG) data using the Glicko-2 rating system to dynamically evaluate team performance. Match outcomes are determined by comparing xG values of home and away teams. A win, draw, or loss is assigned based on xG values:

Additionally, xG data for specific play types, such as “FromCorner” and “SetPiece,” is filtered and averaged for each team.

The scaling factor (0.1) ensures the adjustment is proportional and keeps outcomes between 0 and 1.

The Glicko-2 system updates team ratings after each match using adjusted outcomes. Each team has a rating (R), a rating deviation (RD), and a volatility (σ). Updates are based on the opponent’s rating and RD, incorporating the adjusted match outcome (S). The system calculates the new rating as:

This is obviously for all the technical mathematicians out there, however, this is the calculation that has been done in Python, but via code. By converting this into Python code, we get a ready to use excel that we can use in the analysis.

Analysis

With the data in the excel file, I know have ratings for every matchday for every team in the Eredivisie. It shows how well every team is doing and how they are progressing over the first half of the 2024–2025 season.

In the bargraph above you can see the final ratings for the Eredivisie with an average included. In the bargraph previous ratings are also included for every team. Feyenoord, FC Twente, AZ, PSV and Ajax are the best teams in terms of SPER. Fortuna Sittard, PEC Zwolle, NAC Breda and RKC Waalwijk are the worst.

In the line graph above, you can see how the ratings evolve over the course of the season for the top 5 teams in the Eredivisie for SPER. As we can see Feyenoord steadily becomes better, while PSV jave a more interesting trajectory with starting high and climbing again. Ajax really sinks in the last few weeks.

Final thoughts

The Glicko-2 scoring system provides a clear way to rank Eredivisie teams by combining match results and average expected goals (xG). It adjusts ratings dynamically, considering form and opponent strength, while xG adds context by reflecting goal-scoring chances. This approach gives a better understanding of team performance than traditional standings. However, its accuracy depends on reliable xG data and the chosen scaling factor for adjustments. Overall, the system is practical for tracking team progress and comparing strengths, offering useful insights for fans and analysts.

--

--

Marc Lamberts
Marc Lamberts

Written by Marc Lamberts

Academic | CAF A | Recruitment + data analysis consultant in football | Set pieces

Responses (5)