根据php项目,进攻三区传球成功率?

wen PHP项目 4

本文目录导读:

根据php项目,进攻三区传球成功率?

  1. 数据模型设计(MySQL)
  2. 核心定义:进攻三区判定标准
  3. PHP后端逻辑(Laravel / 原生PHP示例)
  4. 处理“方向”问题(重要)
  5. API 响应格式建议(给前端图表)
  6. 前端调用(JS示例)
  7. 优化与陷阱提示

在足球数据分析中,“进攻三区传球成功率”是衡量一支球队在对方半场最靠近球门的区域(即对方禁区前沿30米区域)内,传球的精准度和威胁性/控制力的重要指标。

结合PHP项目(通常涉及后端API、MySQL数据库和前段JS图表),我为你提供一个完整的实现方案,包含数据库设计、核心查询逻辑以及API返回格式。


数据模型设计(MySQL)

传球事件数据存储在事件表中,你需要确保有足够字段来区分比赛、球员、球队和位置。

假设你有以下简化的表结构:

-- 事件表
CREATE TABLE pass_events (
    id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    match_id INT NOT NULL,          -- 比赛ID
    team_id INT NOT NULL,           -- 球队ID(传球方)
    player_id INT NOT NULL,         -- 球员ID
    start_x DECIMAL(5,2),           -- 传球起始点X坐标 (0-100)
    start_y DECIMAL(5,2),           -- 传球起始点Y坐标 (0-100)
    end_x DECIMAL(5,2),             -- 传球结束点X坐标
    end_y DECIMAL(5,2),             -- 传球结束点Y坐标
    is_accurate TINYINT(1),         -- 是否成功 (1=成功, 0=失败)
    is_assist TINYINT(1) DEFAULT 0, -- 是否为助攻
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    INDEX idx_match_team (match_id, team_id),
    INDEX idx_position (start_x, start_y)
);

核心定义:进攻三区判定标准

在标准足球场坐标系中(X 轴为球场长度,Y 轴为宽度,0-100 比例尺):

  • 进攻方向:假设你的球队是从左向右进攻(即 X 轴正方向)。
  • 进攻三区定义:起始 X 坐标 大于等于 60(即对方半场靠近球门的 1/3 区域)。

注意:如果你的数据是“半场交换制”,或者方向不固定,建议在入库时统一处理为“朝向对方球门”的方向,如果数据源是 Opta 或 StatsBomb,通常有 End X 字段直接指向对方球门。


PHP后端逻辑(Laravel / 原生PHP示例)

我们需要计算传球成功率 = (成功的传球次数 / 总传球次数)* 100

A. 基础SQL查询(按球队聚合)

<?php
// 假设使用 Laravel Query Builder 或原生 PDO
// 输入参数
$matchId = (int) $_GET['match_id'] ?? 0; // 可选,筛选特定比赛
$teamId  = (int) $_GET['team_id'] ?? 0;  // 可选,筛选特定球队
$query = "
    SELECT 
        team_id,
        COUNT(*) AS total_passes, 
        SUM(CASE WHEN is_accurate = 1 THEN 1 ELSE 0 END) AS accurate_passes,
        ROUND( (SUM(CASE WHEN is_accurate = 1 THEN 1 ELSE 0 END) / COUNT(*)) * 100, 1) AS success_rate
    FROM pass_events
    WHERE 
        -- 核心条件:进攻三区(假设己方半场X为0-50,对方半场为50-100)
        start_x >= 60 
        -- 如果需要按比赛筛选
        AND (match_id = :match_id OR :match_id = 0)
        -- 如果需要按球队筛选
        AND (team_id = :team_id OR :team_id = 0)
    GROUP BY team_id
    ORDER BY success_rate DESC
";
// 执行查询(以 PDO 为例)
$stmt = $pdo->prepare($query);
$stmt->execute([
    ':match_id' => $matchId,
    ':team_id'  => $teamId
]);
$result = $stmt->fetchAll(PDO::FETCH_ASSOC);
// 返回 JSON
header('Content-Type: application/json');
echo json_encode($result);
?>

B. 进阶场景:加入“防线深度”或“压迫”过滤

如果你想看“在对方高位压迫下的传球成功率”,你可能需要结合对手的站位数据,但这通常需要更复杂的地理空间计算。

简化版:只统计传到进攻三区(而不是在进攻三区发起)的成功率 如果你要计算的是“传入进攻三区的成功率”,则将判断条件改为 end_x >= 60

-- 传入进攻三区
SELECT 
    team_id,
    COUNT(*) AS total_forward_passes,
    SUM(is_accurate) AS accurate_passes,
    ROUND(AVG(is_accurate) * 100, 1) AS success_rate
FROM pass_events
WHERE end_x >= 60
GROUP BY team_id;

处理“方向”问题(重要)

如果你们的比赛数据是动态翻转的(比如上半场A队从左往右攻,下半场从右往左攻),你必须在数据导入时进行标准化。建议在ETL阶段处理

// 假设原始数据中,主队默认从左往右攻,客队从右往左攻。
// 如果该传球事件属于客队,则 X 坐标需要翻转。
if ($team_side == 'away') {
    // 翻转坐标轴(假设球场长度是100)
    $normalized_x = 100 - $original_x;
} else {
    $normalized_x = $original_x;
}
// 如果翻转后的X <= 40 (即距离对方球门较近区域),算作进攻三区

API 响应格式建议(给前端图表)

为了让前端(如ECharts、Chart.js)直接使用,建议返回结构化数据:

{
  "status": "success",
  "data": {
    "zone": "进攻三区",
    "threshold": "start_x >= 60",
    "teams": [
      {
        "team_id": 1,
        "team_name": "曼城",
        "total_passes": 120,
        "accurate_passes": 102,
        "success_rate": 85.0
      },
      {
        "team_id": 2,
        "team_name": "利物浦",
        "total_passes": 95,
        "accurate_passes": 73,
        "success_rate": 76.8
      }
    ]
  }
}

前端调用(JS示例)

fetch('/api/pass-success?match_id=1001')
  .then(response => response.json())
  .then(data => {
    const chartData = data.data.teams.map(t => ({
      name: t.team_name,
      value: t.success_rate
    }));
    // 使用 ECharts 绘制柱状图
    const chart = echarts.init(document.getElementById('chart'));
    chart.setOption({
      xAxis: { type: 'category', data: chartData.map(d => d.name) },
      yAxis: { type: 'value', max: 100, name: '成功率(%)' },
      series: [{
        type: 'bar',
        data: chartData.map(d => d.value)
      }]
    });
  });

优化与陷阱提示

  1. 数据量过大:如果一场比赛传球超5000次,务必给 match_idstart_x 建立复合索引INDEX(match_id, start_x)),否则查询会极慢。
  2. 准确性:SQL中的 ROUND(..., 1) 建议在PHP层做,避免浮点数精度问题。
  3. 定义歧义:Opta 定义进攻三区为场上 X 坐标 >= 60,但某些统计机构(如 Wyscout)会以“距离球门30米”为界。确保你的数据源定义的坐标系与查询条件一致

如果你需要更具体的代码(比如原生PHP PDO完整类、或针对特定数据源如StatsBomb的适配),请告诉我你的数据结构,我可以进一步细化。

抱歉,评论功能暂时关闭!