Predicting footballer market value, part 1: building a multi-source dataset

Machine LearningFootball AnalyticsData EngineeringPythonWeb ScrapingMajor Project

Post

This is part 1 of a three-part series on my final-year major project: Predicting the Market Value of Professional Football Players — A Multi-Source Stacked Ensemble Approach Using Transfermarkt, FBref and EA Sports FC Data. The full code is in the project repository.

Why market value?

A footballer's market value is one of the most argued-over numbers in sport. Transfermarkt's crowd-sourced valuations are the de-facto reference, but they are opinions, not measurements. My question was: how well can market value be predicted from observable data — on-pitch performance, player attributes and contract context — and which signals actually drive it?

Three sources, three views of the same player

No single dataset describes a player completely, so the project fuses three complementary sources:

  • Transfermarkt — the target variable (market value) plus contract and transfer context.
  • FBref — detailed on-pitch performance statistics for the top five European leagues, scraped with a custom Python scraper (fbref_scraper.py) using Playwright for the dynamic pages.
  • EA Sports FC (SoFIFA) — expert-assessed player attributes such as overall rating and potential, which encode scouting judgement that raw match statistics miss.

The unglamorous 80%

The cleaning notebooks (Fbref_cleaning, Transfermarkt_cleaning, SoFIFA_cleaning_revised) ended up being a large share of the project, and the messiest problems were entity resolution and leakage:

  • Entity resolution — the same player appears as different name spellings across the three sources, sometimes with different clubs mid-transfer. Joining them reliably required normalisation and fuzzy matching, then manual checks of the residuals.
  • Temporal alignment — a valuation on a given date must only see performance data from before that date, or the model is quietly cheating.
  • Per-90 normalisation — raw season totals confound ability with minutes played, so performance features are normalised per 90 minutes.

The result is a cleaned, parquet-backed dataset of top-five-league players with aligned performance, attribute and valuation data — the foundation everything else in this series builds on.

Next up, part 2: designing the stacked ensemble, and why combining model families beats any single learner on this problem.

← All posts