Methodology · like-for-like player map · v2

How the like-for-like map is built — and what I got wrong the first time

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.

Correction, 28 Aug (later the same day). A per-table minutes check shows the archived FBref release's 2024/25 possession, defence and misc tables cover only ~20% of the season (median 4.7 nineties vs 21.9 in the standard table). Six of the twelve metrics below were therefore ~5× too low for 2024/25. Everything in §§4–8 built on 2024/25 is superseded by the 2023/24 rerun in §6b and §8b. Understat-based numbers (the register, Marcel) are unaffected.

1. What v1 actually was

The headline conclusion — Vlahović and Kolo Muani are not similar players — survives every change below. The neighbour lists do not. That distinction is the point of this page.

2. What already exists, and what was taken from each

SourceMethodWhat 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-adjustedThe 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 likePosition-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 scoutsThe 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 similarityNothing usable: needs full event data (StatsBomb open only)
Public PCA→k-means scouting reposz-score season stats → PCA → k-means or KNN, cosine or EuclideanThe 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 forShots (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

3. What v2 does

  1. Metrics = the StatsBomb striker + wide-attacker template, mapped to FBref. Two honest substitutions: FBref stopped publishing pressures in 2022, so att-3rd tackles + interceptions stands in for pressures and pressure regains; turnovers = miscontrols + dispossessed. 12 metrics: npxg, shots, npxg_per_shot, box_touches, shot_touch_pct, xa, aerials_won, dribbles_succ, turnovers, press_proxy, fouls_won, box_crosses.
  2. Per 90, then z-scored across all 491 big-5 attackers with 900+ minutes in 2024/25.
  3. PCA-whitened before measuring distance. Keep the components explaining 95% of variance (8 of 12), divide each by its standard deviation. Distance in this space is Mahalanobis distance: two metrics that say the same thing count once, not twice. This is the fix for v1's double-counting.
  4. Similarity = Euclidean distance in the whitened space. The 2-D picture uses the first two raw components and is for reading only.
  5. k-means on the same space, k chosen by silhouette — to test whether archetypes exist, not to assert them.

4. Redundancy — the correlation matrix

npxgshotsnpxg_per_shotbox_touchesshot_touch_pctxaaerials_wondribbles_succturnoverspress_proxyfouls_wonbox_crosses
npxg1.000.760.580.370.04-0.030.19-0.090.08-0.22-0.04-0.39
shots0.761.000.170.420.070.180.100.070.13-0.120.07-0.21
npxg_per_shot0.580.171.000.13-0.01-0.210.20-0.160.01-0.170.02-0.34
box_touches0.370.420.131.00-0.550.170.280.470.620.220.36-0.07
shot_touch_pct0.040.07-0.01-0.551.00-0.09-0.22-0.33-0.46-0.28-0.36-0.05
xa-0.030.18-0.210.17-0.091.00-0.350.34-0.040.160.040.53
aerials_won0.190.100.200.28-0.22-0.351.00-0.080.330.010.20-0.28
dribbles_succ-0.090.07-0.160.47-0.330.34-0.081.000.550.330.380.25
turnovers0.080.130.010.62-0.46-0.040.330.551.000.310.58-0.06
press_proxy-0.22-0.12-0.170.22-0.280.160.010.330.311.000.290.21
fouls_won-0.040.070.020.36-0.360.040.200.380.580.291.000.03
box_crosses-0.39-0.21-0.34-0.07-0.050.53-0.280.25-0.060.210.031.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.

5. Sensitivity — how much the answer depends on the metric list

Same player, top-8 neighbours under v1 (28 metrics, raw z) versus v2 (12-metric template, whitened):

Vlahović2 of 8 neighbours in common. Castellanos survives; the rest change.Kolo Muani5 of 8 in common — Juanmi, Akor Adams, Cardona persist.Jonathan David6 of 8 in common.Openda4 of 8 in common.
Read this as: the specific names are metric-dependent; the neighbourhoods are not. Vlahović's list is penalty-box strikers under both definitions (v1: Roque, Dovbyk, Castellanos, Watkins, Haaland; v2: Mosquera, Castellanos, Piccoli, Jiménez, Cutrone). Kolo Muani's is hybrids and wide forwards under both. Any single "his closest comp is X" claim from this kind of model deserves the same scepticism you brought to v1.

Vlahović ↔ Kolo Muani distance: 74th percentile of all attacker pairs in v1, 92th percentile in v2. The headline gets stronger under the template.

6. Do archetypes exist? Testing the k-means story

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.

There are no natural clusters among big-5 attackers in this space. Quadrant labels — "mace, sword, spear, shield" — are a reading aid drawn over a continuum, not something the data produces. Vlahović, Kolo Muani and David all land in the same cluster. This is why the engine is nearest-neighbour distance, and why cluster labels, if ever shown, are captions rather than findings.

7. Does similarity mean anything? A test against next season

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/90RMSEcorr
Positional mean (no information)0.157
Player's own 2023/24 npxG/90 (persistence)0.1240.68
Mean of 8 nearest neighbours' 2024/250.1460.42
50/50 blend of the two0.121
Similarity carries real information about future output — and much less than a player's own history. Neighbours beat knowing nothing (0.146 vs 0.157) and lose clearly to persistence (0.124). Blending helps slightly. So: the map is a candidate generator — who plays like him — not a projection. Projection stays with Marcel and the P1 model.

8. v2 neighbour lists

Nearest to Vlahović

PlayerClub 24/25DistnpxG/90ShotsBox touchesAerialsDribblesxAPress proxyTurnovers
Dušan Vlahović (self)Juventus0.000.463.71.80.50.10.050.11.0
Daniel MosqueraHellas Verona1.420.433.70.90.70.30.060.01.0
Valentín CastellanosLazio1.450.434.01.50.80.20.100.20.8
Roberto PiccoliCagliari1.500.352.80.80.40.10.010.10.8
Raúl JiménezFulham1.510.353.40.90.20.00.080.10.6
Patrick CutroneComo1.530.283.01.50.30.10.090.21.1
Mostafa MohamedNantes1.590.403.10.60.40.00.030.10.4
Nikola KrstovićLecce1.680.293.90.90.40.20.050.10.6
Georginio RutterBrighton1.700.252.71.10.40.30.090.10.9

Nearest to Kolo Muani

PlayerClub 24/25DistnpxG/90ShotsBox touchesAerialsDribblesxAPress proxyTurnovers
Randal Kolo Muani (self)Juventus/Paris S-G0.000.462.41.20.40.30.080.11.1
JuanmiBetis/Getafe1.720.341.80.80.40.40.030.20.7
Emanuel EmeghaStrasbourg2.680.672.40.90.40.20.030.10.9
Irvin CardonaEspanyol/Saint-Étien2.800.261.80.60.20.10.150.20.6
Akor AdamsMontpellier/Sevilla2.810.352.11.81.00.10.010.01.0
Arnaut DanjumaGirona/Villarreal2.840.262.11.50.10.30.130.20.8
Mario GötzeEint Frankfurt2.890.170.50.50.00.00.110.10.3
Orri Steinn ÓskarssonReal Sociedad2.940.501.80.80.50.00.050.10.6
Myron BoaduBochum3.040.602.31.00.10.10.140.00.9

Nearest to Jonathan David

PlayerClub 24/25DistnpxG/90ShotsBox touchesAerialsDribblesxAPress proxyTurnovers
Jonathan David (self)Lille0.000.382.31.20.10.20.110.10.6
Takumi MinaminoMonaco0.930.362.30.80.20.10.190.10.7
Danny WelbeckBrighton0.970.372.51.20.30.20.060.10.8
Gianluca GaetanoCagliari1.010.442.71.10.10.30.210.10.7
Nicolas JacksonChelsea1.040.503.11.40.10.20.080.11.1
Fábio SilvaLas Palmas1.070.312.21.20.20.20.090.10.9
Arnaud KalimuendoRennes1.090.312.40.80.20.10.070.10.7
Joshua KingToulouse1.250.362.70.70.20.10.090.10.4
Alexander IsakNewcastle Utd1.260.563.10.70.10.10.120.10.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.

6b. Correction: profiles exist as regions, not as gaps

§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.

kSame cluster, year to yearChanceAdjusted RandBootstrap stability
280%50%0.360.97
375%34%0.380.91
476%34%0.420.76
562%28%0.320.57
6–8≤51%≤23%≤0.23
Three persistent attacking profiles. Players stay in their profile at more than double chance, and the structure collapses beyond k=4 (one of the four is an empty degenerate cluster caused by the shot-touch-% tail). So: no gaps (§6 stands), but three real regions (§6 was wrong to imply none). Any claim of seven or more archetypes is naming noise.
ProfileSignature (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.6Solanke, 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.4Saka, 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.8Gibbs-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.

6c. Finer grain: a persistence-selected taxonomy over seven seasons

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.

LevelkAdjusted Rand, year to yearSame groupChance
Families30.5179%44%
Sub-profiles within the wide family20.3881%52%
Sub-profiles within the 9 family20.3981%52%
Any third split within a family3+fails the floor (ARI ≥ 0.25 and stability ≥ 1.5× chance)
Four persistent attacking profiles, plus a transient bin. The wide/9 boundary is very firm — almost nobody crosses it year to year. Each family splits once, and only once, into two stable sub-profiles. Anything finer does not survive a season.
ProfileShareStickinessSignature (per 90)Who lives here, 2021/22–2023/24
Finishing 922%69%npxG 0.39, box touches 4.8, shots high; passing and carrying volume lowKane, Watkins, David, Salah, Lewandowski, Lautaro, Haaland, Osimhen, Immobile, Ben Yedder
Target 916%66%aerials won 3.8 (vs ~1 elsewhere), npxG 0.30, turnovers high, carrying lowestToney, Solanke, Joselu, Ünal, Muriqi, Pinamonti, Budimir, Nzola, Mounié
Wide creator19%70%crosses 5.3, key passes high, final-third passing; npxG 0.18Bourigeaud, Grifo, Foden, Brandt, Bruno Fernandes, Bowen, Berardi, Son, Candreva, Dybala
Wide carrier35%69%progressive carries and carry distance high, take-ons 3.5, pressing; npxG 0.18Leã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 duelsWhere 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.

Profile trajectories, Juventus cases

PlayerSeason by seasonReading
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 MuaniFinishing 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 DavidFinishing 9 all four seasonsThe incumbent is the stable version of what Kolo Muani was at Nantes
OpendaFinishing 9 (Lens, Leipzig)Same profile as David — Juve bought two of the same thing in 2025
ChiesaWide carrier (Fiorentina) → finishing 9 (19/20) → wide creator (Juve 23/24)A genuine role change across clubs
Salah · Haaland · Lautaro · OsimhenFinishing 9 every season on recordElite output is stable in profile as well as in level
LeãoFinishing 9 (Lille, early Milan) → wide carrier (21/22 onward)Milan moved him wide and he stayed there
What this taxonomy is for. Candidate generation and a sanity check on fit — "Juve replaced a finishing 9 with a player who has not held any profile for two consecutive seasons" is a statement the data supports. It is not a quality measure: the finishing-9 profile contains Haaland and Gyasi. Quality is Marcel and the P1 model; profile is where to look.

8b. Neighbours on clean data — 2023/24

Nearest to Vlahović (Juventus, 2,307 min)

PlayerClubDistnpxG/90ShotsBox touchesAerialsDribblesxA
Victor OsimhenNapoli0.860.523.96.91.70.70.04
Isaac BernalSevilla1.270.633.65.51.41.10.09
Luis Javier SuárezAlmería1.300.563.85.51.01.20.05
Folarin BalogunMonaco1.610.453.47.40.40.60.10
Akor AdamsMontpellier1.710.503.24.72.20.60.06
Takuma AsanoBochum1.720.362.94.30.70.70.04
Wahbi KhazriMontpellier1.880.263.34.10.71.10.06
Maximilian BeierHoffenheim1.890.423.05.40.71.20.11

Nearest to Kolo Muani (Frankfurt/PSG, 1,421 min)

PlayerClubDistnpxG/90ShotsBox touchesAerialsDribblesxA
Neal MaupayBrentford/Everton3.060.452.65.00.90.60.14
Samuel OmorodionAlavés/Granada4.030.523.05.02.71.00.03
Facundo PellistriGranada/Man Utd4.080.211.34.01.01.10.10
David Datro FofanaBurnley/Union Berlin4.480.422.65.01.32.00.03
PortuGetafe/Girona4.890.251.54.10.60.30.18
Brennan JohnsonForest/Spurs4.950.412.16.30.21.00.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.

9. What is still not done

player_recruitment · method v2 · data: FBref 2024/25 via worldfootballR (archived release) · code: scratchpad/fb/sim2.R · results: experiments/style-space-v2-template.json