This page exists because the first version was built by intuition and presented with more confidence than it had earned. Below: exactly what v1 did, what the published and open-source methods do, what v2 does instead, and the tests that show where it holds and where it does not.
| Source | Method | What v2 takes |
|---|---|---|
| StatsBomb radars (Knutson, 2014→; the position templates the industry copied) | 11 fixed metrics per position, per 90, axes scaled to the 5th–95th percentile of the position, defensive metrics possession-adjusted | The metric list. Striker: xG, shots, touches in box, shot-touch %, xG assisted, pressures, pressure regains, aerial wins, turnovers, successful dribbles, xG/shot. Wide: + box-cross %, fouls won |
| Soccermatics (Sumpter, open course) | Count actions with context filters, per 90 or per possession-minute, convert to percentile within position and league, compare like with like | Position-relative comparison; the warning that tackles and pass completion are context, not quality |
| PlayeRank (Pappalardo et al., ACM TIST 2019) | 76 event features; weights learned by a linear SVM against match outcome (AUC 0.89); 8 roles by k-means on average position; 68–74% agreement with scouts | The principle that metric weights should be learned from outcomes, not asserted — the target for P1, not achievable from season aggregates. Also: it does not handle correlated features, which v2 does |
| football2vec (Magdaci) | Word2Vec over event sequences → player embeddings → cosine similarity | Nothing usable: needs full event data (StatsBomb open only) |
| Public PCA→k-means scouting repos | z-score season stats → PCA → k-means or KNN, cosine or Euclidean | The failure mode to test: snapshot, no possession adjustment, redundancy uncontrolled, clusters asserted. §6 below tests whether clusters exist at all |
| Transfer Flow corpus (37 episodes, 349k words) | Not a method — but a record of which numbers a working practitioner reaches for | Shots (303 mentions), xG (196), pressing (190), dribbles/carries (79), minutes and availability (457), age (144); always position-relative percentiles — "97th percentile xG for his position, 96th shots, 98th dribble-and-carry OBV." The Salah-decline example uses exactly shots/90, box touches/90 and passes into the box — the template |
| npxg | shots | npxg_per_shot | box_touches | shot_touch_pct | xa | aerials_won | dribbles_succ | turnovers | press_proxy | fouls_won | box_crosses | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| npxg | 1.00 | 0.76 | 0.58 | 0.37 | 0.04 | -0.03 | 0.19 | -0.09 | 0.08 | -0.22 | -0.04 | -0.39 |
| shots | 0.76 | 1.00 | 0.17 | 0.42 | 0.07 | 0.18 | 0.10 | 0.07 | 0.13 | -0.12 | 0.07 | -0.21 |
| npxg_per_shot | 0.58 | 0.17 | 1.00 | 0.13 | -0.01 | -0.21 | 0.20 | -0.16 | 0.01 | -0.17 | 0.02 | -0.34 |
| box_touches | 0.37 | 0.42 | 0.13 | 1.00 | -0.55 | 0.17 | 0.28 | 0.47 | 0.62 | 0.22 | 0.36 | -0.07 |
| shot_touch_pct | 0.04 | 0.07 | -0.01 | -0.55 | 1.00 | -0.09 | -0.22 | -0.33 | -0.46 | -0.28 | -0.36 | -0.05 |
| xa | -0.03 | 0.18 | -0.21 | 0.17 | -0.09 | 1.00 | -0.35 | 0.34 | -0.04 | 0.16 | 0.04 | 0.53 |
| aerials_won | 0.19 | 0.10 | 0.20 | 0.28 | -0.22 | -0.35 | 1.00 | -0.08 | 0.33 | 0.01 | 0.20 | -0.28 |
| dribbles_succ | -0.09 | 0.07 | -0.16 | 0.47 | -0.33 | 0.34 | -0.08 | 1.00 | 0.55 | 0.33 | 0.38 | 0.25 |
| turnovers | 0.08 | 0.13 | 0.01 | 0.62 | -0.46 | -0.04 | 0.33 | 0.55 | 1.00 | 0.31 | 0.58 | -0.06 |
| press_proxy | -0.22 | -0.12 | -0.17 | 0.22 | -0.28 | 0.16 | 0.01 | 0.33 | 0.31 | 1.00 | 0.29 | 0.21 |
| fouls_won | -0.04 | 0.07 | 0.02 | 0.36 | -0.36 | 0.04 | 0.20 | 0.38 | 0.58 | 0.29 | 1.00 | 0.03 |
| box_crosses | -0.39 | -0.21 | -0.34 | -0.07 | -0.05 | 0.53 | -0.28 | 0.25 | -0.06 | 0.21 | 0.03 | 1.00 |
No pair exceeds |r| = 0.8 in the template, which is one reason the template is better than v1's 28. Whitening handles what correlation remains.
Same player, top-8 neighbours under v1 (28 metrics, raw z) versus v2 (12-metric template, whitened):
Vlahović ↔ Kolo Muani distance: 74th percentile of all attacker pairs in v1, 92th percentile in v2. The headline gets stronger under the template.
Silhouette by k = 2…8: 0.24, 0.13, 0.12, 0.14, 0.15, 0.15, 0.15. Best is k = 2 at 0.24 — weak structure. The two "clusters" are 444 players and a rump of 47 with very few box touches and a high shot-to-touch ratio: long-range shooters and wide players mislabelled FW, not an archetype.
For the 276 attackers with 900+ minutes in both 2023/24 and 2024/25: place each player in the 2023/24 space, take his 8 nearest neighbours, and predict his 2024/25 npxG/90 as the mean of what those neighbours did in 2024/25.
| Predictor of 2024/25 npxG/90 | RMSE | corr |
|---|---|---|
| Positional mean (no information) | 0.157 | — |
| Player's own 2023/24 npxG/90 (persistence) | 0.124 | 0.68 |
| Mean of 8 nearest neighbours' 2024/25 | 0.146 | 0.42 |
| 50/50 blend of the two | 0.121 | — |
| Player | Club 24/25 | Dist | npxG/90 | Shots | Box touches | Aerials | Dribbles | xA | Press proxy | Turnovers |
|---|---|---|---|---|---|---|---|---|---|---|
| Dušan Vlahović (self) | Juventus | 0.00 | 0.46 | 3.7 | 1.8 | 0.5 | 0.1 | 0.05 | 0.1 | 1.0 |
| Daniel Mosquera | Hellas Verona | 1.42 | 0.43 | 3.7 | 0.9 | 0.7 | 0.3 | 0.06 | 0.0 | 1.0 |
| Valentín Castellanos | Lazio | 1.45 | 0.43 | 4.0 | 1.5 | 0.8 | 0.2 | 0.10 | 0.2 | 0.8 |
| Roberto Piccoli | Cagliari | 1.50 | 0.35 | 2.8 | 0.8 | 0.4 | 0.1 | 0.01 | 0.1 | 0.8 |
| Raúl Jiménez | Fulham | 1.51 | 0.35 | 3.4 | 0.9 | 0.2 | 0.0 | 0.08 | 0.1 | 0.6 |
| Patrick Cutrone | Como | 1.53 | 0.28 | 3.0 | 1.5 | 0.3 | 0.1 | 0.09 | 0.2 | 1.1 |
| Mostafa Mohamed | Nantes | 1.59 | 0.40 | 3.1 | 0.6 | 0.4 | 0.0 | 0.03 | 0.1 | 0.4 |
| Nikola Krstović | Lecce | 1.68 | 0.29 | 3.9 | 0.9 | 0.4 | 0.2 | 0.05 | 0.1 | 0.6 |
| Georginio Rutter | Brighton | 1.70 | 0.25 | 2.7 | 1.1 | 0.4 | 0.3 | 0.09 | 0.1 | 0.9 |
| Player | Club 24/25 | Dist | npxG/90 | Shots | Box touches | Aerials | Dribbles | xA | Press proxy | Turnovers |
|---|---|---|---|---|---|---|---|---|---|---|
| Randal Kolo Muani (self) | Juventus/Paris S-G | 0.00 | 0.46 | 2.4 | 1.2 | 0.4 | 0.3 | 0.08 | 0.1 | 1.1 |
| Juanmi | Betis/Getafe | 1.72 | 0.34 | 1.8 | 0.8 | 0.4 | 0.4 | 0.03 | 0.2 | 0.7 |
| Emanuel Emegha | Strasbourg | 2.68 | 0.67 | 2.4 | 0.9 | 0.4 | 0.2 | 0.03 | 0.1 | 0.9 |
| Irvin Cardona | Espanyol/Saint-Étien | 2.80 | 0.26 | 1.8 | 0.6 | 0.2 | 0.1 | 0.15 | 0.2 | 0.6 |
| Akor Adams | Montpellier/Sevilla | 2.81 | 0.35 | 2.1 | 1.8 | 1.0 | 0.1 | 0.01 | 0.0 | 1.0 |
| Arnaut Danjuma | Girona/Villarreal | 2.84 | 0.26 | 2.1 | 1.5 | 0.1 | 0.3 | 0.13 | 0.2 | 0.8 |
| Mario Götze | Eint Frankfurt | 2.89 | 0.17 | 0.5 | 0.5 | 0.0 | 0.0 | 0.11 | 0.1 | 0.3 |
| Orri Steinn Óskarsson | Real Sociedad | 2.94 | 0.50 | 1.8 | 0.8 | 0.5 | 0.0 | 0.05 | 0.1 | 0.6 |
| Myron Boadu | Bochum | 3.04 | 0.60 | 2.3 | 1.0 | 0.1 | 0.1 | 0.14 | 0.0 | 0.9 |
| Player | Club 24/25 | Dist | npxG/90 | Shots | Box touches | Aerials | Dribbles | xA | Press proxy | Turnovers |
|---|---|---|---|---|---|---|---|---|---|---|
| Jonathan David (self) | Lille | 0.00 | 0.38 | 2.3 | 1.2 | 0.1 | 0.2 | 0.11 | 0.1 | 0.6 |
| Takumi Minamino | Monaco | 0.93 | 0.36 | 2.3 | 0.8 | 0.2 | 0.1 | 0.19 | 0.1 | 0.7 |
| Danny Welbeck | Brighton | 0.97 | 0.37 | 2.5 | 1.2 | 0.3 | 0.2 | 0.06 | 0.1 | 0.8 |
| Gianluca Gaetano | Cagliari | 1.01 | 0.44 | 2.7 | 1.1 | 0.1 | 0.3 | 0.21 | 0.1 | 0.7 |
| Nicolas Jackson | Chelsea | 1.04 | 0.50 | 3.1 | 1.4 | 0.1 | 0.2 | 0.08 | 0.1 | 1.1 |
| Fábio Silva | Las Palmas | 1.07 | 0.31 | 2.2 | 1.2 | 0.2 | 0.2 | 0.09 | 0.1 | 0.9 |
| Arnaud Kalimuendo | Rennes | 1.09 | 0.31 | 2.4 | 0.8 | 0.2 | 0.1 | 0.07 | 0.1 | 0.7 |
| Joshua King | Toulouse | 1.25 | 0.36 | 2.7 | 0.7 | 0.2 | 0.1 | 0.09 | 0.1 | 0.4 |
| Alexander Isak | Newcastle Utd | 1.26 | 0.56 | 3.1 | 0.7 | 0.1 | 0.1 | 0.12 | 0.1 | 0.5 |
Kolo Muani's nearest neighbour sits at 1.72 and the next at 2.68 — his second-closest is further away than Vlahović's eighth. He is a genuinely unusual profile in this space, not a mid-table striker.
§6 asked whether there are gaps between groups (silhouette). The better question is whether there are stable, nameable regions — which a continuum can have. Test: fit k-means on 2022/23 + 2023/24 pooled (both seasons complete), assign each season separately, and ask whether players stay in their cluster.
| k | Same cluster, year to year | Chance | Adjusted Rand | Bootstrap stability |
|---|---|---|---|---|
| 2 | 80% | 50% | 0.36 | 0.97 |
| 3 | 75% | 34% | 0.38 | 0.91 |
| 4 | 76% | 34% | 0.42 | 0.76 |
| 5 | 62% | 28% | 0.32 | 0.57 |
| 6–8 | ≤51% | ≤23% | ≤0.23 | — |
| Profile | Signature (z) | 2023/24 examples |
|---|---|---|
| Box 9 (n=173) | npxG +0.8, npxG/shot +0.6, aerials +0.6; crosses −0.6, pressing −0.6, dribbles −0.6 | Solanke, Watkins, Osimhen, Zapata, Lautaro, Haaland, Vlahović, Kolo Muani, David, Openda |
| Wide dribbler (n=144) | dribbles +1.1, fouls won +0.7, turnovers +0.6; aerials −0.4 | Saka, Foden, Kvaratskhelia, Sávio, Gordon, Leão, Lookman, Soulé |
| Second-line creator (n=180) | pressing +0.6, box crosses +0.6, xA +0.1; box touches −0.8, npxG −0.8, shots −0.8 | Gibbs-White, Bruno Fernandes, McGinn, McNeil, Candreva |
The nuanced Kolo Muani answer: same family as Vlahović, opposite corner of it. On clean 2023/24 data their distance is at the 100th percentile of all pairs; Vlahović's nearest neighbour is Osimhen at 0.86, Kolo Muani's is Maupay at 3.06. The family label alone would have hidden the second fact.
Seven complete seasons (2017/18–2023/24; 3,533 attacker-seasons, 1,478 players) give six year-pairs to test persistence on. Method: 25 per-90 metrics (the template plus zone touches, progression, receiving, passing types), audited for season consistency — xA and progressive passes were dropped because FBref only populates them from 2023/24, which had been silently pulling every 2023/24 season into its own cluster — then standardised within season, whitened, and clustered hierarchically: families first, then sub-profiles inside each family, with the number of groups at each level chosen by year-to-year stability, not by silhouette.
| Level | k | Adjusted Rand, year to year | Same group | Chance |
|---|---|---|---|---|
| Families | 3 | 0.51 | 79% | 44% |
| Sub-profiles within the wide family | 2 | 0.38 | 81% | 52% |
| Sub-profiles within the 9 family | 2 | 0.39 | 81% | 52% |
| Any third split within a family | 3+ | fails the floor (ARI ≥ 0.25 and stability ≥ 1.5× chance) | ||
| Profile | Share | Stickiness | Signature (per 90) | Who lives here, 2021/22–2023/24 |
|---|---|---|---|---|
| Finishing 9 | 22% | 69% | npxG 0.39, box touches 4.8, shots high; passing and carrying volume low | Kane, Watkins, David, Salah, Lewandowski, Lautaro, Haaland, Osimhen, Immobile, Ben Yedder |
| Target 9 | 16% | 66% | aerials won 3.8 (vs ~1 elsewhere), npxG 0.30, turnovers high, carrying lowest | Toney, Solanke, Joselu, Ünal, Muriqi, Pinamonti, Budimir, Nzola, Mounié |
| Wide creator | 19% | 70% | crosses 5.3, key passes high, final-third passing; npxG 0.18 | Bourigeaud, Grifo, Foden, Brandt, Bruno Fernandes, Bowen, Berardi, Son, Candreva, Dybala |
| Wide carrier | 35% | 69% | progressive carries and carry distance high, take-ons 3.5, pressing; npxG 0.18 | Leão, Vinícius, Rodrygo, Saka, Sterling, Mbappé, Bernardo Silva, Ocampos, Almirón |
| Atypical (not a profile) | 7% | 10% | Rate-stat extremes on low volume — very high pass completion on few passes, long shot distance, high aerial % on few duels | Where a player lands in an unusual season: Vlahović 21/22, Kolo Muani 23/24, Palmer 23/24, Weghorst, Zapata |
Movement between profiles is informative in itself. Of 386 finishing-9 seasons with a next season, 61 became target-9 and 34 became wide carriers; of 309 target-9 seasons, 61 became finishing 9s. Fewer than 5% of wide seasons became any kind of 9. The permeable boundaries are finishing↔target and creator↔carrier; the wide/9 boundary is close to a wall.
| Player | Season by season | Reading |
|---|---|---|
| Vlahović | Target 9 (Fiorentina 19/20, 20/21) → atypical (21/22, the split season) → Finishing 9 (Juve 22/23, 23/24) | Became less of a target man at Juve; ended as a conventional finishing 9 |
| Kolo Muani | Finishing 9 (Nantes 20/21, 21/22) → Target 9 (Frankfurt 22/23) → atypical (23/24 Frankfurt/PSG) | A different profile every season; the only headline case with no stable identity — consistent with every earlier finding |
| Jonathan David | Finishing 9 all four seasons | The incumbent is the stable version of what Kolo Muani was at Nantes |
| Openda | Finishing 9 (Lens, Leipzig) | Same profile as David — Juve bought two of the same thing in 2025 |
| Chiesa | Wide carrier (Fiorentina) → finishing 9 (19/20) → wide creator (Juve 23/24) | A genuine role change across clubs |
| Salah · Haaland · Lautaro · Osimhen | Finishing 9 every season on record | Elite output is stable in profile as well as in level |
| Leão | Finishing 9 (Lille, early Milan) → wide carrier (21/22 onward) | Milan moved him wide and he stayed there |
| Player | Club | Dist | npxG/90 | Shots | Box touches | Aerials | Dribbles | xA |
|---|---|---|---|---|---|---|---|---|
| Victor Osimhen | Napoli | 0.86 | 0.52 | 3.9 | 6.9 | 1.7 | 0.7 | 0.04 |
| Isaac Bernal | Sevilla | 1.27 | 0.63 | 3.6 | 5.5 | 1.4 | 1.1 | 0.09 |
| Luis Javier Suárez | Almería | 1.30 | 0.56 | 3.8 | 5.5 | 1.0 | 1.2 | 0.05 |
| Folarin Balogun | Monaco | 1.61 | 0.45 | 3.4 | 7.4 | 0.4 | 0.6 | 0.10 |
| Akor Adams | Montpellier | 1.71 | 0.50 | 3.2 | 4.7 | 2.2 | 0.6 | 0.06 |
| Takuma Asano | Bochum | 1.72 | 0.36 | 2.9 | 4.3 | 0.7 | 0.7 | 0.04 |
| Wahbi Khazri | Montpellier | 1.88 | 0.26 | 3.3 | 4.1 | 0.7 | 1.1 | 0.06 |
| Maximilian Beier | Hoffenheim | 1.89 | 0.42 | 3.0 | 5.4 | 0.7 | 1.2 | 0.11 |
| Player | Club | Dist | npxG/90 | Shots | Box touches | Aerials | Dribbles | xA |
|---|---|---|---|---|---|---|---|---|
| Neal Maupay | Brentford/Everton | 3.06 | 0.45 | 2.6 | 5.0 | 0.9 | 0.6 | 0.14 |
| Samuel Omorodion | Alavés/Granada | 4.03 | 0.52 | 3.0 | 5.0 | 2.7 | 1.0 | 0.03 |
| Facundo Pellistri | Granada/Man Utd | 4.08 | 0.21 | 1.3 | 4.0 | 1.0 | 1.1 | 0.10 |
| David Datro Fofana | Burnley/Union Berlin | 4.48 | 0.42 | 2.6 | 5.0 | 1.3 | 2.0 | 0.03 |
| Portu | Getafe/Girona | 4.89 | 0.25 | 1.5 | 4.1 | 0.6 | 0.3 | 0.18 |
| Brennan Johnson | Forest/Spurs | 4.95 | 0.41 | 2.1 | 6.3 | 0.2 | 1.0 | 0.17 |
Note the distances: Vlahović's eighth neighbour is closer than Kolo Muani's first. That is the outlier signature, and it survives the correction.
player_recruitment · method v2 · data: FBref 2024/25 via worldfootballR (archived release) · code: scratchpad/fb/sim2.R · results: experiments/style-space-v2-template.json