Bottom at Christmas, down in May?
One of football's oldest sayings is that the side bottom at Christmas goes down. In the Scottish Premiership it's mostly true. Of 26 sides bottom on Christmas Day, 18 finished bottom, and every one that escaped was within a point of the side above.
Beginner
Contents
The claim
"Bottom at Christmas, down in May." It's one of football's oldest sayings: whoever is propping up the table when the decorations go up is the side that'll finish there. Every December someone quotes it, and every December the side at the bottom insists there's plenty of football left.
Why people believe it
By Christmas, a Scottish Premiership side has played about half its matches. That's enough for the table to mean something, and a side at the bottom has usually got there by being the weakest in the league, not by bad luck alone. Fans also remember the escapes precisely because they're unusual, which makes the rule feel even stronger.
The data
Every Scottish Premiership season from 2000/01 to 2025/26: 26 seasons, 12 teams each, from the football-data.co.uk results files.
The method
For each season, build the table from every match played before 25 December, ranking on points, then goal difference, then goals scored. Take the side at the bottom, note how many points behind the side above it was, and compare with where it finished the season. The test is finishing bottom, not being relegated, because the relegation rules have changed over the years (see Caveats).
The evidence
How often the saying comes true
| Where the side bottom at Christmas finished | Seasons |
|---|---|
| Bottom | 18 |
| Second-bottom | 3 |
| Higher | 5 |
18 of 26, a little over two-thirds, finished where they were at Christmas, and 21 of 26 finished in the bottom two. Being close to the bottom is dangerous too: the side second-bottom at Christmas went on to finish bottom 6 times.
The gap matters more than the place
The saying treats bottom as bottom. The table doesn't: a side level on points with the one above is in a very different position from one seven points adrift.
| Behind at Christmas | Seasons | Bottom | Bottom two |
|---|---|---|---|
| 0 or 1 point | 12 | 7 | 7 |
| 2 or more | 14 | 11 | 14 |
A side level with, or a point behind, the team above finished bottom 7 times in 12. Two points or more, and every one of the 14 finished in the bottom two. Even two points is a lot to make up on one specific side, when that side is picking up points too.
The five escapes
| Side | At Christmas | Finished |
|---|---|---|
| Livingston 2004/05 | 15 from 18, level | 10th |
| Hamilton 2008/09 | 17 from 19, level | 9th |
| Aberdeen 2010/11 | 10 from 16, level | 9th |
| Ross County 2013/14 | 11 from 16, 1 behind | 7th |
| Ross County 2020/21 | 13 from 19, 1 behind | 10th |
"15 from 18" is points from games played; "level" means level on points with the side above, bottom on goal difference.
Every escape came from a side that was only bottom by a point, or on goal difference. Ross County's 2013/14 is the biggest: bottom at Christmas, seventh in May, top of the bottom six.
Verdict
Supported. The side bottom on Christmas Day finished bottom 18 times in 26, and in the bottom two 21 times. The saying is too blunt in one way: it's the size of the gap, not the position, that decides it. Level on points or a point behind, the escape rate is nearly half. Two points or more behind, not one side in 26 seasons got out of the bottom two.
Caveats
- Bottom isn't always relegated. In 2002/03 Motherwell finished bottom but stayed up, because the First Division champions' ground didn't meet the league's criteria. Since 2014/15 the second-bottom side has also faced a play-off. This analysis only asks who finished bottom.
- Points only. Points deductions aren't in the results files, so a few tables differ slightly from the official ones.
- 2019/20 ended early. The season stopped in March and was decided on points per game; the data holds the matches played. Hearts were bottom either way.
- Games in hand. By Christmas, sides had played between 16 and 21 matches, so a small gap can hide a game in hand either way.
- One league. A 12-team league with a split in spring may behave differently from a 20-team one.
Reproduce the analysis
The results files are published by football-data.co.uk. Download the Premiership file (SC0) for each season from 2000/01 to 2025/26 and save each under its own name, such as SC0_2425.csv; they aren't rehosted on this site. Then:
Show the Python50 lines, ready to copy and run.
import csv
from collections import Counter
from datetime import datetime
names = [f"{y % 100:02d}{(y + 1) % 100:02d}" for y in range(2000, 2026)]
def season(s):
with open(f"SC0_{s}.csv", encoding="latin-1") as f:
games = [r for r in csv.DictReader(f) if r.get("FTR") in ("H", "D", "A")]
for r in games:
r["date"] = datetime.strptime(r["Date"], "%d/%m/%Y" if len(r["Date"]) == 10 else "%d/%m/%y")
return games
def table(games):
"""Teams in league order: points, then goal difference, then goals scored."""
pts, gd, gf, played = Counter(), Counter(), Counter(), Counter()
for r in games:
h, a, hg, ag = r["HomeTeam"], r["AwayTeam"], int(r["FTHG"]), int(r["FTAG"])
pts[h] += {"H": 3, "D": 1, "A": 0}[r["FTR"]]
pts[a] += {"H": 0, "D": 1, "A": 3}[r["FTR"]]
gd[h] += hg - ag
gd[a] += ag - hg
gf[h] += hg
gf[a] += ag
played[h] += 1
played[a] += 1
order = sorted(played, key=lambda t: (pts[t], gd[t], gf[t]), reverse=True)
return order, pts, played
rows = []
for s in names:
games = season(s)
christmas = datetime(2000 + int(s[:2]), 12, 25)
before, pts, played = table([r for r in games if r["date"] < christmas])
final, _, _ = table(games)
bottom, next_up = before[-1], before[-2]
rows.append({"season": f"20{s[:2]}/{s[2:]}", "bottom": bottom, "played": played[bottom], "points": pts[bottom],
"gap": pts[next_up] - pts[bottom], "finish": final.index(bottom) + 1, "teams": len(final),
"second_bottom": next_up, "second_finish": final.index(next_up) + 1})
n = len(rows)
last = sum(r["finish"] == r["teams"] for r in rows)
eleventh = sum(r["finish"] == r["teams"] - 1 for r in rows)
print(f"{n} seasons: bottom on Christmas Day finished bottom {last} times, second-bottom {eleventh}, higher {n - last - eleventh}")
print(f"second-bottom on Christmas Day finished bottom {sum(r['second_finish'] == r['teams'] for r in rows)} times")
for r in rows:
print(f" {r['season']} {r['bottom']:16} {r['points']:2} pts from {r['played']:2}, {r['gap']:2} behind, finished {r['finish']}")
for label, group in (("level or 1 point behind", [r for r in rows if r["gap"] <= 1]), ("2 or more points behind", [r for r in rows if r["gap"] >= 2])):
print(f"{label} the side above: {len(group)} seasons, finished bottom {sum(r['finish'] == r['teams'] for r in group)}, "
f"bottom two {sum(r['finish'] >= r['teams'] - 1 for r in group)}")