Hi all,
A quick tutorial today for soccer fans that want to shift their visualisations away from being built in python/R and build the output in Tableau!

We will be tackling the voronoi chart. Before we dive in here are some useful resources to help get started:
Using Voronoi Diagrams in Football – Ricardo Tavares – This is useful context on voronoi diagrams in regards to football theory.
How to create Football Pitches/Goals as Backgrounds in Tableau – James Smith – We will need some of the learnings from this to be able to ‘snap on’ our football pitch background!
MPLSoccer Voronoi – Andy Rowlinson – The original source code I used where you can follow the steps to get your own event data using the MPLSoccer package. We will be looking to recreate the voronoi shown here but within Tableau.
Voronoi Diagram in Python – Mckay Johns
What is a voronoi chart?
“In mathematics, a Voronoi diagram is a partition of a plane into regions close to each of a given set of objects. In the simplest case, these objects are just finitely many points in the plane (called seeds, sites, or generators). For each seed there is a corresponding region, called a Voronoi cell, consisting of all points of the plane closer to that seed than to any other. The Voronoi diagram of a set of points is dual to its Delaunay triangulation.” – Wikipedia.
Yeah, I’m still not sure after reading that either. So, you have a bunch of points. Each point has a surrounding area that will be closer to that point than others. That is what creates the area of the Voronoi. The lines therefore are created where two points are equidistant. The corners (nodes) will be created where three or more points are equidistant.
Why are they useful for soccer / football?
The Voronoi diagram is useful as it can be used to take a freeze frame of a match for example at the time a shot is taken, to present the space around each player. The border will therefore reflect the mid-point between one player and another player around them. There have been some really cool video analysis of showing this during a game.
SOURCE THE DATA
The data I used can be found in my Git Repo at the top of the page. The code also can be found there. Please familiarise yourself with the code in a console before proceeding!
So firstly, if you want to follow the tutorial, lets see which parts of the python code are important.

So to find the different polygon (voronoi shapes) for each team we will want to print team1 and team2 out in the console. You will see that they are captured in arrays.
These are our x and y values that we will plot in Tableau. How does this translate into our excel document? We split each array out. Path is really important here, and it something we manually create based off of the order they are shown in the array. We must make sure that the co-ordinates are joined up in the correct order!
We follow these steps for team2.

So now we know each block/shape is made up of co-ordinates that are joined up in an order using a path. But then we must include an ID for each block/shape, because otherwise Tableau will not know that they are their own distinct shape and will try aggregating the values. This is why you will see a shape column. The final column I have added is Team which will be used within the calculations as well as for colour!
We’re now in a position where we could build the Voronoi visualisation. However if we want to go one step further and include the player positions we need to add these co-ordinates to the dataset.
You will see these appended at the bottom of the dataset. These values come from the sample code again, but this time are the x and y values of the player positions, not the voronoi shape! Again, they are currently stored in an array.

Heres how the data will need to be prepped in excel.

Each set of co-ordinates in this case represent a Player. In this case we have split them again by team using a 1 or 2 notation.
CALCULATIONS
You can find a link to the viz that is downloadable using the links at the top of the page.
There are 5 calculations you will need. Here is an explanation of them.
001. Y Voronoi – We are just seperating our voronoi Y points from our player dot Y points to be able to distinguish between the two.
002. X Voronoi – Repeating the same process for our X points to only pick the ones that are going to be included in our voronoi chart.
We can check these calculations work by plotting them against each other, adding shape to detail and path to path.

003. X Player – Just like separating the Voronoi points out we must do the same for the player dots.
004. Y Player – Much the same as the co-ordinates for the x player but separating out the Y co-ordinate.
Again, we can sense check this.

If you do use these sense checks, remember to look at the axis. I tend to fix mine to be able to the same size to see any transformations.
Lastly we will want to layer the circles over the top of voronoi, as well as add a football pitch background. There are two methods of doing this. In truth map layers I find is easier, but for the sake of the tutorial I will show the old fashioned dual axis! If you’d like to look at my map layer alternative approach, see calculations 006 and 007.
BUILD THE VIZ
Data prepped, calculations made and sense checks done, finally time to build the final viz.

Drag Y Voronoi and Y Player onto Columns.
Drag X Voronoi and X Player onto Rows.
Make sure they are dimensions.

Dual and synchronise the axis.
Now let’s start with the Voronoi on the marks card (on the left under all)

Change the mark to polygon, add shape to detail, team to colour and path to path. You will want to make sure shape and path are dimensions. Amend the colours transparency.
Starting to look a bit more reasonable. We can at least see the pitch shape a bit more clearly!

Lets click into the Player on the marks card.
Add X and Y onto detail and team onto colour. Make sure the marks is a circle. These are our player points.
Finally let’s add the background football pitch. This is where James’ blog comes in handy.
Whilst on the sheet click map, background map.
Go to add image.
Locate your file of the pitch, you can find a copy of the pitch in both black and white, within the repo.

Use the above co-ordinates for now, however these are open to slight amendments.
You will see that I use the fields within my column and row bar of the sheet as the X and Y field! It is important to get these the right way round. In options lock the aspect ratio and always show the entire image.
Click apply and ok.

Finally it is a case of cosmetics, hiding the axis and removing the map movement control.
Go to map, Map options, uncheck the boxes of show layer control, toolbar and pan and zoom.
This removes zoom ability.
& There we have it! Our voronoi soccer viz.

SOME ERRORS THAT CAN OCCUR
I think one of the main difficulties will be with prepping the data, the path is really important to get right for polygons. So the path shows the order in which the co-ordinates are joined up.
I would recommend building your voronoi and players charts separately before trying to merge them together in a dual axis, as it will help with troubleshooting.
Snapping the pitch onto the chart can be a bit fiddly. Sometimes it doesn’t always apply correctly and save my values when I do it, make sure to go back and check your numbers and X/Y field is correct!
One REALLY important thing i’ve noticed is when using dual axis, is when you want to add a pitch background you have to use the first metric that is seen in your column and row header! Otherwise the pitch will not appear. I.e in my case it was the voronoi x and voronoi y fields.
GOING FURTHER
Try finding your own data using the statsbomb api or MPLSoccer python package
Try adding in the position of the ball in the freeze frame.
Try making the polygon into a line path to allow for the football pitch to show more easily. (Hint, no further data prep is required, It is just using the marks card!)
Try using a combination of colour and polygon/line to only highlight the spacing of the defending team.
Try using map layers to create the visualisation.
As always let me know how you got on with this one @_CJMayes
LOGGING OFF,
CJ