Shot map
Every shot a player takes in a season, placed on the pitch, sized by xG and coloured by outcome.
Visualizations
Everything here is built in Python with mplsoccer and matplotlib, from event data. Each project shows the output first and links to the notebook that produced it, so you can read the code as easily as the picture.
Maps — 4 examples
Every shot a player takes in a season, placed on the pitch, sized by xG and coloured by outcome.
Where a player's assists are delivered from and where they arrive.
Positional density split by offensive and defensive actions. The base spatial function reused across several of the projects below.
Passing — 10 examples
Average length and frequency of a player's passes by direction, in one shape.
Completion measured against the difficulty of the passes attempted: who beats their expected numbers, by how much, and against whom.
The same player seen three ways: build-up passes, progressive passes, and passes played straight after a defensive action.
Every pass from a position clustered into repeatable types, so players can be ranked on the clusters that actually carry value.
Carries — 3 examples
Where a player carries the ball, overall and when the carry moves play forward.
What those carries produce once the player gives the ball up.
Other work — 8 examples
Rolling xG for and against across a season, so form is separated from results.
Rolling values of a chosen metric, to show whether a team's level holds or swings.
One team's metrics compared across two seasons, gains and losses side by side.
How a team gets the ball into the penalty area, by route and by volume.
What players do in the seconds after they receive the ball, as a leaderboard and as a map.
Dribbles started with no run-up, the harder version of the skill, plus who does it best.