#15: Getting Started with Free StatsBomb Event Data – xG Shot Map Tutorial

Introduction

After attending StatsBomb’s Introduction to Football Analytics last week, I was inspired to take another look at the free events data that they offer. One of the main obstacles to breaking into the football analytical industry is getting data to play around with and show what you can do, which is why Statsbomb’s commitment to offering such samples of data for free is so amazing and should be taken advantage of! There are endless possibilities of insight and visualisations to create using the event data, limited only by your creativity.

Support and free tutorials are also freely available for using data in R, including their own StatsBombR package and FCrStats’s twitter and GitHub who provides functions for creating custom pitches for visualisations. Did I mention they were both free?

https://github.com/statsbomb/StatsBombR & @StatsBomb
https://github.com/FCrSTATS & @FC_rstats

It can be intimidating to start to work with complex data like this, so I will go through step by step and create a version of a popular match visualisation: an Expected Goals Shot Map.

Since the Fifa Women’s World Cup is currently taking place and the StatsBombR package is continually being updated with new games as they are played, I thought I’d use the recent England v Argentina game as an example.

Install RStudio

FOr those completely new to R, you can download the latest RStudio version here:

https://cran.r-project.org/

And install packages using:

install.packages(“…package name here…”)

Load Libraries

To start we will load the relevant libraries.

library("StatsBombR") # Event data
library("SBpitch")    # Custom functions for creating pitches
library("ggplot2")    # Building visualisations 
library("tidyverse")  # Data manipulation

Create Blank Pitch

Using FCrStat’s SBpitch package you can create a pitch to use with custom visualisations using the create_Pitch() function. You can specify the colours and which lines you want to see. For the xG Shot Map, we will use the whole pitch.

# Create a blank pitch using create_Pitch()
blank_pitch <- create_Pitch(
  goaltype = "box",
  grass_colour = "#202020", 
  line_colour =  "#797876", 
  background_colour = "#202020", 
  goal_colour = "#131313"
)

blank_pitch

unnamed-chunk-2-1

Get StatsBomb Data

Using the StatsBombR package, getting access to the free events data is as simple as running the StatsBombFreeEvents() function as below and storing it in your environment.

statsbomb_events <- StatsBombFreeEvents()

## [1] "Whilst we are keen to share data and facilitate research, we also urge you to be responsible with the data. Please register your details on https://www.statsbomb.com/resource-centre and read our User Agreement carefully."

Get Match Info

There are over 100 variables for each event of each match, so we want to narrow the data set down to a single match. We are interested in the Fifa Women’s World Cup match with England v Argentina. We are also only interested in shots, so will only include those types of events.

I have also included the colours for the respective teams to use later on.

The x,y location of each event is stored in a single variable as an array.
Using the separate() function in the Tidyverse we can extract these and create new variables called “location_x” and “location_y”.
Use as.numeric() to make the new location variables numeric so we can plot them later.

event_type <- "Shot"
team1_colour <- "red4"
team2_colour <- "lightblue"

# Narrow down to a specific match: Australia Women's v Brazil Women's
match <- statsbomb_events %>%
  filter(# Fifa Women's World Cup Competition ID
           competition_id == 72 & 
           # Eng Womens v BArg Women's Match ID
           match_id == 22962 & 
           # Only keep events that are shots
           type.name == event_type ) %>%
  # X,Y locations are stored in a single array column, separate() into two columns
  separate(col = location, into = c(NA, "location_x","location_y")) %>%
  mutate(location_x = as.numeric(location_x),
         location_y = 80 - as.numeric(location_y))

Create Goal and xG Indicators

Since we are interested in the actual goals and expected goals of each shot, we can create a goal indicator variable and respective expected goal variables for the shots of each team.

match <- match %>%
  mutate(# Create a goal indicator
         Goal = ifelse(shot.outcome.name == "Goal","1","0"),
         # Create England goal indicator and xG
         team1_Goal = ifelse((shot.outcome.name == "Goal" & team.name == unique(match$team.name)[1]),"1","0"),
         team1_xG = ifelse(team.name == unique(match$team.name)[1],shot.statsbomb_xg,NA),
         # Create Argentina goal indicator and xG
         team2_Goal = ifelse((shot.outcome.name == "Goal" & team.name == unique(match$team.name)[2]),"1","0"),
         team2_xG = ifelse(team.name == unique(match$team.name)[2],shot.statsbomb_xg,NA)
)

