python案例统计界外球进攻威胁次数?

wen python案例 3

本文目录导读:

python案例统计界外球进攻威胁次数?

  1. 整体思路
  2. 完整代码实现
  3. 简化版本(适合快速使用)
  4. 使用说明
  5. 判定标准说明

我来为您设计一个足球比赛中统计界外球进攻威胁次数的Python案例。

整体思路

界外球进攻威胁的判定需要考虑多个因素:

  • 界外球位置(越靠近对方禁区威胁越大)
  • 是否形成射门
  • 是否形成传中
  • 是否造成对方防守混乱

完整代码实现

import pandas as pd
import numpy as np
from datetime import datetime
import json
class ThrowInThreatAnalyzer:
    """界外球进攻威胁分析器"""
    def __init__(self):
        # 定义球场区域(将球场分为多个区域)
        self.pitch_zones = {
            'own_defensive': {'name': '本方后场', 'x_range': (0, 30), 'threat_weight': 0.1},
            'own_midfield': {'name': '本方中场', 'x_range': (30, 50), 'threat_weight': 0.2},
            'midfield': {'name': '中场', 'x_range': (50, 70), 'threat_weight': 0.3},
            'opp_midfield': {'name': '对方中场', 'x_range': (70, 90), 'threat_weight': 0.5},
            'opp_final_third': {'name': '对方前场', 'x_range': (90, 105), 'threat_weight': 0.8},
            'opp_box': {'name': '对方禁区', 'x_range': (105, 120), 'threat_weight': 1.0}
        }
        # 结果存储
        self.results = []
    def judge_zone(self, x_coordinate):
        """判断界外球所在区域"""
        for zone_id, zone_info in self.pitch_zones.items():
            if zone_info['x_range'][0] <= x_coordinate < zone_info['x_range'][1]:
                return zone_id, zone_info
        return 'unknown', None
    def analyze_throw_in(self, throw_in_data):
        """
        分析单个界外球事件
        参数:
        throw_in_data: dict - 界外球数据
            - position_x: 界外球位置的x坐标(0-120米)
            - position_y: 界外球位置的y坐标(0-80米)
            - player_position: 掷球后接球球员位置
            - outcome: 掷球结果 ('射门', '助攻', '传中', '角球', '无效', '丢失')
            - time: 比赛时间
        返回:
        dict - 分析结果
        """
        try:
            x_coord = throw_in_data.get('position_x', 0)
            y_coord = throw_in_data.get('position_y', 40)
            # 判断区域
            zone_id, zone_info = self.judge_zone(x_coord)
            # 基础威胁得分
            base_threat = zone_info['threat_weight'] if zone_info else 0.3
            # 根据结果加权
            threat_score = base_threat
            # 分析掷球结果
            outcome = throw_in_data.get('outcome', '丢失')
            outcome_multipliers = {
                '射门': 2.0,
                '助攻': 1.8,
                '传中': 1.5,
                '角球': 1.3,
                '进球': 3.0,
                '无效': 0.3,
                '丢失': 0.1
            }
            threat_multiplier = outcome_multipliers.get(outcome, 0.5)
            threat_score *= threat_multiplier
            # 考虑接球位置(如果靠近球门)
            if throw_in_data.get('player_position'):
                player_x = throw_in_data['player_position'].get('x', 0)
                # 接球位置越靠近对方球门,威胁越大
                if player_x > 90:
                    threat_score *= 1.3
            # 判断威胁等级
            if threat_score >= 1.5:
                threat_level = '高威胁'
            elif threat_score >= 0.8:
                threat_level = '中等威胁'
            elif threat_score >= 0.3:
                threat_level = '低威胁'
            else:
                threat_level = '无威胁'
            # 记录分析结果
            result = {
                'time': throw_in_data.get('time', ''),
                'position': (x_coord, y_coord),
                'zone': zone_info['name'] if zone_info else '未知',
                'outcome': outcome,
                'base_threat': round(base_threat, 2),
                'threat_score': round(threat_score, 2),
                'threat_level': threat_level
            }
            self.results.append(result)
            return result
        except Exception as e:
            print(f"分析界外球时出错: {e}")
            return None
    def analyze_batch(self, throw_in_events):
        """批量分析多个界外球事件"""
        results = []
        for event in throw_in_events:
            result = self.analyze_throw_in(event)
            if result:
                results.append(result)
        return results
    def calculate_total_threats(self, high_threat_only=False):
        """计算总威胁次数"""
        if not self.results:
            return 0
        if high_threat_only:
            # 只计算高威胁
            return sum(1 for r in self.results if r['threat_level'] == '高威胁')
        else:
            # 计算所有有威胁的界外球事件
            return sum(1 for r in self.results if r['threat_level'] != '无威胁')
    def print_analysis_report(self):
        """打印分析报告"""
        print("=" * 60)
        print("界外球进攻威胁分析报告")
        print("=" * 60)
        if not self.results:
            print("暂无界外球数据分析")
            return
        # 统计数据
        total_throw_ins = len(self.results)
        high_threats = sum(1 for r in self.results if r['threat_level'] == '高威胁')
        mid_threats = sum(1 for r in self.results if r['threat_level'] == '中等威胁')
        low_threats = sum(1 for r in self.results if r['threat_level'] == '低威胁')
        no_threats = total_throw_ins - high_threats - mid_threats - low_threats
        print(f"\n总界外球次数: {total_throw_ins}")
        print(f"高威胁次数: {high_threats}")
        print(f"中等威胁次数: {mid_threats}")
        print(f"低威胁次数: {low_threats}")
        print(f"无威胁次数: {no_threats}")
        print(f"\n进攻威胁总次数: {self.calculate_total_threats()}")
        print(f"高威胁占比: {high_threats/total_throw_ins*100:.1f}%" if total_throw_ins > 0 else "")
        # 按区域和结果分析
        print("\n--- 区域分布 ---")
        zone_stats = {}
        for r in self.results:
            zone = r['zone']
            if zone not in zone_stats:
                zone_stats[zone] = {'count': 0, 'threats': 0}
            zone_stats[zone]['count'] += 1
            if r['threat_level'] != '无威胁':
                zone_stats[zone]['threats'] += 1
        for zone, stats in zone_stats.items():
            print(f"{zone}: 共{stats['count']}次, stats['threats']}次构成威胁")
        # 详细结果列表
        print("\n--- 详细事件列表 ---")
        for idx, r in enumerate(self.results, 1):
            print(f"{idx}. 时间: {r['time']}")
            print(f"   位置: {r['position']}")
            print(f"   区域: {r['zone']}")
            print(f"   结果: {r['outcome']}")
            print(f"   威胁得分: {r['threat_score']}")
            print(f"   威胁等级: {r['threat_level']}")
            print()
