An end-to-end machine learning pipeline that predicts ACL injury risk for all 1,218 players at the 2026 FIFA World Cup, using only publicly available data.
- 0.917 CV ROC-AUC on a held-out validation set
- 307 players flagged as High Risk
- 101 players identified as re-tear candidates (prior ACL history)
- 206 players flagged as first-tear risk from injury burden alone
- Manuel Ugarte (Uruguay) — torn ACL June 28 2026, flagged pre-tournament ✓
| Source | What | How |
|---|---|---|
| FBref (via soccerdata) | Player workload stats — minutes, starts, tackles | Python scraper |
| Wikipedia | 2026 World Cup squads — 1,248 players, 48 teams | BeautifulSoup |
| Transfermarkt | Full career injury history per player | Custom scraper + fuzzy matching |
| Manual | Venue surface types (artificial vs natural turf) | 16 stadiums |
XGBoost classifier with SMOTE oversampling to handle class imbalance (8.3% positive rate). 18 features — all validated for zero target leakage.
Key features: total_days_out, knee_injuries, avg_days_out, injuries_last_2_years, pos_risk, age_risk, workload_risk
Interactive Streamlit app with risk leaderboard, re-tear vs first-tear split, player spotlight, and risk distribution.
pip install -r requirements.txt
streamlit run app.pyacl-predictor/
├── pipeline.ipynb ← Steps 1–3: data collection, cleaning, model training
├── app.py ← Streamlit dashboard
├── data/raw/ ← scraped CSVs
├── data/processed/ ← master_scored.csv (dashboard input)
├── models/ ← trained XGBoost pipeline
└── outputs/ ← feature importance charts
pip install -r requirements.txt- Run all cells in
pipeline.ipynb(~3 hours total — scraping is the bottleneck) streamlit run app.py
Note: Transfermarkt scraping includes a 1.5s delay per request to be respectful of their servers.