Plot Shot Locations

Okay, lots of preparation done so far. Let’s plot some shots!

ggplot2 builds plots from the ground upwards. Remember the blank_pitch we made earlier? We use that as a base and add the shot locations on top using geom_point to add points/dots

# Plotting raw shot locations
blank_pitch + 
  geom_point(data = match, aes(x=location_x, y=location_y), colour = "white")

unnamed-chunk-5-1

Oops, looks like all the shots happened at the same end, regardless of team. We need to reverse the shot locations of one team, since we know the pitch dimensions from create_Pitch() as 120 x 80, we can use those.

# Looks like all shots are at the same end, need to reverse the locations of one team
match <- match %>%
  mutate(location_x = ifelse(team.name == unique(match$team.name)[1],
                             120 - location_x,
                             location_x),
         location_y = ifelse(team.name == unique(match$team.name)[1],
                             80 - location_y,
                             location_y)
         )

Plot Respective Coloured Locations

Let’s see if it worked!

# Try again, with different colours for each team
blank_pitch + 
  geom_point(data = match, aes(x=location_x, y=location_y, colour = team.name)) +
  theme(legend.position="none") + 
  scale_colour_manual(values = c(team1_colour, team2_colour))

unnamed-chunk-7-1

Oof, looks like England had lots of shots and denied Argentina anything significant.

Highlight Goals

We have shot locations, but it would be nice to see which shots are goals using the goal indicator we created earlier and we can use a different shape (triangle) to differentiate.

# Now highlight the goals
blank_pitch + 
  geom_point(data = match, aes(x=location_x, y=location_y, colour = team.name, shape = Goal)) +
  theme(legend.position="none") + 
  scale_colour_manual(values = c(team1_colour, team2_colour))
unnamed-chunk-8-1

Plot Size of xG

Looks like England scored from their shot closest to the goal in the Argentina 6-yard box. Let’s see how likely they were to score by using the size of the points to reflect the expected goals.

# Now use size to reflect shot xG
blank_pitch + 
  geom_point(data = match, aes(x=location_x, y=location_y, colour = team.name, shape = Goal, size = shot.statsbomb_xg)) +
  theme(legend.position="none") + 
  scale_colour_manual(values = c(team1_colour, team2_colour))
unnamed-chunk-9-1

Looks like England scored with their best chance and could potentially have scored a few more considering their volume of relatively good shots. This is a skeleton of an Expected Goals Shot Map, we can add in annotations to make the final plot look more presentable and quantify each team’s expected goals versus actual goals.

Add Titles and Annotations

blank_pitch + 
  geom_point(data = match, aes(x=location_x, y=location_y, colour = team.name, shape = Goal, size = shot.statsbomb_xg)) +
  theme(legend.position="none") + 
  scale_colour_manual(values = c(team2_colour, team1_colour)) + 
  # Australia's xG
  geom_text(aes(x = 2, y=78,label = unique(match$team.name)[1]), hjust=0, vjust=0.5, size = 5, colour = team1_colour) +
  geom_text(aes(x = 2, y=75,label = paste0("Expected Goals (xG): ",round(sum(match$team1_xG, na.rm = TRUE),2))), hjust=0, vjust=0.5, size = 3, colour = team1_colour) + 
  geom_text(aes(x = 2, y=73,label = paste0("Actual Goals: ",round(sum(as.numeric(match$team1_Goal), na.rm = TRUE),0))), hjust=0, vjust=0.5, size = 3, colour = team1_colour) + 
  geom_text(aes(x = 2, y=71,label = paste0("xG Difference: ",round(sum(as.numeric(match$team1_Goal), na.rm = TRUE),0)-round(sum(match$team1_xG, na.rm = TRUE),2))), hjust=0, vjust=0.5, size = 3, colour = team1_colour) +
  # Brazil's xG
  geom_text(aes(x = 80, y=78,label = unique(match$team.name)[2]), hjust=0, vjust=0.5, size = 5, colour = team2_colour) +
  geom_text(aes(x = 80, y=75,label = paste0("Expected Goals (xG): ",round(sum(match$team2_xG, na.rm = TRUE),2))), hjust=0, vjust=0.5, size = 3, colour = team2_colour) + 
  geom_text(aes(x = 80, y=73,label = paste0("Actual Goals: ",round(sum(as.numeric(match$team2_Goal), na.rm = TRUE),0))), hjust=0, vjust=0.5, size = 3, colour = team2_colour) + 
  geom_text(aes(x = 80, y=71,label = paste0("xG Difference: ",round(sum(as.numeric(match$team2_Goal), na.rm = TRUE),0)-round(sum(match$team2_xG, na.rm = TRUE),2))), hjust=0, vjust=0.5, size = 3, colour = team2_colour)
unnamed-chunk-10-1

That looks a little better, at least we now know the score and how each team did compared to their expected goals. After creating a blank pitch, we only need to add layers to get a visualisation of the information we want which is incredibly powerful. To get the visualisation for another match, simply change the match_id (and team colours) above!

The only packages used to create this are those loaded above, with the free events data provided by StatsBomb and extra functions/tutorials by FCrStats

Again, you can find those two here:
@StatsBomb
@FCrStats

Hopefully this will help get some people get started and overcome any initial intimidation. I will look to provide more of these types of step by step guides going forwards the more I get to play around with the data.

@TLMAnalytics

#11 Normalizing xG Chain – Are all actions created equal?

Featured

In this post I will be taking a look at the concepts of xG Chain (xGC) and xG Buildup (xGB), why they are useful and how we can develop these concepts to get even more use from them. Both of these concepts further the expected goals (xG) and expected assists (xA) metrics, allowing the contribution of players not directly involved in a goal to be accounted for.

xG is a likelihood attached to each shot that attributed the chance of that shot being a goal. This metric is only really useful for players who take lots of shots, such as forwards.

xA is attached to a pass that immediately precedes a shot, the xA measures the likelihood that a pass will become an assist from the following shot.. This metric aims to widen the influence of the xG metric and attribution of play to the creative players who create the shots that the xG provides information for.

Both of these are intuitive and simple concepts that provide an estimate for specific actions on the pitch. Since goals and assists are key events in a match, it makes sense to focus analysis on them since they are incredibly predictive. xG and xA are very limited however, they only care about a shot and the preceding pass so don’t tell us anything about any of the play that happens leading up to there. It turns out that the majority of football isn’t just taking turns taking shots, so it would be nice to be able to do something like xG/xA for other actions on the pitch.

Just as xA is to xG; attributing the result to the preceding pass, xG Chain is to xA where it aims to do the same thing for the whole preceding possession chain. In this way you can widen the influence of xG to all players that are involved in the preceding possession. Where xG mainly highlights forwards and xA mainly highlights creative players, xG Chain aims to highlight players that make contributions to the possessions that end up with a shot. These could include your ‘assisting the assister’ players, your deep lying playmakers like Jorginho who get criticised for lack of assists or your progressive passing defenders that wouldn’t usually get the credit they potentially deserve for starting effective possessions.

Calculating xG Chain: https://statsbomb.com/2018/08/introducing-xgchain-and-xgbuildup/

  • Find all possessions each player is involved in
  • Find all shots within those possessions
  • Sum the xG of those shots (usually take the highest xG per possession)
  • Assign that sum to each player, however involved they are

You can normalise xGC per 90mins to see contributions per match, however this still highlights forwards and creative players since if they are the players getting the shots then they will get all the credit for their own shots plus any other possession chains they are involved in.

Since the aim is to highlight players that xG and xA don’t directly pick up, you can calculate xGC without including the shots and assists to get xG Buildup. This leaves all of the preceding actions to the assist and the shot, or all of the build up play as it were. By removing assists and shots, the dominance of forwards is removed and the remaining players are heavily involved in all the play up to just before the defining assist and shot. You can also normalize xGB per 90 mins to see contributions per match. Again, each player involved gets equal contribution as long as they are involved in the possession chain in some way.

xG Chain and especially xG Buildup are great metrics that highlight the contributions of players leading up to assists and shots. They allow players that don’t contribute directly to goals to make a case for their own importance. Normalising per 90 mins is an effective way to allow for reduced player minutes due to injury or substitutions, and evaluate all players on the same basis.

As great as the concepts of xGC and xGB are, there is a clear and influential flaw in the calculation when assigning the xG of the possession chain to the players involved. Each player gets equal contribution no matter how involved they were. So player A makes a simple 5 yard pass in their own half gets the same assigned contribution as player B who made the decisive through ball to a player who squared it for an open goal. Neither player would get credit in xG/xA but both would get the same xGC/xGB contribution despite the fact that player A’s contribution was potentially arbitrary and player B’s turned the possession chain from probing to penetrating and a shot on goal.

Another way to consider the contributions of each player is if you were to remove the action of that player, how likely was the possession chain to have still occurred. If you remove player A’s simple pass, it doesn’t take much for the possession chain to maintain its low threat whereas if you remove player B’s decisive through ball then it’s unlikely that the possession chain continues in the same way. In this way, player B’s contribution could be argued to be more important than player A’s.

This leads to considering other ways of normalising xGC and xGB, each method of assigning contribution and normalising will highlight different aspects of the build up.

Since you have all the information of each possession chain, you may have access to the number of passes or touches that each player contributed to the chain. If you proportion the xGC out by the frequency of passes or touches you can get a good idea of the proportion of involvement that each player has in each possession chain. For example, if a possession chain involves two players, C and D, where player C made 3 passes and player D made 4 passes with a resulting shot that has an xG of 0.7. Then player C contributed 3/7 passes so gets an xGC of 3/7 * 0.7 = 0.3 and player D contributed 4/7 passes so gets an xGC of 4/7 * 0.7 = 0.4. Since player D was involved slightly more than player C then player D gets a higher xGC. A similar calculation can be made using touches which will consider players who dribble more than just counting passes.

You aren’t limited to just counting passes or touches of the ball, you can get more creative with the allocations if you want to credit specific types of actions. You could only count progressive passes that move the ball forward by at least 10 yards, try to quantify the most important or necessary actions of a possession chain (decisive through ball/taking on a player in the box) or count the number of opposition players taken out of the game by each player involved, where ‘taking a player out the game’ may be defined as moving the ball closer to the defending team’s goal than the player.

xG Chain and xG Buildup are both intuitive and simple metrics that assign contributions to players that don’t get directly involved in taking shots or assists but are frequently involved in preceding actions to these events. On their own they can already highlight players that seem to contribute well under the ‘eye-test’ when you watch them, but they can be misleading and provide many false positives since all actions are considered equal under xG Chain.

@TLMAnalytics

Credit to Statsbomb and Thom Lawrence for introducing concepts and providing clear explanations and examples. They even include free data sets for FAWSL and the 2108 FIFA World Cup if anyone wants to try themselves. Check them out here:

https://statsbomb.com/

 #5 Defensive Metric Concepts [Expected Shot Block]

Featured

There are emerging metrics in football such as Expected Goals, Key Passes, Progressive Passes and even now Expected Assists. These are all measuring single events in a football match and quantifying their utility or effectiveness with an indicator or a probability of happening. These are also all measurements of how effective a player is at executing actions whilst on the ball, particularly in offensive positions such as shooting or creating shots from passes. They give us a better idea for which players and teams are most (or least) effective at offensive events. The higher your Expected Goals and the more Key Passes you make, the more goals your team is likely to score. However, there aren’t similar metrics that measure defensive contribution. This may be due to the act of contributing to goal scoring being an objective decision, with each goal scored there is a single player who scored it and it’s easy to allocate contributions. With allocating defensive contribution, it is hard to quantify the presence of a non-event. It is hard to quantify how much of an effect a player or team has on the opposition not scoring. I think that if it’s possible to quantify a sensible defensive metric of any kind then it could be as useful as any of the offensive metrics above, I will use this series to brainstorm some ideas of such defensive metrics and how it would be possible to compute them.

Expected Shot Block:

Where better to start with defensive metrics than with the clearest act of denying a goal, the shot block. This concept is in direct competition to and is inspired by the concept of Expected Goals.

