# Does home advantage vanish once you count the shots? Causal diagrams

Source: https://www.footballdatascience.co.uk/learn/causal-diagrams-home-advantage
Published: 2026-10-26

> Home sides take about a third of a point a game more than away sides. Compare matches where both sides had the same shots-on-target edge and the advantage all but disappears. Why that doesn't make home advantage a myth, and how a causal diagram tells you what to hold fixed.

**On the terraces:** Count the shots and home advantage seems to disappear, so is it a myth? No: getting more shots is how home advantage works. This piece shows how to tell when comparing like with like helps, and when it hides the very thing you're looking for.

## The football question

Home sides in the Scottish Premiership take **1.55 points a game**. Away sides take **1.21**. That's about a third of a point a game, over 5,649 matches since 2000/01 (leaving out 2020/21, when there were no crowds).

Now compare like with like. Take every match where one side had, say, two more shots on target than the other, and ask whether it mattered which of them was at home. Do the same for every gap in shots on target, and average. **The home advantage left over is 0.01 points a game.** Next to nothing.

**So has home advantage disappeared once you count the shots?**

No. And why not is the most useful idea in this series.

## The concept

A **causal diagram** draws what causes what, with an arrow from each cause to what it affects. It doesn't need any maths. Its job is to decide one thing before you look at a single number: **which things to hold fixed when you compare.**

"Compare like with like" sounds like it's always right. It isn't. There are three basic shapes, and each one gives a different answer.

## Shape one: a fork, so hold it fixed

<figure class="rank-chart"><div role="img" aria-label="Team strength at the top, with arrows down to fewer fouls and to more points. A dashed line joins fewer fouls and more points.">

</div><figcaption>A fork: one cause drives both things, so they move together even if neither affects the other.</figcaption></figure>

Teams that foul less take more points. But strong teams have the ball more, so they rarely need to foul, and they win more because they're strong. Team strength is a **confounder**: it sits at the top of a fork and pushes both. [Do football stats mislead?](/research/correlation-causation) shows that when you compare sides of similar strength, the link between fouling and points all but goes.

For a fork, holding the confounder fixed is exactly right. It removes a link that was never there.

## Shape two: a chain, so think before you hold it fixed

<figure class="rank-chart"><div role="img" aria-label="At home, an arrow to more shots on target, then an arrow to more points.">

</div><figcaption>A chain: playing at home brings more shots on target, and more shots on target bring more points.</figcaption></figure>

Home sides average **5.11 shots on target** a game. Away sides average **4.09**. A crowd behind you, a familiar pitch and no long journey: whatever the reasons, home sides get about one more shot on target a game. That's the route home advantage takes to the result. Shots on target are a **mediator**: they sit in the middle of the chain.

Now look at what happens to the side with more shots on target, depending on where it's playing:

| More on target | At home | Away |
|---|---|---|
| Level | +0.10 | −0.10 |
| 1 more | +0.56 | +0.53 |
| 2 more | +0.82 | +0.96 |
| 3 more | +1.35 | +1.45 |
| 6 or more | +2.40 | +2.21 |

The numbers are the side's points minus its opponent's, on average. With the same edge in shots on target, the away side does as well as the home side. Average across every gap and the home side's extra is **+0.01 points a game**. Even when the shots on target are level, the home side's edge is only **+0.10**.

<div class="plain" markdown="1">
In plain football

- Holding shots on target fixed asks: "between two sides who got the same shots, does being at home still help?" Barely.
- That doesn't mean home advantage isn't real. It means almost all of it works *through* the shots.
- Holding a mediator fixed removes the effect you were trying to measure, like asking whether a striker helped his side once you've allowed for the goals he scored.
</div>

Both questions are fair, but they're different questions. **"Is home advantage real?"** is about the whole chain: don't hold the shots fixed, and the answer is yes, a third of a point a game. **"How does home advantage work?"** is about the middle of the chain: hold the shots fixed, and the answer is through the shots, almost entirely. Whether home advantage is as big as people say is tested in its own myth, [is home advantage worth a goal?](/myth-or-maths/home-advantage)

## Shape three: a collider, so never hold it fixed

<figure class="rank-chart"><div role="img" aria-label="Technique and athleticism at the top, each with an arrow down to picked by the academy.">

</div><figcaption>A collider: two things both feed into a third. Look only where the third is fixed and a link appears between them.</figcaption></figure>

The third shape has the arrows pointing inwards. An academy picks players on technique and athleticism. Among the players it picks, the more technical turn out to be the less athletic, even when the two have nothing to do with each other. [Collider bias](/learn/collider-bias) shows how strong that false link gets. Here, holding the middle fixed, by looking only at the players who were picked, *creates* a link that isn't there.