def generate_sample_data():
    """生成示例数据"""
    return [
        {
            'time': '12:30',
            'position_x': 110,
            'position_y': 65,
            'player_position': {'x': 108, 'y': 70},
            'outcome': '射门',
            'team': '主队'
        },
        {
            'time': '25:10',
            'position_x': 85,
            'position_y': 35,
            'player_position': {'x': 88, 'y': 40},
            'outcome': '传中',
            'team': '主队'
        },
        {
            'time': '38:45',
            'position_x': 60,
            'position_y': 45,
            'player_position': {'x': 62, 'y': 50},
            'outcome': '丢失',
            'team': '主队'
        },
        {
            'time': '52:20',
            'position_x': 115,
            'position_y': 50,
            'player_position': {'x': 112, 'y': 55},
            'outcome': '助攻',
            'team': '主队'
        },
        {
            'time': '70:15',
            'position_x': 95,
            'position_y': 30,
            'player_position': {'x': 97, 'y': 35},
            'outcome': '角球',
            'team': '主队'
        },
        {
            'time': '83:50',
            'position_x': 100,
            'position_y': 20,
            'player_position': {'x': 102, 'y': 25},
            'outcome': '传中',
            'team': '主队'
        },
        {
            'time': '88:33',
            'position_x': 30,
            'position_y': 60,
            'player_position': {'x': 35, 'y': 55},
            'outcome': '丢失',
            'team': '主队'
        }
    ]
