中卫组合默契度量化框架(PHP 项目实践)
注:“中卫”我理解为中后卫(Center Back, CB)组合,若你指的是别的含义(如中场中路),可以再说明。
下面给出一套可落到 PHP 后端、可用于计算和存储的量化模型 + 数据结构 + 代码示例。
默契度的量化拆解
中卫默契度不是一个单一指标,建议拆成 4 个维度,加权求和 → 0~100 分。
| 维度 | 含义 | 数据来源 | 权重建议 |
|---|---|---|---|
| D1 同场时长 | 两人共同出场时间(分钟) | 比赛阵容事件 | 25% |
| D2 稳定性 | 同场时段的连续性(首发搭配占比) | 首发/换人记录 | 20% |
| D3 防守协同 | 同场时的失球率、零封率、被射门数 | 比赛统计 | 35% |
| D4 行为互补 | 抢断/拦截/争顶/解围的互补性 | 球员事件统计 | 20% |
默契度 = 0.25*D1 + 0.20*D2 + 0.35*D3 + 0.20*D4
各维度公式
D1 同场时长(归一化)
minutes_together = Σ 两人同场分钟
D1 = min(100, 100 * minutes_together / T_ref) // T_ref 建议 = 900 分钟(10 场)
D2 稳定性
starts_together = 两人同时首发的场次
matches_together = 两人同场的场次
D2 = 100 * starts_together / max(1, matches_together)
D3 防守协同(对比基线,防止把“弱队失球多”算成不默契)
goals_conceded_together = 同场失球数
minutes_together
GA90 = goals_conceded_together / minutes_together * 90
baseline_GA90 = 该队整体 GA90(同赛季)
D3 = 100 * clamp(1 - (GA90 - baseline_GA90) / baseline_GA90, -1, 1)
→ 映射到 [0,100]
可选增强:把零封率作为另一子项,D3 = 0.6*GA90_score + 0.4*cleanSheet_score。
D4 行为互补性
对每人统计:抢断 T、拦截 I、争顶成功 H、解围 C。
互补度 = 1 - |x1 - x2| / (x1 + x2 + ε) // 每项 0~1,越接近 1 越互补
D4 = 100 * mean(互补度_T, 互补度_I, 互补度_H, 互补度_C)
逻辑:两人风格过于重合(都是争顶型/都是拦截型)在高端局里协同性反而下降;一高一快、一抢一护的搭配通常更默契。
PHP 数据结构
final class CbPairMatchStat {
public function __construct(
public int $matchId,
public int $playerA,
public int $playerB,
public int $minutesTogether,
public bool $bothStarted,
public int $goalsConceded,
public int $cleanSheet, // 0/1
public array $statsA, // ['tackle'=>, 'intercept'=>, 'aerial'=>, 'clear'=>]
public array $statsB,
) {}
}
表建议:
CREATE TABLE cb_pair_match ( id BIGINT PRIMARY KEY AUTO_INCREMENT, match_id INT, player_a INT, player_b INT, minutes_together SMALLINT, both_started TINYINT, goals_conceded SMALLINT, clean_sheet TINYINT, tackle_a SMALLINT, tackle_b SMALLINT, intercept_a SMALLINT, intercept_b SMALLINT, aerial_a SMALLINT, aerial_b SMALLINT, clear_a SMALLINT, clear_b SMALLINT, UNIQUE KEY uq (match_id, player_a, player_b) );
PHP 计算示例
final class CbSynergyCalculator
{
public const W = ['d1'=>0.25, 'd2'=>0.20, 'd3'=>0.35, 'd4'=>0.20];
public const T_REF = 900.0;
/**
* @param CbPairMatchStat[] $rows
* @param float $teamGA90 球队赛季整体 GA90(基线)
*/
public function compute(array $rows, float $teamGA90): array
{
$minutes = 0; $matches = 0; $starts = 0;
$gc = 0; $cs = 0;
$sum = ['tackle_a'=>0,'tackle_b'=>0,'intercept_a'=>0,'intercept_b'=>0,
'aerial_a'=>0,'aerial_b'=>0,'clear_a'=>0,'clear_b'=>0];
foreach ($rows as $r) {
$minutes += $r->minutesTogether;
$matches++;
$starts += $r->bothStarted ? 1 : 0;
$gc += $r->goalsConceded;
$cs += $r->cleanSheet;
foreach ($sum as $k => $_) {
$sum[$k] += $r->statsA[explode('_', $k)[0]] ?? 0;
}
}
// 修正:上面循环写法略繁琐,下面显式计算
// D1
$d1 = min(100.0, 100.0 * $minutes / self::T_REF);
// D2
$d2 = 100.0 * $starts / max(1, $matches);
// D3
$ga90 = $minutes > 0 ? $gc / $minutes * 90.0 : $teamGA90;
$base = max($teamGA90, 0.1);
$raw = 1.0 - ($ga90 - $base) / $base; // >0 好于基线,<0 差于基线
$d3 = 100.0 * (max(-1.0, min(1.0, $raw)) + 1.0) / 2.0; // 映射到 0~100
// D4
$pairs = [
[$sum['tackle_a'], $sum['tackle_b']],
[$sum['intercept_a'], $sum['intercept_b']],
[$sum['aerial_a'], $sum['aerial_b']],
[$sum['clear_a'], $sum['clear_b']],
];
$comp = 0.0;
foreach ($pairs as [$x, $y]) {
$comp += 1.0 - abs($x - $y) / ($x + $y + 1e-6);
}
$d4 = 100.0 * $comp / count($pairs);
$score = self::W['d1']*$d1 + self::W['d2']*$d2
+ self::W['d3']*$d3 + self::W['d4']*$d4;
return [
'score' => round($score, 2),
'd1' => round($d1,2), 'd2' => round($d2,2),
'd3' => round($d3,2), 'd4' => round($d4,2),
'minutes' => $minutes, 'matches' => $matches,
'ga90' => round($ga90,2), 'baseline_ga90' => round($base,2),
];
}
}
✅ 上面代码里第一个
foreach那段我保留了一次示意,正式使用时删除,用下面的显式字段累加。
工程化落地要点
- 数据最小样本门槛:
minutes_together < 180时不输出默契度,标记为 “样本不足”,避免小样本噪声。 - 时间衰减:近 1 年权重高,可对每行加
exp(-Δdays/365)权重,再用加权平均重算 D1~D4。 - 对手强度修正:D3 可用对手进攻强度(对手 xG/场)做基线调整,避免“只对弱队一起踢”被高估。
- 持久化 + 缓存:结果表
cb_pair_score(pair_key, score, d1..d4, sample, updated_at),pair_key = min(id_a,id_b).'-'.max(...),供前端/API 直接读。 - 增量更新:每场比赛结束后只重算涉及的组合(一个球员最多 3~5 个搭档),O(1) 更新即可。
- 可视化:雷达图 / 组合热力图(球员 × 球员矩阵),前端直接跑。
可扩展(进阶)
- 用 xG prevented 替代失球数,噪声更小、样本效率更高。
- 引入 空间覆盖互补(球员平均位置散点图的距离/重叠面积)——需要 tracking 数据。
- 把 D2 换成 共现稳定性指数(同场组合在球队所有中卫组合中的占比 + 连续出场 run length)。
- 做 贝叶斯收缩:小样本向球队均值收缩,
score_shrunk = (n*score + k*prior) / (n + k)。
需要我把这套改成你现有 PHP 项目的表结构 / 框架(Laravel / Symfony / ThinkPHP)风格,或者补一个 API 返回结构 + 单元测试,告诉我用的框架和现有数据字段即可。
版权声明:足球直播
足球直播
足球直播
足球直播
足球直播
中超直播
中超直播
中超直播
中超直播
中超直播
英超直播
英超直播
英超直播
英超直播
英超直播
德甲直播
德甲直播
德甲直播
德甲直播
德甲直播
西甲直播
西甲直播
西甲直播
西甲直播
西甲直播
意甲直播
意甲直播
意甲直播
意甲直播
意甲直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
足球直播
足球直播
足球直播
足球直播
足球直播
中超直播
中超直播
中超直播
中超直播
中超直播
英超直播
英超直播
英超直播
英超直播
英超直播
德甲直播
德甲直播
德甲直播
德甲直播
德甲直播
西甲直播
西甲直播
西甲直播
西甲直播
西甲直播
意甲直播
意甲直播
意甲直播
意甲直播
意甲直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
足球直播
足球直播
足球直播
足球直播
足球直播
中超直播
中超直播
中超直播
中超直播
中超直播
英超直播
英超直播
英超直播
英超直播
英超直播
德甲直播
德甲直播
德甲直播
德甲直播
德甲直播
西甲直播
西甲直播
西甲直播
西甲直播
西甲直播
意甲直播
意甲直播
意甲直播
意甲直播
意甲直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