For Expected Goals, each shot is given a probability of being a goal based on historical shots of a similar type. For example, a shot that is taken with the head from a cross may be given 0.1 xG whereas a shot from a counter attack inside the 6-yard box may be given 0.5 xG. It suggests that the shot from a counter is 5 times more likely to go in than the headed effort. These may not be realistic numbers but the concept stands. Some shots are more likely to go in than others depending on a number of factors including where on the pitch the shot was taken, what play led to the shot, what the shot is taken with and game state of the match.

The concept of the Expected Shot Block would be to calculate the probability that the shot is blocked by a defender. This would require more information than just the event data of the shot, it would require the knowledge of the presence of a defender and how likely it is that a defender makes a block in a similar situation based on historically similar shots. The time this decision is made would be at point of contact of the shot. Based on shots from the past, you can categorise them into similar categories as that of Expected Goals but with the added factor of the presence of a defender or defenders between the ball location and the goal. The ball location and the two posts of the goal create a triangle and if there are any defenders in this area then the shot would be identified as having the potential to be blocked. The presence of the goalkeeper is expected and since we are looking at shots being blocked not saved then the goalkeeper’s location can be acknowledged but not required for calculation. The location of the goalkeeper may alter the shot direction of the attacker so may affect shot blocking numbers.

Expected Shot Block - FM

Furthering the concept of an Expected Shot Block would be to calculate the percentage of the goal that is open to the shot at the point of contact. When identifying if a shot has the potential to be blocked, you can calculate the percentage of the goal that is available to be shot at where the defenders wouldn’t make a block. This calculation could be done in either 2D or 3D. You can assume an average area for the defender’s body and block out the area of the goal that the defender is in front of. In 2D this would be less accurate than in 3D since it would be assumed that the defender can block a shot of any height. Whereas in 3D, you could create silhouettes of the defender’s limbs and create a more accurate percentage that way.

There are some problems with this concept but I think it has potential. You need more than just event information, you also need player location data which is harder to get. It also assumes that the shot is a direct hit straight at goal, whereas many players attempt to bend and curl the ball around defenders. Just because a defender is in the way of the goal, doesn’t guarantee a blocked shot in that location. There are many times where a shot goes through a defender’s legs or just past a limb, defenders and players aren’t perfect.

It’s hard to quantify defensive actions and shot blocking seemed to have the most relevant as it’s related to the current set of offensive metrics, it’s not perfect. If anyone has any thoughts or comments regarding other issues I may have missed, please do let me know!

@TLMAnalytics

#4 Team Analysis: AS Monaco – Realistic Expectations

Featured

In this piece I will take a look at AS Monaco’s Ligue 1 performance to see why they are sitting in 19th after 13 games. Looking at their recent transfers, I’ll investigate what their expectations would have been compared to what their expectations should be.

This is a team that only two years ago won the Ligue 1 title, holding top spot for most of the season, and was a team full of emerging young talent. Players such as Kylian Mbappe, Bernado Silva, Thomas Lemar, Benjamin Mendy, Tiemoue Bakayoko and Fabinho all contributed greatly alongside veterans such as Radamel Falcao and Joao Moutinho. This season the only player still at the club is still Falcao, Monaco were a club that thrived off the talent of these rising stars and cashed in. Larger European clubs such as Paris Saint Germain, Manchester City, Atletico Madrid, Chelsea and Liverpool all came in and stripped Monaco of their title winning team.

Since the system worked so well previously, it’s not hard to see why they have tried to replicate their success and have looked to reinvest in a new crop of youngsters to compliment the likes of Falcao once again. They have brought in the likes of Youri Tielemans, Pietro Pellegri, Willem Geubells, Benjamin Henrichs and Aleksandr Golovin who are all under 22, with Pelegri and Geubells both 16 at the time they were brought in. The concept which they are trying to repeat is to build the team around giving these promising youngsters lots of playing time, hoping to accelerate their development and mature early, therefore prolonging their careers at the highest level.

This transition couldn’t happen overnight, and has taken two years for these recruitment changes to occur. Last year Monaco managed a 2nd place finish behind a resurgent PSG team, which is respectable considering they loaned Paris their best asset in Mbappe for the year and lost Bernado Silva and Mendy to Manchester City. That’s a lot of attacking threat to lose, however they managed to keep hold of Lemar, Fabinho and Moutinho. Fabinho and Moutinho are two competent central midfielders who can take control of any given game, allowing Monaco the foundation to let their forwards do their thing. It could be suggested that losing Fabinho to Liverpool and Moutinho to Wolves in the summer before this season are the losses that were hardest to replace. Fabinho has proved himself worthy of a spot in a Jurgen Klopp midfield three which is saying something and Moutinho is part of the Portuguese midfield duo at a Wolves team proving themselves already a competent Premier League team.

Out of those youngsters brought in over the last two years, only Youri Tielemans has the suggested promise to be able to replace either. However, Tielemans has been playing in a more offensive midfield role previously at Anderlecht and Belgium, relying on a young player who’s still getting used to controlling a game from deep may not be the best idea.

That moves us on to Monaco’s current crisis, they sit 19th in Ligue 1 after 13 games and just been thrashed 4-0 for the second time by PSG [PSG have won their opening 13 games and sit 13 points clear]. After 9 games, Leonardo Jardim, who was in charge of their title winning season, mutually agreed with the club to leave and has been replaced by Thierry Henry in his first managerial role.

Monaco v PSG 11Nov18

A team that has finished 1st and 2nd in the previous two seasons shouldn’t be anywhere near the bottom of the league at this point of the season. They have underperformed their xG and xGA across the 13 games, so they haven’t scored as many as they should and have conceded more than they should have. Though not by a huge margin, they have 12 goals from 16.31 xG and conceded 22 from 17.47 xGA. Regressing to the mean, we can expect Monaco to perform better than current standings suggest, but that is nowhere near challenging for the title. Based on previous seasons, expectations would be to dominate most games by creating lots of chances and giving away few. Their goal difference of -10 and xGD of -1.16 shows a difference in expectation versus reality but compared to 2nd place Lille’s xGD of +7.28 [PSG’s xGD = 23.66] shows how far away from pre-season expectations they are.

Except, there doesn’t seem to be anything clearly wrong. Their defence is as leaky as suggested, conceding 1.69 goals per game. They aren’t creating enough good chances to score the goals to win games, scoring 0.92 goal per game. They have had 150 shots, creating 15 big chances but conceded 154 shots and 19 big chances so far. Most worrying is that they aren’t controlling games, they aren’t putting the opposition under pressure and they seem to be playing in matches on a level playing field with many of the teams in the league. So far this season they are performing like an unlucky mid table side, nowhere near their expectations of European qualification.

When I say there doesn’t seem to be anything clearly wrong, I mean that there doesn’t seem to be anything immediately fixable wrong. It’s not the case that they can change just one thing and go back to being the title challenging side they used to be. That’s because they are literally a completely different team to that one, even if the expectation hasn’t changed, the players definitely have and they are not as good as those who left. Unfortunately, it seems as though Monaco’s attempts to recruit a new group of young title winners, or at least challengers haven’t worked so far. Which isn’t surprising. It will take time for the players to get used to playing in a top 5 European league and playing with each other and handling the expectations all at once. They aren’t suddenly a bad team, just not what they were last year and the expectations surrounding the team need to reflect that. It is also worth noting that they have had some serious injury concerns which has forced them to play maybe more youngsters than planned.

*credit to Understat and @Statszone for the numbers and figure

@TLMAnalytics

#2 Team Analysis: The Rise (and Rise?) of Deportivo Alaves

I will take a look at the intriguing situation that Deportivo Alaves have found themselves in. Comparing where they were a year ago to where they are now, I will look to identify whether or not their current results are sustainable.

In 2016/2017, Mauricio Pellegrino managed Alaves to 9th place in their first season back in La Liga for 6 seasons. This was a great achievement and quickly drew the eyes of the Premier League where he went on to manage Southampton. Luis Zubeldia, an Argentine who had never managed in Europe before, took over for the start of the 2017/2018 season before being sacked after losing and failing to score in each of the first four games. Gianni De Biasi, who was previously the Albania coach who managed to qualify them to their first major tournament, replaced Zubeldia. Though he managed to get them their first goals and wins, it wasn’t enough as after only two months in charge his contract was terminated as Alaves sat rock bottom of the La Liga table on 6 points. They had 2 wins and 11 losses from 13 games, only scoring 7 goals and conceding 22. After a great first season back in La Liga finishing 9th the year before, this wasn’t exactly how they’d hoped the start of their second season would go. Since then, Abelardo Fernandez has been in charge and has won 19 out of 35 La Liga games, winning 1.74 points per game. Alaves would’ve finished 5th in the 2017/2018 season had they maintained that across a season and qualified for Europe. After 10 games in the current 2018/2019 season, Alaves find themselves 2nd only behind Spanish giants Barcelona.

