Chapter 8: Key Takeaways

Quick Reference Card

What is xA?

Expected Assists (xA) measures the quality of chances a player creates for teammates by summing the xG values of shots resulting from their passes.

  • Value range: Typically 0-0.4 per key pass
  • Interpretation: Higher xA = better quality chances created
  • Relationship: xA of a pass = xG of the resulting shot

Core Formulas

Basic xA Calculation

xA_player = Σ(xG of shots from player's key passes)

xA per 90 Minutes

xA_90 = xA_total / (minutes / 90)

Key Pass Rate

KP_rate = key_passes / total_passes × 100

Assist vs xA Difference

Δ_assist = actual_assists - xA

Positive = overperformance; Negative = underperformance


Typical Values

Metric Average Good Elite
xA per 90 (AM) 0.12 0.20 0.30+
xA per 90 (Winger) 0.15 0.22 0.35+
Key passes per 90 1.5 2.5 3.5+
xA per key pass 0.08 0.12 0.16+

Pass Type xG Values

Pass Type Typical xG Notes
Through ball 0.15-0.25 Highest quality, lowest volume
Cutback 0.12-0.20 High quality from byline
Regular penalty area pass 0.08-0.12 Standard chance
Cross 0.04-0.08 Lower quality but high volume
Set piece delivery 0.05-0.10 Variable by situation

Essential Python Code

Calculate xA from Events

def calculate_xa(shots_df, passes_df):
    """Calculate xA for all players."""
    xa_data = []

    for _, shot in shots_df.iterrows():
        kp_id = shot.get('shot_key_pass_id')
        if pd.notna(kp_id):
            kp = passes_df[passes_df['id'] == kp_id]
            if len(kp) > 0:
                xa_data.append({
                    'player': kp.iloc[0]['player'],
                    'xA': shot['shot_statsbomb_xg'],
                    'assist': shot['shot_outcome'] == 'Goal'
                })

    xa_df = pd.DataFrame(xa_data)
    return xa_df.groupby('player').agg({
        'xA': 'sum',
        'assist': 'sum'
    }).rename(columns={'assist': 'assists'})

Key Pass Identification

# Using StatsBomb data
key_passes = passes_df[passes_df['pass_shot_assist'] == True]

# Manual linkage (if needed)
def is_key_pass(pass_row, shots_df, time_threshold=10):
    """Check if pass led to a shot within time threshold."""
    same_team_shots = shots_df[
        (shots_df['team'] == pass_row['team']) &
        (shots_df['minute'] >= pass_row['minute']) &
        (shots_df['minute'] <= pass_row['minute'] + time_threshold/60)
    ]
    return len(same_team_shots) > 0

Pass Type Classification

def classify_key_pass(pass_row):
    """Classify pass type for analysis."""
    if pass_row.get('pass_through_ball'):
        return 'through_ball'
    elif pass_row.get('pass_cross'):
        return 'cross'
    elif pass_row.get('pass_cut_back'):
        return 'cutback'
    else:
        return 'regular'

Shot-Creating Actions

def calculate_sca(events_df, n_preceding=2):
    """Calculate Shot-Creating Actions."""
    shots = events_df[events_df['type'] == 'Shot']
    sca_counts = {}

    for shot_idx in shots.index:
        shot = events_df.loc[shot_idx]
        preceding = events_df[
            (events_df.index < shot_idx) &
            (events_df['team'] == shot['team'])
        ].tail(n_preceding)

        for _, action in preceding.iterrows():
            player = action['player']
            if player:
                sca_counts[player] = sca_counts.get(player, 0) + 1

    return sca_counts

Key Concepts

Shot-Creating Actions (SCA) vs xA

Metric What It Counts Best For
xA Only the final pass (key pass) Direct creativity
SCA Last 2 actions before shot Broader involvement
GCA Last 2 actions before goal Goal contribution

xA Interpretation Guidelines

Individual Shot Level: - xA = xG of shot created - Single passes range from 0.02 to 0.50+ xA

Match Level: - Sum all key passes by player - Top creators: 0.3-0.6 xA per match

Season Level: - Total xA correlates with actual assists (r ≈ 0.7) - Over/underperformance regresses to mean


Common Pitfalls

1. Ignoring Sample Size

  • Problem: Judging creativity from 5 key passes
  • Solution: Require 20+ key passes for reliable conclusions

2. Not Accounting for Position

  • Problem: Comparing CAM xA to CB xA
  • Solution: Use positional percentiles

3. Set Piece Inflation

  • Problem: Corner/FK takers have inflated xA
  • Solution: Separate open play vs. set piece xA

4. Ignoring Teammate Quality

  • Problem: Playing with clinical finishers boosts assist totals
  • Solution: Focus on xA, which removes conversion dependency

5. Confusing xA with Passing Quality

  • Problem: Thinking xA measures pass difficulty
  • Solution: Remember xA = shot quality, not pass quality

Applications Summary

Application Key Metric What It Shows
Player scouting xA per 90 Creativity rate
Style analysis Pass type breakdown How they create
Team tactics Team xA distribution Creation patterns
Partnership Passer-shooter xA Combination effectiveness
Luck/skill Assists vs xA Teammate conversion

Pass Types and Values

Through Balls

  • Definition: Pass into space behind defense
  • Characteristics: High risk, high reward
  • Typical success rate: 30-40%
  • When successful: Generates 0.15-0.25 xG

Crosses

  • Definition: Pass from wide to central penalty area
  • Characteristics: High volume, lower per-pass value
  • Typical success rate: 20-30%
  • When shot results: Generates 0.04-0.08 xG

Cutbacks

  • Definition: Pass from byline backward into box
  • Characteristics: High quality when executed
  • Typical success rate: 50-60%
  • When shot results: Generates 0.12-0.20 xG

Quick Reference: Evaluation Steps

For Individual Players:

  1. Calculate total xA and xA per 90
  2. Compare to positional benchmarks
  3. Analyze pass type breakdown
  4. Check assists vs. xA (luck factor)
  5. Consider team/tactical context

For Team Analysis:

  1. Sum team xA per match
  2. Compare creation methods (cross vs. through ball)
  3. Analyze set piece vs. open play split
  4. Identify key creative players
  5. Assess tactical style signature

One-Page Summary

xA = Sum of xG from shots you create

  1. xA measures creativity independent of teammate finishing
  2. Different pass types have different typical xG values
  3. Through balls > Cutbacks > Regular > Crosses for xA per pass
  4. SCA broadens the view to all shot-contributing actions
  5. Context matters: position, team style, set pieces
  6. Sample size: need 20+ key passes for stability
  7. Assists will regress toward xA over time
  8. Compare to positional benchmarks not raw totals