## The rule

Draw the diagram first, then decide what to hold fixed:

| Shape | The middle is | Hold it fixed? |
|---|---|---|
| Fork | a confounder | Yes |
| Chain | a mediator | Only to ask how it works |
| Collider | a collider | No |

In the [first part of this series](/learn/counterfactuals-new-manager), the form before a manager change was the fork: bad form pushed boards into changing *and* pushed sides towards the bottom. Holding it fixed was the fair comparison. The diagram tells you that before the data does.

## Why it matters

Statistical software will happily hold anything fixed you give it. It can't tell a confounder from a mediator or a collider; only the diagram can. Analysts who "control for everything" can make a real effect vanish, as shots on target did here, or invent one, as the academy did. Most of the arguments in football analytics about whether a stat "explains" something are really arguments about which shape the diagram has.

## Limitations

- **Real diagrams have more arrows.** The score affects the shots too: sides that go ahead often sit back and shoot less, which is trap five in [do football stats mislead?](/research/correlation-causation) The chain here is a simplified picture, enough to show the shape.
- **A diagram is an assumption.** It can't be proved from the data that produced it. It's a statement of what you believe causes what, which is why it should be drawn and argued over before the analysis, not after.
- **Shots on target were recorded differently from 2013/14.** Each comparison here is between the two sides in the same match, so the change affects both equally.
- **2020/21 is left out**, because matches without crowds are a different kind of home game.

## Reproduce the analysis

Save the Premiership results files (SC0) from football-data.co.uk in one folder; the [download script](/data#get-the-files) fetches them under the names the snippet expects. It needs only Python 3 and takes under a second:

```python
# From Football Data Science by Bryan McGuire. Free to use with credit.
# https://www.footballdatascience.co.uk/learn/causal-diagrams-home-advantage
import csv
from collections import defaultdict
from statistics import mean

POINTS = {"H": (3, 0), "D": (1, 1), "A": (0, 3)}  # (home side, away side)

# every match with shots on target, leaving out 2020/21, played without crowds
matches = []
for y in range(2000, 2026):
    if y == 2020:
        continue
    with open(f"SC0_{y % 100:02d}{(y + 1) % 100:02d}.csv", encoding="latin-1") as f:
        for r in csv.DictReader(f):
            if r.get("FTR") in POINTS and r.get("HST"):
                home, away = POINTS[r["FTR"]]
                matches.append({"home": home, "away": away, "hst": int(float(r["HST"])), "ast": int(float(r["AST"]))})

print(f"{len(matches):,} matches")
print(f"points a game: home {mean(m['home'] for m in matches):.2f}, away {mean(m['away'] for m in matches):.2f}, "
      f"gap {mean(m['home'] - m['away'] for m in matches):.2f}")
print(f"shots on target a game: home {mean(m['hst'] for m in matches):.2f}, away {mean(m['ast'] for m in matches):.2f}")

# group matches by how many more shots on target the home side had (6 or more counts as 6)
edge = defaultdict(list)  # gap -> home points minus away points
for m in matches:
    edge[max(-6, min(6, m["hst"] - m["ast"]))].append(m["home"] - m["away"])

print("\nmore shots on target than the other side: points edge when at home, and when away")
level = mean(edge[0])
print(f"level: the home side's edge {level:+.2f} ({len(edge[0])} matches)")
weighted, count = level * len(edge[0]), len(edge[0])
for d in range(1, 7):
    at_home, away = mean(edge[d]), -mean(edge[-d])  # the side with d more shots on target
    print(f"{d}{'+' if d == 6 else ''} more: at home {at_home:+.2f} ({len(edge[d])}), away {away:+.2f} ({len(edge[-d])})")
    n = min(len(edge[d]), len(edge[-d]))
    weighted += (at_home - away) / 2 * n
    count += n
print(f"\nhome advantage at the same shots-on-target gap: {weighted / count:+.2f} points a game")
```

## Further reading

- [Causal graph](https://en.wikipedia.org/wiki/Causal_graph), Wikipedia. Causal diagrams and how they're used to decide what to adjust for.
- [Mediation (statistics)](https://en.wikipedia.org/wiki/Mediation_(statistics)), Wikipedia. How an effect can work through a variable in the middle, and how to measure the part that goes through it.
- [Confounding](https://en.wikipedia.org/wiki/Confounding), Wikipedia. Hidden causes that make two things look linked, and the ways of dealing with them.
