本文目录导读:

在足球数据分析领域,量化“进攻三区效率”通常不是指单一的PHP函数,而是指一套数据模型和计算逻辑,你需要结合事件数据(传球、跑动、对抗)和期望进球(xG)模型。
以下是一个从基础到进阶的PHP实现方案,包含计算公式和代码示例。
第一步:定义核心指标(KPI)
在写代码前,先确定你要计算哪几个“效率”维度,常见的有:
- 传球成功率(Pass Completion):在进攻三区内,成功传球/总传球。
- 推进效率(Progression):将球从进攻三区外推进到三区内的有效传球/带球次数。
- 射门转化率(Conversion Rate):进攻三区内的射门数 / 进球数。
- 综合进攻威胁值(Threat Value):结合位置、角度和防守压力的加权评分。
第二步:基础版 PHP 实现(基于简单规则)
假设你有一个简单的比赛事件数组,你可以通过计算传入和传出进攻三区的球权来量化。
<?php
class AttackThirdZoneAnalyzer
{
private array $events;
private int $fieldLength = 105; // 标准场地长度(米)
private int $attackThirdStartX = 70; // 进攻三区起始X坐标(从本方底线算起)
public function __construct(array $events)
{
$this->events = $events;
}
/**
* 计算进攻三区传球成功率
*/
public function passSuccessRate(): array
{
$total = 0;
$success = 0;
foreach ($this->events as $event) {
// 假设事件坐标在进攻三区内
if ($event['type'] === 'pass' && $event['x'] >= $this->attackThirdStartX) {
$total++;
if ($event['outcome'] === 'successful') {
$success++;
}
}
}
return [
'attempts' => $total,
'successful' => $success,
'rate' => $total > 0 ? round($success / $total, 2) : 0,
];
}
/**
* 计算进攻三区“触球权”效率(进入三区后的处理效率)
* 公式:(射门/关键传球) / 总触球次数
*/
public function threatIndex(): float
{
$touches = 0;
$dangerousActions = 0;
foreach ($this->events as $event) {
if ($event['x'] < $this->attackThirdStartX) {
continue; // 跳过非三区事件
}
// 任何在三区的触球
if (in_array($event['type'], ['pass', 'shot', 'dribble', 'receive'])) {
$touches++;
}
// 关键传球或射正算作威胁动作
if ($event['type'] === 'shot') {
$dangerousActions++;
} elseif ($event['type'] === 'pass' && $event['isKeyPass'] === true) {
$dangerousActions++;
}
}
if ($touches === 0) {
return 0.0;
}
// 效率值 = 威胁动作次数 / 触球次数
return round($dangerousActions / $touches, 3);
}
/**
* 计算“推进效率”(从X=50推进到X=70的成功率)
*/
public function progressionEfficiency(): float
{
$attempts = 0;
$success = 0;
foreach ($this->events as $event) {
if ($event['type'] === 'pass' && $event['x'] < $this->attackThirdStartX && $event['endX'] >= $this->attackThirdStartX) {
$attempts++;
if ($event['outcome'] === 'successful') {
$success++;
}
}
}
return $attempts > 0 ? round($success / $attempts, 2) : 0;
}
}
// --- 使用示例 ---
$sampleEvents = [
// 坐标 x 为距离本方底线的距离(米)
['type' => 'pass', 'x' => 75, 'endX' => 80, 'outcome' => 'successful', 'isKeyPass' => false],
['type' => 'pass', 'x' => 80, 'endX' => 85, 'outcome' => 'failed', 'isKeyPass' => false],
['type' => 'shot', 'x' => 78, 'outcome' => 'goal', 'isKeyPass' => false],
['type' => 'receive', 'x' => 72, 'outcome' => 'successful', 'isKeyPass' => false],
['type' => 'pass', 'x' => 45, 'endX' => 72, 'outcome' => 'successful', 'isKeyPass' => false], // 推进
['type' => 'pass', 'x' => 60, 'endX' => 69, 'outcome' => 'failed', 'isKeyPass' => false], // 推进失败
];
$analyzer = new AttackThirdZoneAnalyzer($sampleEvents);
echo "传球成功率: " . json_encode($analyzer->passSuccessRate()) . PHP_EOL;
echo "威胁指数: " . $analyzer->threatIndex() . PHP_EOL;
echo "推进效率: " . $analyzer->progressionEfficiency() . PHP_EOL;
第三步:进阶版(引入权重与 xG)
如果静态指标太“扁平”,你可能需要量化“得分概率权重”,这需要结合场地位置赋予权重值(因为靠近底线的传球比中路的传球更具威胁)。
这里提供一个加权评分模型:
/**
* 计算综合威胁评分(基于位置和动作类型)
*/
public function weightedThreatScore(): float
{
$totalScore = 0;
$totalActions = 0;
foreach ($this->events as $event) {
if ($event['x'] < $this->attackThirdStartX) {
continue;
}
$baseWeight = 1.0;
$actionMultiplier = 1.0;
// 1. 位置权重(越靠近底线和球门,权重越高)
$proximityToGoal = 105 - $event['x']; // 距离球门的距离
if ($proximityToGoal < 20) {
$baseWeight = 3.0; // 极危险区域
} elseif ($proximityToGoal < 30) {
$baseWeight = 2.0;
} elseif ($proximityToGoal < 40) {
$baseWeight = 1.5;
}
// 2. 动作类型权重(射门 > 关键传球 > 普通传球)
switch ($event['type']) {
case 'shot':
$actionMultiplier = 4.0;
break;
case 'pass':
if ($event['isKeyPass']) {
$actionMultiplier = 2.5;
} else {
$actionMultiplier = 1.0;
}
break;
case 'dribble':
$actionMultiplier = 1.8;
break;
case 'receive':
$actionMultiplier = 0.8; // 纯控制球权
break;
default:
$actionMultiplier = 0.5;
}
// 3. 结果修正(失败的动作扣分,成功的动作加分)
if ($event['outcome'] === 'failed') {
$actionMultiplier *= 0.2; // 失败大幅降低效率
}
$totalScore += ($baseWeight * $actionMultiplier);
$totalActions++;
}
// 效率值 = 加权总分 / 动作次数(归一化)
return $totalActions > 0 ? round($totalScore / $totalActions, 2) : 0;
}
关键点: 如果你的数据源是 SportVU 或 StatsBomb,你需要将 x 坐标归一化(0-1),并可能需要引入“包抄点”或“传球角度”来进一步细化权重。
第四步:架构建议(面向复杂项目)
如果项目较大,建议使用策略模式来隔离算法。
<?php
interface EfficiencyCalculator
{
public function calculate(array $events): float;
}
class PassSuccessEfficiency implements EfficiencyCalculator
{
public function calculate(array $events): float
{
// 实现逻辑
}
}
class WeightedThreatEfficiency implements EfficiencyCalculator
{
public function calculate(array $events): float
{
// 实现逻辑
}
}
class EfficiencyContext
{
private EfficiencyCalculator $calculator;
public function __construct(EfficiencyCalculator $calculator)
{
$this->calculator = $calculator;
}
public function analyze(array $events): float
{
return $this->calculator->calculate($events);
}
}
第五步:数据清洗与优化
- 坐标系归一化:建议把X坐标转换为 0-100 或 0-1,方便不同球场尺寸的比较。
- 防守压力(可选):如果有对抗数据,可以给受压迫的传球乘以一个 7 的系数(更难所以更值钱)。
- 缓存机制:对于复杂计算(如动态加权),使用 Redis 缓存按
match_id + team_id存储结果,避免每次请求都全量遍历。
总结公式
最实用的“进攻三区效率值”公式通常是:
Efficiency = (成功传球数 + 射门数 + 关键传球数) / (总触球次数 + 预期失误次数) * 位置权重修正
这样既考虑了数量(多少球传进去了),也考虑了质量(传进去之后做了什么)。
选择哪种方式取决于你的数据颗粒度,如果只有基础坐标,用基础版即可;如果有全量事件流,推荐使用加权评分模型。