Chapter 9: Key Takeaways

Quick Reference Card

What is xT?

Expected Threat (xT) measures the probability that possessing the ball at a given location will lead to a goal in subsequent actions.

  • Value range: Typically 0.002 (own half) to 0.40+ (central penalty area)
  • Interpretation: Higher xT = more dangerous position
  • Key insight: Position has value independent of the action taken

Core Formulas

xT Value Iteration

xT(zone) = P(shot|zone) × xG(zone) + P(move|zone) × E[xT(destination)]

xT Added by Action

xT_added = xT(end_zone) - xT(start_zone)

xT per 90 Minutes

xT_90 = total_xT / (minutes_played / 90)

Progressive Pass Definition

is_progressive = end_distance_to_goal < 0.75 × start_distance_to_goal

Typical xT Values by Zone

Zone xT Range Interpretation
Own penalty area 0.002-0.005 Recovery/clearance
Own half 0.005-0.015 Build-up phase
Central midfield 0.015-0.030 Transition zone
Final third (wings) 0.020-0.050 Crossing positions
Final third (center) 0.040-0.100 Dangerous territory
Edge of box 0.080-0.150 High threat
Inside penalty area 0.150-0.350 Very high threat
Central 6-yard box 0.300-0.500+ Maximum threat

Typical Player Values by Position

Position xT per 90 (Average) xT per 90 (Elite)
Goalkeeper 0.01-0.03 0.05+
Center-Back 0.05-0.10 0.15+
Full-Back 0.10-0.18 0.25+
Defensive Mid 0.08-0.15 0.22+
Central Mid 0.15-0.25 0.35+
Attacking Mid 0.25-0.40 0.50+
Winger 0.20-0.35 0.45+
Striker 0.15-0.30 0.40+

Progressive Actions Reference

Progressive Passes

Metric Average Good Elite
Progressive passes per 90 4-6 8-10 12+
Progressive pass distance per 90 150-250m 300-400m 450m+
Passes into final third per 90 2-4 5-7 8+
Passes into penalty area per 90 0.5-1.5 2-3 4+

Progressive Carries

Metric Average Good Elite
Progressive carries per 90 2-4 5-7 8+
Progressive carry distance per 90 80-150m 180-250m 300m+
Carries into final third per 90 1-2 3-4 5+

Essential Python Code

Grid Setup

def coord_to_zone(x, y, grid_size=(12, 8), pitch_dims=(120, 80)):
    """Convert coordinates to zone indices."""
    zone_x = int(x / pitch_dims[0] * grid_size[0])
    zone_y = int(y / pitch_dims[1] * grid_size[1])
    zone_x = max(0, min(zone_x, grid_size[0] - 1))
    zone_y = max(0, min(zone_y, grid_size[1] - 1))
    return zone_x, zone_y

def zone_to_index(zone_x, zone_y, grid_size=(12, 8)):
    """Convert zone to flat index."""
    return zone_y * grid_size[0] + zone_x

xT Calculation

def calculate_xt_added(event, xt_values):
    """Calculate xT added by a single action."""
    start_idx = zone_to_index(*coord_to_zone(event['start_x'], event['start_y']))
    end_idx = zone_to_index(*coord_to_zone(event['end_x'], event['end_y']))
    return xt_values[end_idx] - xt_values[start_idx]

Progressive Pass Check

def is_progressive_pass(start_x, start_y, end_x, end_y):
    """Check if pass meets 25% closer rule."""
    goal_x, goal_y = 120, 40
    start_dist = np.sqrt((goal_x - start_x)**2 + (goal_y - start_y)**2)
    end_dist = np.sqrt((goal_x - end_x)**2 + (goal_y - end_y)**2)
    return end_dist < 0.75 * start_dist

Player xT Aggregation

def calculate_player_xt(events_df, xt_values):
    """Calculate total xT for each player."""
    player_xt = {}
    for _, event in events_df.iterrows():
        if event['type'] not in ['Pass', 'Carry']:
            continue
        player = event['player']
        xt_added = calculate_xt_added(event, xt_values)
        if player not in player_xt:
            player_xt[player] = 0
        player_xt[player] += xt_added
    return player_xt

Framework Comparison

Aspect xT VAEP EPV
Data needed Event only Event + features Tracking
Complexity Low Medium High
Interpretability High Medium Low
Accuracy Moderate Good High
Computational cost Low Medium High
Best for Quick analysis Detailed evaluation Premium insights

Common Applications

Player Scouting

  1. Calculate xT per 90 for all players at target position
  2. Compare to positional benchmarks
  3. Decompose xT into passes vs. carries
  4. Analyze consistency across matches
  5. Consider team context and playing style

Tactical Analysis

  1. Calculate team xT by pitch zone
  2. Identify preferred progression routes
  3. Compare build-up patterns between teams
  4. Analyze xT generation by game state
  5. Track tactical changes over time

Player Development

  1. Baseline xT metrics at start of period
  2. Track progression over time
  3. Compare to development targets
  4. Identify specific areas for improvement
  5. Adjust training based on insights

Common Pitfalls

1. Ignoring Position Context

  • Problem: Comparing xT across positions
  • Solution: Use position-specific percentiles

2. Not Accounting for Team Style

  • Problem: Possession teams inflate xT totals
  • Solution: Compare within similar tactical systems

3. Overvaluing Volume

  • Problem: High xT from many low-value actions
  • Solution: Consider xT per action alongside totals

4. Ignoring Risk

  • Problem: High xT players may lose ball frequently
  • Solution: Combine xT with action success rate

5. Set Piece Inflation

  • Problem: Corner/FK takers get artificial xT boost
  • Solution: Separate open play vs. set piece xT

6. Grid Resolution Mismatch

  • Problem: Using wrong grid for data density
  • Solution: Match resolution to sample size (more data = finer grid)

Quick Evaluation Steps

For Individual Players:

  1. Calculate total xT and xT per 90
  2. Compare to positional benchmarks
  3. Break down by action type (pass/carry)
  4. Check action success rate
  5. Consider team context

For Team Analysis:

  1. Sum team xT per match
  2. Identify which zones generate most xT
  3. Compare to opponent xT allowed
  4. Analyze temporal patterns
  5. Correlate with results

One-Page Summary

xT = Position Value + Action Value

  1. Position has inherent value: Being in dangerous areas matters even before acting
  2. xT captures build-up contributions: Values all ball-advancing actions, not just shots
  3. Progressive actions simplify xT: 25% closer rule provides interpretable metric
  4. Compare within positions: A CB's 0.10 xT/90 may be elite; an AM's 0.25 may be average
  5. Combine with risk measures: High xT is less valuable if it comes with high turnover
  6. Context matters: Team style, opponent, and game state affect interpretation
  7. Multiple frameworks exist: xT, VAEP, EPV offer different tradeoffs
  8. Validate against outcomes: xT should correlate with goals at team level