Visualizing Passing Events in Soccer Game

Visualizing Passing Events in Soccer Game

This brief post is about a course project on information visualization that I did last semester. Checkout .

Basic Idea

The data comes from StatsBomb, where you can get a timeline of whole sorts of events (such as passes, shots and goals) happening in a game. Yah, of course there are more than 60 games with a total size of 150 MB. But it seems to me that the data schema was quite well designed that I can work with that data as is in d3 without need any cleaning or processsing. For this project, we used all the FIFA 2018 games.

Once you have selected a game with the selector, you can see a soccer pitch on the left and a timeline on the right. For a given time range, it will extract all the pass events and draw them as solid (for successful ones) or dashed (for failed ones) lines between “players”. The circles representing each player are placed at the average positions of his involved events.

You can click on a player to see only events that he has been involved. Then the right side will appear a summary of his total number of passes, shots and goals during the selected time range.

More notes about the timeline: the area graph shows the pass frequency of the two teams along the game duration. The grey triangles are shots and the yellow ones are goals.

Overall, this tool is useful for user to visualize and explore the play patterns of different teams, which include team formation, player interactions and attack patterns.

Take Aways

This visualization was implemented with (pure) D3.js. D3 is a very flexible but also a low-level library for interactive visualization. Thus it is important to keep things organized when you are dealing with complex visualizations that involves dynamic interactions between multiple components. Here are some take aways:

Be clear about states of the vis.

There are many different states you need to maintain as your vis grow more and more complex, which include vis options, size of the container, async data loading, initialization of the visualization, binding status with other components …

Public methods should be provided to alternate the states and partially refresh the dom. By design, the actual dom or appearance should be a deterministic function of the maintained states, which makes it a lot easier to reason about.

What about extensibility?

Another issue is extensibility. Though in this project I do not need to worry about it, in practical visualization libraries that are meant to be reused by others, it is virtually important.

One great example is the set of TnT libraries developed by my GSoC mentor Miguel Pignatelli. You may check out the tnt.board API and tnt.genome API. The thing is that the tnt.genome library is implemented entirely on top of the flexible api of tnt.board. The mechanism of inheritance was also very clean and clever so that it requires only a small amount of code to implement the features in tnt.genome.


My teammate has made a wonderful wrap-up about the design for this project. Checkout !

d3  vis