Tracking Data Overview
Beginner
10 min read
0 views
Nov 27, 2025
# Tracking Data Overview
## Introduction
Player tracking data revolutionized basketball analytics by capturing spatial coordinates of all players and the ball at 25 frames per second. This guide introduces tracking data concepts and analysis.
## Understanding Tracking Data Structure
### Data Format
```python
import pandas as pd
import numpy as np
# Example tracking data structure
tracking_sample = {
'game_id': '0022300001',
'event_id': 1,
'timestamp': 0.04, # seconds
'quarter': 1,
'game_clock': 720.0,
'shot_clock': 24.0,
'ball': {'x': 25.0, 'y': 47.0, 'z': 10.0},
'home_team': [
{'player_id': 201935, 'x': 10.5, 'y': 20.3, 'speed': 2.1},
{'player_id': 203507, 'x': 15.2, 'y': 25.8, 'speed': 1.8},
# ... 3 more players
],
'away_team': [
# 5 players
]
}
```
## Python Analysis Framework
```python
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from scipy.spatial import distance
class TrackingAnalyzer:
def __init__(self, tracking_data):
"""Initialize with tracking DataFrame"""
self.data = tracking_data
self.court_length = 94 # feet
self.court_width = 50
def calculate_player_distance(self, player1_coords, player2_coords):
"""Calculate Euclidean distance between players"""
return distance.euclidean(player1_coords, player2_coords)
def calculate_spacing(self, team_coords):
"""Calculate team spacing metric"""
distances = []
for i in range(len(team_coords)):
for j in range(i+1, len(team_coords)):
dist = self.calculate_player_distance(
team_coords[i],
team_coords[j]
)
distances.append(dist)
return np.mean(distances)
def get_player_speed(self, player_id, start_frame, end_frame):
"""Calculate player speed over time window"""
frames = self.data[
(self.data['player_id'] == player_id) &
(self.data['frame'] >= start_frame) &
(self.data['frame'] <= end_frame)
]
# Calculate frame-to-frame distance
positions = frames[['x', 'y']].values
distances = np.sqrt(np.sum(np.diff(positions, axis=0)**2, axis=1))
# Speed in feet per second (25 fps)
speeds = distances * 25
return speeds.mean()
def plot_positions(self, frame_num):
"""Visualize player positions at specific frame"""
frame_data = self.data[self.data['frame'] == frame_num]
fig, ax = plt.subplots(figsize=(10, 5))
# Draw court boundaries
ax.plot([0, self.court_length], [0, 0], 'k-')
ax.plot([0, self.court_length], [self.court_width, self.court_width], 'k-')
ax.plot([0, 0], [0, self.court_width], 'k-')
ax.plot([self.court_length, self.court_length], [0, self.court_width], 'k-')
# Plot players
home = frame_data[frame_data['team'] == 'home']
away = frame_data[frame_data['team'] == 'away']
ax.scatter(home['x'], home['y'], c='blue', s=100, label='Home')
ax.scatter(away['x'], away['y'], c='red', s=100, label='Away')
# Plot ball
ball = frame_data[frame_data['is_ball'] == True]
ax.scatter(ball['x'], ball['y'], c='orange', s=50, marker='*', label='Ball')
ax.legend()
ax.set_xlim(-5, 99)
ax.set_ylim(-5, 55)
plt.show()
# Usage
# analyzer = TrackingAnalyzer(tracking_df)
# spacing = analyzer.calculate_spacing(team_positions)
```
## R Implementation
```r
library(dplyr)
library(ggplot2)
calculate_player_distance <- function(x1, y1, x2, y2) {
sqrt((x2 - x1)^2 + (y2 - y1)^2)
}
calculate_team_spacing <- function(team_coords) {
n <- nrow(team_coords)
distances <- c()
for (i in 1:(n-1)) {
for (j in (i+1):n) {
dist <- calculate_player_distance(
team_coords$x[i], team_coords$y[i],
team_coords$x[j], team_coords$y[j]
)
distances <- c(distances, dist)
}
}
mean(distances)
}
plot_tracking_frame <- function(tracking_data, frame_num) {
frame_data <- tracking_data %>% filter(frame == frame_num)
ggplot(frame_data, aes(x = x, y = y, color = team)) +
geom_point(size = 4) +
geom_point(data = frame_data %>% filter(is_ball),
aes(x = x, y = y),
color = "orange", size = 3, shape = 8) +
xlim(-5, 99) +
ylim(-5, 55) +
coord_fixed() +
theme_minimal() +
labs(title = paste("Frame", frame_num))
}
```
## Key Metrics from Tracking Data
1. **Spacing** - Average distance between teammates
2. **Speed/Distance** - Player movement metrics
3. **Defensive Pressure** - Closest defender distance
4. **Time in Paint** - Zone occupancy
5. **Ball Movement** - Passes and ball speed
## Data Sources
- NBA Advanced Stats (limited public access)
- Second Spectrum (NBA's official provider)
- STATS SportVU (legacy system)
- Research partnerships with teams
Discussion
Have questions or feedback? Join our community discussion on
Discord or
GitHub Discussions.
Table of Contents
Related Topics
Quick Actions