import matplotlib.pyplot as plt
# ===========================================
# 2026 FIFA World Cup
# Attack vs Defence (Expected Goals)
# X-axis : xG Conceded per Match (lower = better defence)
# Y-axis : xG Created per Match (higher = better attack)
# ===========================================
teams = [
"Spain", "Portugal", "Morocco", "Canada", "France",
"Paraguay", "Brazil", "Norway", "Mexico", "England",
"Argentina", "Egypt", "Switzerland", "Colombia",
"Belgium", "USA", "GER", "NED"
]
# xG conceded (X-axis)
x = [
0.30, 1.17, 1.29, 0.65, 1.04,
1.43, 0.80, 1.52, 0.78, 1.17,
0.78, 1.65, 1.05, 0.62,
1.35, 1.24, 0.81, 0.90
]
# xG created (Y-axis)
y = [
1.95, 1.40, 1.41, 1.94, 2.19,
0.32, 2.46, 1.68, 1.33, 1.79,
1.82, 1.20, 1.61, 1.48,
1.82, 1.23, 2.08, 1.37
]
plt.style.use("default")
fig, ax = plt.subplots(figsize=(10, 8), dpi=150)
fig.patch.set_facecolor("white")
ax.set_facecolor("white")
# Highlight semifinalists
colors = {
"Spain": "#D4AF37", # Gold
"Argentina": "#C0C0C0", # Silver
"England": "#CD7F32", # Bronze
"France": "#C62828" # Red
}
# Plot teams
for team, x_val, y_val in zip(teams, x, y):
color = colors.get(team, "#1F4E79")
size = 170 if team in colors else 90
ax.scatter(
x_val,
y_val,
s=size,
color=color,
edgecolor="white",
linewidth=1.4,
zorder=3
)
# Team name
ax.text(
x_val + 0.02,
y_val + 0.02,
team,
fontsize=9,
weight="bold" if team in colors else "normal"
)
# Coordinates
ax.text(
x_val + 0.02,
y_val - 0.05,
f"({x_val:.2f}, {y_val:.2f})",
fontsize=7,
color="gray"
)
# Tournament averages
avg_x = sum(x) / len(x)
avg_y = sum(y) / len(y)
ax.axvline(avg_x, color="gray", linestyle="--", linewidth=1.2)
ax.axhline(avg_y, color="gray", linestyle="--", linewidth=1.2)
# Quadrant labels
ax.text(
0.22, 2.62,
"Elite Defence\nElite Attack",
fontsize=11,
weight="bold",
color="#0B6E4F",
ha="left",
va="top"
)
ax.text(
1.78, 2.62,
"Weak Defence\nElite Attack",
fontsize=11,
color="#E67E22",
ha="right",
va="top"
)
ax.text(
0.22, 0.25,
"Elite Defence\nWeak Attack",
fontsize=11,
color="#1565C0",
ha="left",
va="bottom"
)
ax.text(
1.78, 0.25,
"Weak Defence\nWeak Attack",
fontsize=11,
color="#C0392B",
ha="right",
va="bottom"
)
# Axes
ax.set_xlim(0.2, 1.8)
ax.set_ylim(0.2, 2.7)
# Optional: Uncomment to place the best defensive teams on the right.
# ax.invert_xaxis()
ax.set_xlabel(
"xG Conceded per Match",
fontsize=13,
weight="bold"
)
ax.set_ylabel(
"xG Created per Match",
fontsize=13,
weight="bold"
)
ax.set_title(
"2026 FIFA World Cup\nAttack vs Defence (Expected Goals per Match)",
fontsize=17,
weight="bold",
pad=15
)
# Grid
ax.grid(True, linestyle="--", linewidth=0.6, alpha=0.35)
ax.set_axisbelow(True)
# Remove unnecessary borders
ax.spines["top"].set_visible(False)
ax.spines["right"].set_visible(False)
plt.tight_layout()
plt.show()
To embed this project on your website, copy the following code and paste it into your website's HTML: