Skip to content

Tracking Data

A tracking data feed provides X/Y/(Z) coordinate data showing the position of all players and the ball. The data is collected using in-stadium optical tracking systems or based on broadcast video. In-stadium tracking data typically has a higher accuracy and provides the locations of all players and the ball, while broadcast-based tracking data only includes the positions of on-camera players.

One widely used open dataset is the Metrica Sports dataset. Below, we demonstrate how to load tracking data from Metrica Sports using kloppy:

1
2
3
4
5
6
from kloppy import metrica

dataset = metrica.load_open_data(
    match_id=1, 
    limit=1000  # Optional: load the first 1000 frames only
)

This will create a TrackingDataset that wraps a list of Frame entities. The tracking data is sampled at a fixed frame rate, available via the metadata.frame_rate attribute.

>>> print(dataset.metadata.frame_rate)
25

This value represents the number of frames recorded per second. For example, a frame rate of 25 means there are 25 frames per second of game time.

The remainder of this section explains the Frame entities. Later sections of the user guide will explain in-depth how to process a tracking dataset.

Kloppy’s tracking data model

Kloppy uses Frame objects to store tracking data. Each frame contains:

  • The exact moment the frame was recorded.
  • The (x, y) coordinates of the ball.
  • A mapping of player identifiers to their (x, y) coordinates.

To inspect a specific frame, use indexing on the dataset.frames list. For example, to access the frame at index 500:

frame = dataset.frames[500]

Timestamp

The .timestamp attribute returns a Time object representing when the frame was recorded.

>>> print(frame.time)
P1T00:20

For more on the Time object, see the next section.

Ball coordinates

The .ball_coordinates attribute provides the position of the ball as a Point object:

>>> print(frame.ball_coordinates)
Point(x=0.37413, y=0.33704999999999996)

Some tracking data providers also include the ball's height (z-axis). In those cases, .ball_coordinates will return a Point3D object instead.

Player coordinates

Each Frame includes a .players_coordinates dictionary. This maps each Player object to a Point indicating the player’s location on the pitch.

>>> print(f"Number of players in the frame: {len(frame.players_coordinates)}")
Number of players in the frame: 22

Example: Coordinates of Home Team Players

1
2
3
4
5
6
7
8
>>> home_team, away_team = dataset.metadata.teams
>>> print("List home team players coordinates", [
...    player_coordinates 
...    for player, player_coordinates
...    in frame.players_coordinates.items()
...    if player.team == home_team
... ])
List home team players coordinates [Point(x=0.09609, y=0.51082), Point(x=0.34208, y=0.24092000000000002), Point(x=0.36416, y=0.33575999999999995), Point(x=0.31874, y=0.38464), Point(x=0.32943, y=0.5150600000000001), Point(x=0.46178, y=0.19284), Point(x=0.42934, y=0.30888000000000004), Point(x=0.39962, y=0.39798), Point(x=0.46043, y=0.63039), Point(x=0.55401, y=0.44205000000000005), Point(x=0.51692, y=0.32194)]