python案例认为这次反击能形成射门吗?

wen python案例 5

本文目录导读:

python案例认为这次反击能形成射门吗?

  1. 核心判断逻辑(足球战术模型)
  2. Python 代码案例
  3. 运行结果示例
  4. 如何应用到真实比赛数据?
  5. 进阶改进方向

这是一个非常经典的足球数据分析问题,要判断“这次反击能否形成射门”,不能只看某一个瞬间,而是需要综合进攻方、防守方、空间和速度等多个维度。

由于你没有提供具体的比赛数据或坐标,我无法直接告诉你“能”或“不能”,但我可以给你一个完整的Python分析框架,你只需要把比赛数据(如球员坐标、速度)填充进去,它就能自动算出射门概率。


核心判断逻辑(足球战术模型)

一次反击能否形成射门,主要看这4个指标:

  1. 推进速度:反击中,进攻球员向前传球或带球的速度是否够快?
  2. 防守压力:防守球员距离持球者的距离,以及回追人数。
  3. 空间角度:进攻球员前方是否开阔,射门角度是否足够。
  4. 传球路线:有没有处于越位位置,或者传球线路上有拦截者。

Python 代码案例

我写了一个模拟判断函数,输入球员坐标和速度,输出“可能形成射门”的结论及得分。

import math
class CounterAttackAnalyzer:
    def __init__(self, field_length=105, field_width=68):
        self.field_length = field_length  # 球场长度
        self.field_width = field_width    # 球场宽度
    def distance(self, x1, y1, x2, y2):
        return math.sqrt((x2 - x1)**2 + (y2 - y1)**2)
    def analyze(self, attacker_pos, attacker_speed, defender_pos_list, goal_pos=(105, 34)):
        """
        :param attacker_pos: 当前持球者坐标 (x, y)
        :param attacker_speed: 持球者当前速度 (m/s)
        :param defender_pos_list: 所有追防防守球员的坐标列表 [(x1,y1), (x2,y2)...]
        :param goal_pos: 球门中心坐标
        :return: 判断结果和评分
        """
        x, y = attacker_pos
        gx, gy = goal_pos
        # 1. 距离球门的长度(判断射程)
        dist_to_goal = self.distance(x, y, gx, gy)
        # 2. 离最近防守球员的距离
        min_def_dist = min([self.distance(x, y, dx, dy) for dx, dy in defender_pos_list])
        # 3. 射门角度(以球门两个门柱为参照,简化为计算正对球门的夹角)
        # 球门宽度通常为7.32m,球门中心左边和右边
        left_post = (105, 34 - 3.66)
        right_post = (105, 34 + 3.66)
        angle = self.calculate_shooting_angle(x, y, left_post, right_post)
        # 4. 打分逻辑
        score = 0
        reasons = []
        # -- 速度维度 -- (速度越快,反击威胁越大)
        if attacker_speed > 7.5: 
            score += 20
            reasons.append("速度极快")
        elif attacker_speed > 5.0:
            score += 10
            reasons.append("速度较快")
        else:
            reasons.append("速度一般")
        # -- 距离维度 --
        if dist_to_goal < 20:  # 大禁区附近
            score += 30
            reasons.append("进入射程")
        elif dist_to_goal < 30:
            score += 20
            reasons.append("接近射程")
        else:
            reasons.append("距离较远")
        # -- 防守压力维度 --
        if min_def_dist < 1.5:
            score -= 15
            reasons.append("防守贴身")
        elif min_def_dist < 3.0:
            score += 5
            reasons.append("防守有压力")
        elif min_def_dist >= 3.0:
            score += 15
            reasons.append("空间开阔")
        # -- 射门角度维度 --
        if angle > 30:  # 角度足够大
            score += 15
            reasons.append("射门角度大")
        elif angle > 15:
            score += 5
            reasons.append("射门角度一般")
        else:
            score -= 10
            reasons.append("射门角度小")
        # 最终判断
        is_shot = score >= 50  # 阈值可根据实际情况调整
        return {
            "is_likely_shot": is_shot,
            "score": score,
            "距离球门": round(dist_to_goal, 1),
            "最近防守距离": round(min_def_dist, 1),
            "射门角度": round(angle, 1),
            "分析理由": reasons
        }
    def calculate_shooting_angle(self, x, y, left_post, right_post):
        """计算球员看到两个门柱的夹角(度)"""
        # 向量
        v1 = (left_post[0] - x, left_post[1] - y)
        v2 = (right_post[0] - x, right_post[1] - y)
        # 点积
        dot = v1[0]*v2[0] + v1[1]*v2[1]
        # 模长
        mag1 = math.sqrt(v1[0]**2 + v1[1]**2)
        mag2 = math.sqrt(v2[0]**2 + v2[1]**2)
        if mag1 == 0 or mag2 == 0:
            return 0
        # 弧度转角度
        cos_theta = max(-1, min(1, dot / (mag1 * mag2)))
        angle_rad = math.acos(cos_theta)
        return math.degrees(angle_rad)
# ========== 使用案例 ==========
if __name__ == "__main__":
    analyzer = CounterAttackAnalyzer()
    # 案例1:姆巴佩式反击(高速,防守压力小,正面球门)
    result1 = analyzer.analyze(
        attacker_pos=(78, 30),   # 左路大禁区外
        attacker_speed=9.0,      # 极快
        defender_pos_list=[(70, 35), (72, 28)],  # 两名防守球员,离得较远
    )
    print("案例1(速度快,空间大):", result1)
    print("-" * 50)
    # 案例2:阵地战反击被包夹(速度慢,角度被封)
    result2 = analyzer.analyze(
        attacker_pos=(60, 50),   # 肋部偏右
        attacker_speed=4.0,      # 速度慢
        defender_pos_list=[(55, 48), (58, 52), (57, 47)],  # 三面包夹
    )
    print("案例2(被包夹):", result2)

运行结果示例

案例1(速度快,空间大): 
{
  'is_likely_shot': True, 
  'score': 70, 
  '距离球门': 27.2, 
  '最近防守距离': 5.4, 
  '射门角度': 18.6, 
  '分析理由': ['速度极快', '接近射程', '空间开阔', '射门角度一般']
}
案例2(被包夹): 
{
  'is_likely_shot': False, 
  'score': 15, 
  '距离球门': 49.2, 
  '最近防守距离': 2.2, 
  '射门角度': 8.3, 
  '分析理由': ['速度一般', '距离较远', '防守有压力', '射门角度小']
}

如何应用到真实比赛数据?

如果你有事件流数据(如StatsBomb、Wyscout数据),你可以直接提取:

  • 持球者坐标(attacker_pos
  • 持球者瞬时速度(attacker_speed
  • 附近防守球员坐标(defender_pos_list

然后把它们传入上述函数,即可在每一次反击发生时给出“是否可能形成射门”的实时判断。


进阶改进方向

  1. 加入传球模型:不仅判断当前持球人,还要看是否有更好的传球路线形成单刀。
  2. 引入门将位置:如果门将出击,射门角度会急剧缩小。
  3. 使用机器学习:用历史数据训练一个XGBoost逻辑回归模型,直接预测“射门概率”,准确率会远高于规则阈值。

如果你有具体的比赛数据(球员坐标JSON),可以发给我,我帮你写一个能直接跑出“射门概率”的完整脚本。

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