def main():
    """主函数示例"""
    # 创建分析器
    analyzer = ThrowInThreatAnalyzer()
    # 生成示例数据
    sample_events = generate_sample_data()
    # 分析界外球事件
    print("开始分析界外球事件...")
    results = analyzer.analyze_batch(sample_events)
    # 打印分析报告
    analyzer.print_analysis_report()
    # 导出结果到JSON
    with open('throw_in_analysis.json', 'w', encoding='utf-8') as f:
        json.dump(analyzer.results, f, ensure_ascii=False, indent=2)
    print("分析结果已保存到 throw_in_analysis.json")
    # 额外分析示例
    print("\n" + "="*60)
    print("进阶统计数据")
    print("="*60)
    print(f"总界外球威胁次数: {analyzer.calculate_total_threats()}")
    print(f"仅高威胁次数: {analyzer.calculate_total_threats(high_threat_only=True)}")
if __name__ == "__main__":
    main()

简化版本(适合快速使用)

def simple_throw_in_threat_analysis(throw_in_data):
    """
    简化的界外球威胁分析函数
    参数:
    throw_in_data: list of dict, 每个dict包含:
        - x_position: 球在纵轴的位置(0-120)
        - was_shot: 是否形成射门
        - was_cross: 是否形成传中
        - was_foul_won: 是否赢得犯规
    返回:
    tuple: (总次数, 威胁次数)
    """
    threat_count = 0
    total_count = len(throw_in_data)
    for event in throw_in_data:
        # 简单评分系统
        threat_score = 0
        # 位置因素 (x > 90 表示在对方30米区域)
        if event['x_position'] > 90:
            threat_score += 1
        # 结果因素
        if event.get('was_shot'):
            threat_score += 2
        if event.get('was_cross'):
            threat_score += 1.5
        if event.get('was_foul_won'):
            threat_score += 0.5
        # 判断是否构成威胁
        if threat_score >= 1.5:  # 至少要有位置优势加一个积极结果
            threat_count += 1
    return total_count, threat_count
# 使用示例
sample_data = [
    {'x_position': 115, 'was_shot': True, 'was_cross': False, 'was_foul_won': False},
    {'x_position': 85, 'was_shot': False, 'was_cross': True, 'was_foul_won': True},
    {'x_position': 60, 'was_shot': False, 'was_cross': False, 'was_foul_won': False},
]
total, threats = simple_throw_in_threat_analysis(sample_data)
print(f"总界外球数: {total}, 威胁次数: {threats}")

使用说明

数据准备

需要准备界外球事件的数据,包含:

  • 位置信息: 界外球发生的x坐标(模拟足球场长度0-120米)
  • 结果: 掷球后发生了什么(射门、传中、助攻等)
  • 时间: 事件发生时间

运行方式

python throw_in_analyzer.py

输出结果

程序会输出:

  • 各种威胁等级的数量
  • 总威胁次数
  • 高威胁占比
  • 按区域统计
  • 每个事件的详细分析
  • 自动保存JSON文件

判定标准说明

威胁等级判定:

  • 高威胁(得分>=1.5): 在对方禁区附近获得球权并形成射门/助攻
  • 中等威胁(得分>=0.8): 前场30米内的界外球形成传中或得到角球
  • 低威胁(得分>=0.3): 中场的界外球有进攻的意图
  • 无威胁: 防守压力下的求生性掷球

这个系统可以应用于:

  1. 赛后技术统计
  2. 球员/教练战术分析
  3. 视频分析师的数据标注
  4. 球员专项训练效果评估

您可以根据实际需求调整权重参数和判定标准!

上一篇这个python案例对当前比分有何反应?

下一篇当前分类已是最新一篇

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