TLDR and results are all the way down. Full analysis and explanation are first. Introduction The basic idea of "gravity" is intuitive. Some players can affect a defense just by their presence. By "affect a defense", I mean move an opponent's defensive structure out of shape, take an opponent player out of the game, have the back line change their depth, or have several opponent players disproportionately occupying certain regions of the pitch. Hence the title, "distort defenses". I'm sure gravity metrics exist extensively in private, clubs have access to them in scouting. But there is no widely accepted public measure of gravity. I have seen people discuss it on this platform quite often, but never with any stats. I thought the 2026 World Cup would be a great chance, in a confined tournament, to build this project. I have built a model using full-match player heat maps from this World Cup (credit to FotMob for the heat maps). The final dataset contains all 104 matches, 208 team-match maps, and 2017 player (starters) appearances in total. What is the Metric We will refer to this metric, simply as a player's "Gravity", or the "gravity metric". Gravity measures unusual defensive concentration or structural distortion associated with the areas a player occupies, relative to the following: The opponent's typical shape and setup The player's own team's normal shape. Appropriate players and spaces in the same match under consideration for the player. I just want to clarify before proceeding, that this metric does not prove causation or define a player. It is just another interesting metric to analyze games, and that is all. How does this model actually work? The first idea was to find a single mathematical signature for gravity, based on heat maps, and apply it to everybody, irrespective of role in-game, but this did not work. Following this were multiple failed attempts, such as. Heatmap overlap. This proved too simplistic, with far too many nuances to address reasonably. Channel-based gravity: Defining vertical or horizontal channels on the field, and checking opponent and team occupation in those channels. Zone-based gravity: Dividing the pitch into squares, and independently finding gravity based on opponent presence in adjacent squares, then combining the metric's value for a player across all the squares / zones they were present in. After these attempts, we go to the idea that different spatial roles would indeed require different defensive signatures and hence different definitions of gravity. The final model therefore has four main mechanisms: Wide, High-Central (HC), Deeper-Central (DC), and Roaming. Central players can also be placed in a hybrid state when their heat map genuinely supports both deeper-central and roaming interpretations. 1. Wide Gravity This is probably the easiest one to visualize. Suppose a winger spends most of the match on the left attacking channel. We measure how much opponent defense heat appears in that channel, compared with the tournament expectation. We also need to protect against opponent tactics. Perhaps the opponent was simply defending deeper or narrower in a particular game. Therefore, we create "laterally shifted control regions" in the same match. Very roughly: Raw Excess = Opponent Density in Player's Channel - Expected tournament density And then: Gravity Raw = raw excess - median residual in shifted control channels. We only consider positive excess toward Gravity. The final wide score is: G_wide = min(1, max(0,MRE) / S_wide) MRE stands for match-relative excess. "S_wide" is a fixed calibration constant, selected during calibration (See: Calibration) and frozen before producing any rankings. Conceptually, this answers the question of whether the opponent disproportionately redistributed its defensive structure toward the wide channel this player occupied. 2. High-Central Gravity A striker or very high central attacker is different. They don't just make the defense narrow or compress along one channel. A high-central, player can influence the depth structure of a defense. To measure this aspect of gravity, we collapse the opponent's heat through the wide central corridor and look at the depth distribution. The raw opponent depth gap is: gap = q80-q50 q80 and q50 are weighted percentiles of a heat distribution. Imagine taking all of a team's defensive heat in some region and arranging it by depth. Then, q50 is the median depth. 50% of the heat lies on one side of this point, and 50% on the other side. q80 is the 80th percentile of depth. 80% of the heat has been accumulated by the time we reach this point. So, if q80 - q50 = 20m, for example, there is a 20m depth separation between the median of the defensive heat and its deeper tail. Using percentiles describes the shape of the distribution instead of relying on any one defender's exact location. None of this uses player names. The routing to decide a player's role is game-by-game, based on the player's heat map geometry. The final production scorer contains no player-name logic and does not choose simply based on which role gives the largest score. Essentially, the player role assignment is on a game-to-game basis, and it is based purely on heat map geometry. So we have: gap = q80-q50 We then compare this with the same defending team's other World Cup matches. gap_excess = gap_match - mean(gap_sameDef,otherMatches) So essentially England is compared against England's own normal defensive structure, France against France's, etc... The baseline is "leave-one-out", so the match currently being measured is removed from the comparison. A positive excess means the opponent's central depth structure was unusually stretched in that match. There is one final attribution problem here, if two high-central attackers are present simultaneously in a team's structure, the heat map data cannot honestly tell us what percentage of the team-level distortion was caused by each. So instead of pretending we can identify that, we split the team-level gravity signal evenly between the two high-central players present, which is deliberately conservative. 3. Deeper-Central Gravity For a centrally operation midfielder / creator, we want to know whether the opponent becomes unusually narrow at the player's operating depth specifically, but we don't want to be confused by the opponent simply being narrow everywhere, or by the player's teammates presence. First, we use the player's attacking-half depth anchor: x_anchor. This is essentially the primary depth / point on the pitch around which they operate. Then, we take the opponent's lateral width using the middle 50% of the opponent's heat (percentiles similar to the depth gap from high-central gravity): width_50 = q75(y) - q25(y) For each depth region, compare the match with the defending team's other matches at the same pitch depth, which gives us: M = baseline width_50 - match width_50 A positive C means the opponent is in fact narrower than usual. Finally, we split that region of the pitch into three consecutive 16m bands. shallow = [x_a - 24, x_a - 8] target = [x_a - 8, x_a + 8] deep = [x_a + 8, x_a + 24] Then, the final raw measurement is: DC_raw = C_target - max(C_shallow, C_deep) This tells us that the opponent was unusually concentrated specifically at the depth associated with the player's occupation, relative to the defensive structure above and below this zone. Essentially, it removes a lot of false positives caused by teams simply defending compactly everywhere. 4. Roaming Gravity The deeper-central calculations do have a clear weakness, which is when the player does not really have any one clear operation depth. This happened often with players whose heat maps were distributed in several attacking zones. For these players, we use an opponent's residual map: R = O_match - O_sameDefBaseline Then, at every depth x, we subtract the average residual across the entire width of the pitch: R_local(x,y) = R(x,y) - mean_y * R(x,y) This step ensures that the score doesn't just pick up generic opponent defensive heat everywhere. Instead, we check, at each depth, where laterally did the opponent redistribute itself. Finally, we compare the player's overlap to the overlap produced by his own attacking teammates in the same match. ROAM_raw = local_wr(player) - median(local_wr(attacking teammates)) This means a player doesn't score high simply because the opponent had an unusual shape, but instead when the unusual distribution aligns with the player's roaming occupation more strongly than it aligns with teammates' attacking occupations. 5. Hybrid Central Player: DC or ROAM Certain players, in certain matches, have heat maps that are broad while still having a clear central anchor, which aligns with the definitions of both deeper-central and roaming. To handle such cases, we need to extend the measurement a little bit. M = longitudinal distribution Five attacking-depth features are standardized: weighted x standard deviation x IQR x q10 - q90 range number of meaningfully occupied depth bins inverse max depth-bin share Then, two unsupervised centers represent relatively localized and relatively distributed heat maps. M = (d_local - d_distributed) / (d_local + d_distributed) Negative M means a more localized presence, whereas positive means more distributed. A = anchor coherence We also look at how much of a player's attacking-half heat lies within 16m of the player's depth anchor, and convert this to a percentile A so: A close to 0 is an unusually weak anchor, and A close to 1 is unusually strong. After automated tuning, the final routing rule is: M = 0.65, then DC. M >= 0.3 AND A