Apart from the set back early in 2017/2018, Alaves have proved they are well worth their place in La Liga. In only their 3rd season back to La Liga they are sitting in 2nd place, I will take a look at the stats behind their recent fixtures to judge how sustainable their recent results have been.

So far Alaves have won 6 games, drawn 2 games and lost 2 games, meaning they are at 2 points per game and results are better than average across Fernandez’ tenure. They have scored 14 goals and conceded only 9, however their expected goals (xG) is 10.41 and expected goals against (xGA) is 13.59. Alaves are outperforming their expected returns at both ends of the pitch, they are scoring more than and conceding less than is expected based on the shots that have occurred. When a team is outperforming their expected goals, it is usually not sustainable, elite level finishing is the exception. We can expect that Alaves will regress back to the mean, wherever that mean is.

Even though Alaves have outperformed their xG/xGA as a total, looking at each match they’ve played individually tells a different story. Since they appear to be over performing expectation, you may expect that they over perform in each game. This is not the case as there is only one game that they have won where they had a lower xG than their opponent (1.10 – 0.85 vs Real Valladolid [away]). This includes their win against Real Madrid in which they snatched victory in the last-minute to earn a 1-0 win with xG of 0.95 – 0.84.

Two games in particular highlight the importance of looking at individual games, their first game away to Barcelona and their away trip to Rayo Vallecano. Barcelona thrashed Alaves 3-0 on the opening day after receiving a guard of honour for winning the title last year, with xG of 3.27 – 0.25. So 3.27/13.59 of xGA and 3/9 of their goals against all came in the first game, in the nine games since then they have had an xG of 10.32 and conceded 6. They are still out performing xGA, however it’s a much more representative view. Several games later, Alaves won 1-5 away to Rayo Vallecano with xG of 1.08 – 1.25. Helped out by a Rayo Vallecano red card and some excellent finishing in the first half, they created some higher xG chances in the second half with more space to counter into and ran away with the game. There were 5/14 of Alaves’ goals but only 1.25/10.41 xG in this game, meaning that in the other nine games they had and scored nine goals from 9.16 xG which looks much more reasonable and sustainable.

Rayo Vallecano v Deportivo Alaves

Across each individual game the xG prediction for a winner is correct 70% of the time (2 draws and 1 loss), if Alaves carry on putting up these numbers for xG and xGA then there’s no reason why their success isn’t sustainable. The only question is whether they can keep it up. Of course, xG doesn’t win you games, actual real-life goals do. Let’s delve into what type of goals and when these goals are scored.

Alaves haven’t scored a single goal in the middle 15 minutes of any half (15-30/60-75mins). This means all of their goals have come at the start or the end of a half, these are very good times to score. A goal at the start of a half will put you on the front foot and a goal at the end of the half gives the opposition little time to react, if it’s just before half time you can go and regroup whilst if it’s just before the end of the game there’s usually no time for reply. It is not a conscious decision when they decide to score but provides insight into the flow of how Alaves try to play. Explosive starts to each half with a quieter middle to relax before ending strongly. Alaves are very good at finishing halves but whether that style of play is sustainable is another matter, out of the 10 games they’ve played in they have scored in 90+ minutes five times. This has won them three games and drawn one meaning that they have gained seven points from last-minute goals. That is not sustainable.

Considering that Alaves appear to be over performing their expected returns at both ends at a total level, the fact that they have scored goals in 90+ minutes in half of their La Liga games and they are currently sitting at 2 points per game which is above their average in the last year, it doesn’t appear that their current results are sustainable. That’s not to say that they will revert back to the relegation battling side a year ago, but they will regress back to their mean somewhere in between.

Credit to understat.com once again for their amazing site and xG models. Check them out.

@TLMAnalytics