Causality APIs 20: The Goalie Change Saved The Series. Or Did Shot Quality Change?

A goalie change can look like the cause of fewer goals against, but it is often selected by the same defensive breakdowns that change shot quality.

A National Hockey League (NHL) playoff team changes goalies. The next game looks cleaner. The broadcast booth reaches for the simple sentence: the goalie change saved the series.

That might be true. But a goalie switch is rarely random. Coaches make it after score pressure, defensive breakdowns, rebound trouble, or a run of dangerous chances.

A goalie change can reduce goals against, but the observed before-and-after comparison may mostly be measuring the defensive situation that forced the change.

Share: A goalie switch can look causal when the real change is happening in front of the net. #Causality #NHL #SportsAnalytics

In this article, we audit the headline by separating a goaltender intervention from shot quality.

The headline hides a selection problem

The NHL playoff schedule is active during the week of May 4, 2026 [1]. In a tight series, a coach may change the goalie after a bad game. The mistake is to compare goals against before and after the change without asking why the change happened.

The directed acyclic graph (DAG), a graph whose arrows do not loop back on themselves, treats GoalieChange as the treatment and GoalsAgainst as the outcome:

  • ScorePressure: series and game pressure that makes a change more likely
  • DefensiveBreakdowns: coverage mistakes that create dangerous chances
  • ShotQualityAgainst: how dangerous the conceded shots are
  • ReboundControl: whether the goalie turns first shots into second chances
  • GoalsAgainst: the outcome people use to judge the move

Directed acyclic graph linking score pressure, defensive breakdowns, goalie change, shot quality against, rebound control, and goals against

Here is the same graph as a py-scm setup. This uses the py-scm reference implementation for a continuous Gaussian structural causal model (SCM). An SCM defines each variable through its direct causes. The coefficients are illustrative.

import numpy as np

from pyscm.reasoning import create_reasoning_model

nodes = [
    "ScorePressure",
    "DefensiveBreakdowns",
    "GoalieChange",
    "ShotQualityAgainst",
    "ReboundControl",
    "GoalsAgainst",
]

weighted_edges = [
    ("ScorePressure", "GoalieChange", 0.60),
    ("ScorePressure", "DefensiveBreakdowns", 0.40),
    ("ScorePressure", "GoalsAgainst", 0.20),
    ("DefensiveBreakdowns", "GoalieChange", 0.50),
    ("DefensiveBreakdowns", "ShotQualityAgainst", 0.90),
    ("DefensiveBreakdowns", "GoalsAgainst", 0.40),
    ("GoalieChange", "ReboundControl", 0.35),
    ("GoalieChange", "GoalsAgainst", -0.25),
    ("ReboundControl", "GoalsAgainst", -0.45),
    ("ShotQualityAgainst", "GoalsAgainst", 0.90),
]

idx = {node: i for i, node in enumerate(nodes)}
B = np.zeros((len(nodes), len(nodes)))
for parent, child, weight in weighted_edges:
    B[idx[child], idx[parent]] = weight

A = np.eye(len(nodes)) - B
cov = np.linalg.inv(A) @ np.eye(len(nodes)) @ np.linalg.inv(A).T

model = create_reasoning_model(
    {"nodes": nodes, "edges": [(p, c) for p, c, _ in weighted_edges]},
    {"v": nodes, "m": [0.0] * len(nodes), "S": cov.tolist()},
)

The key idea is that DefensiveBreakdowns points into both GoalieChange and ShotQualityAgainst. NHL tracking and analytics often distinguish shot volume from shot danger, including high-danger areas and expected-goals-style reasoning [2, 3].

The query asks what changed

The inference code compares observing a goalie change with setting a goalie change:

raw_slice = model.pquery({"GoalieChange": 1.0})[0]["GoalsAgainst"]

do_change = model.iquery("GoalsAgainst", {"GoalieChange": 1.0})
do_no_change = model.iquery("GoalsAgainst", {"GoalieChange": 0.0})
change_effect = model.equery(
    "GoalsAgainst",
    {"GoalieChange": 1.0},
    {"GoalieChange": 0.0},
)

raw_slice asks what goals against look like when a goalie change is observed. change_effect asks what changes when the goalie switch is forced while the rest of the graph follows from that intervention.

Observed goalie-change gap: +0.20
Intervention effect:        -0.41
Observed minus effect:      +0.61

The observed slice is worse because goalie changes are selected by trouble. The intervention is beneficial in this toy model because it improves rebound control and directly reduces goals against.

Observed goalie-change slice compared with the intervention effect on goals against

What the model can support

The model supports a narrow statement: a goalie change can help and still look bad in the raw comparison. That is not a contradiction. It means the switch happened in a bad state.

The better evidence would compare shot quality before and after the switch, not just goals. If goals fall because high-danger chances fall, the defense deserves more credit. If high-danger chances stay constant and goals fall, the goalie-change story gets stronger.

Sources

  1. Schedule for May 4, 2026, NHL, accessed April 28, 2026.
  2. NHL EDGE Puck and Player Tracking Statistics Glossary, NHL, accessed April 28, 2026.
  3. Analytics with Alison: Expected Goals, Seattle Kraken, accessed April 28, 2026.

Download the runnable standalone Python example: Python example ZIP.

Leave a Reply

Discover more from Rocket Vector Blog

Subscribe now to keep reading and get access to the full archive.

Continue reading