python案例统计高球传中争顶成功率?

wen python案例 2

本文目录导读:

python案例统计高球传中争顶成功率?

  1. 基础数据模型
  2. 核心统计功能
  3. 高级分析功能
  4. 可视化分析
  5. 完整使用示例

我来为你设计一个Python统计高球传中争顶成功率的方案:

基础数据模型

import pandas as pd
import numpy as np
from datetime import datetime
# 定义比赛事件数据
class FootballEvent:
    def __init__(self):
        self.events = []
    def add_event(self, match_id, player_id, player_name, team, event_type, 
                  outcome, position_x, position_y, minute, assist_player=None):
        """添加比赛事件
        Args:
            event_type: 'cross' (传中) 或 'header' (争顶)
            outcome: 'success' (成功) 或 'fail' (失败)
        """
        self.events.append({
            'match_id': match_id,
            'player_id': player_id,
            'player_name': player_name,
            'team': team,
            'event_type': event_type,
            'outcome': outcome,
            'position_x': position_x,
            'position_y': position_y,
            'minute': minute,
            'assist_player': assist_player,
            'timestamp': datetime.now()
        })

核心统计功能

class CrossHeaderStats:
    def __init__(self, events_data):
        self.df = pd.DataFrame(events_data)
        self.prepare_data()
    def prepare_data(self):
        """数据预处理"""
        # 分离传中和争顶事件
        self.crosses = self.df[self.df['event_type'] == 'cross']
        self.headers = self.df[self.df['event_type'] == 'header']
    def calculate_success_rate(self, group_by=None):
        """计算争顶成功率
        Args:
            group_by: 'player', 'team', 'match' 或 None
        """
        if group_by == 'player':
            grouped = self.headers.groupby('player_name')
        elif group_by == 'team':
            grouped = self.headers.groupby('team')
        elif group_by == 'match':
            grouped = self.headers.groupby('match_id')
        else:
            # 总成功率
            total = len(self.headers)
            success = len(self.headers[self.headers['outcome'] == 'success'])
            return {'total_headers': total, 
                    'success': success,
                    'success_rate': success / total if total > 0 else 0}
        result = {}
        for name, group in grouped:
            total = len(group)
            success = len(group[group['outcome'] == 'success'])
            result[name] = {
                'total': total,
                'success': success,
                'success_rate': success / total if total > 0 else 0
            }
        return result
    def analyze_cross_header_connection(self):
        """分析传中与争顶的关联性"""
        # 将传中事件和后续的争顶事件关联
        cross_connected = []
        for idx, cross in self.crosses.iterrows():
            # 查找同一场比赛,2秒内(或一定时间范围内)的争顶事件
            match_headers = self.headers[
                (self.headers['match_id'] == cross['match_id']) & 
                (self.headers['timestamp'] > cross['timestamp'])
            ]
            if len(match_headers) > 0:
                # 取最近的争顶事件
                nearest_header = match_headers.iloc[0]
                cross_connected.append({
                    'cross_player': cross['player_name'],
                    'header_player': nearest_header['player_name'],
                    'team': cross['team'],
                    'cross_success': cross['outcome'],
                    'header_success': nearest_header['outcome'],
                    'position_x': cross['position_x'],
                    'position_y': cross['position_y']
                })
        return pd.DataFrame(cross_connected)

高级分析功能

class AdvancedCrossHeaderAnalysis:
    def __init__(self, stats_data):
        self.stats = stats_data
    def analysis_by_position(self):
        """按球场位置分析"""
        # 定义球场区域
        def get_area(x, y):
            if x < 0.3:  # 左路
                if y < 0.5:
                    return '左路浅'
                else:
                    return '左路深'
            elif x > 0.7:  # 右路
                if y < 0.5:
                    return '右路浅'
                else:
                    return '右路深'
            else:  # 中路
                if y < 0.5:
                    return '中路浅'
                else:
                    return '中路深'
        self.stats['area'] = self.stats.apply(
            lambda row: get_area(row['position_x'], row['position_y']), axis=1)
        # 按区域统计成功率
        area_stats = {}
        for area in self.stats['area'].unique():
            area_data = self.stats[self.stats['area'] == area]
            success = len(area_data[area_data['outcome'] == 'success'])
            total = len(area_data)
            area_stats[area] = {
                'total': total,
                'success': success,
                'success_rate': success/total if total > 0 else 0
            }
        return area_stats
    def analyze_against_defense_type(self):
        """分析不同防守类型下的成功率"""
        # 假设有防守类型数据
        defense_data = {
            'high_block': 0.35,  # 高位逼抢
            'mid_block': 0.45,   # 中场防守
            'low_block': 0.55,   # 低位防守
        }
        return defense_data
    def trend_analysis(self):
        """趋势分析:按时间节点分析成功率变化"""
        self.stats['time_phase'] = pd.cut(
            self.stats['minute'], 
            bins=[0, 15, 30, 45, 60, 75, 90], 
            labels=['0-15', '15-30', '30-45', '45-60', '60-75', '75-90']
        )
        trend = {}
        for phase in self.stats['time_phase'].unique():
            phase_data = self.stats[self.stats['time_phase'] == phase]
            success = len(phase_data[phase_data['outcome'] == 'success'])
            total = len(phase_data)
            trend[phase] = success/total if total > 0 else 0
        return trend

可视化分析

import matplotlib.pyplot as plt
import seaborn as sns
class CrossHeaderVisualization:
    def __init__(self, stats):
        self.stats = stats
    def plot_success_rate_by_player(self):
        """绘制球员成功率对比图"""
        player_stats = self.stats.calculate_success_rate('player')
        players = list(player_stats.keys())
        rates = [player_stats[p]['success_rate'] for p in players]
        plt.figure(figsize=(12, 6))
        plt.bar(players, rates, color='skyblue')
        plt.xlabel('球员')
        plt.ylabel('争顶成功率')
        plt.title('球员高球传中争顶成功率对比')
        plt.xticks(rotation=45)
        plt.tight_layout()
        plt.show()
    def plot_position_heatmap(self, success_data):
        """绘制球场位置热力图"""
        if 'position_x' in self.stats.columns and 'position_y' in self.stats.columns:
            plt.figure(figsize=(12, 8))
            sns.kdeplot(
                data=self.stats, 
                x='position_x', 
                y='position_y', 
                hue='outcome',
                levels=20
            )
            plt.title('争顶成功与失败位置分布')
            plt.xlabel('球场横向位置')
            plt.ylabel('球场纵向位置')
            plt.show()

完整使用示例

def demo_cross_header_analysis():
    """演示完整分析流程"""
    # 创建模拟数据
    stats = CrossHeaderStats([])
    # 模拟数据生成
    np.random.seed(42)
    players = ['张三', '李四', '王五', '赵六', '孙七']
    teams = ['A队', 'B队']
    events = []
    for i in range(100):
        events.append({
            'match_id': np.random.randint(1, 5),
            'player_id': np.random.randint(1, 10),
            'player_name': np.random.choice(players),
            'team': np.random.choice(teams),
            'event_type': np.random.choice(['cross', 'header']),
            'outcome': np.random.choice(['success', 'fail'], p=[0.4, 0.6]),
            'position_x': np.random.uniform(0, 1),
            'position_y': np.random.uniform(0, 1),
            'minute': np.random.randint(1, 90),
            'assist_player': np.random.choice(players) if np.random.random() > 0.5 else None,
            'timestamp': datetime.now()
        })
    # 初始化分析对象
    stats = CrossHeaderStats(pd.DataFrame(events))
    # 总成功率
    total_rate = stats.calculate_success_rate()
    print(f"总争顶成功率: {total_rate['success_rate']:.2%}")
    # 按球员分析
    player_rates = stats.calculate_success_rate('player')
    print("\n球员争顶成功率:")
    for player, data in player_rates.items():
        print(f"{player}: {data['success_rate']:.2%} ({data['success']}/{data['total']}次)")
    # 高级分析
    advanced = AdvancedCrossHeaderAnalysis(pd.DataFrame(events))
    area_analysis = advanced.analysis_by_position()
    print("\n区域分析:")
    for area, data in area_analysis.items():
        print(f"{area}: {data['success_rate']:.2%}")
    # 可视化
    viz = CrossHeaderVisualization(stats)
    viz.plot_success_rate_by_player()
    viz.plot_position_heatmap(pd.DataFrame(events))
# 运行演示
if __name__ == "__main__":
    demo_cross_header_analysis()

这个系统可以:

  1. 统计球员/球队/比赛级别的争顶成功率
  2. 分析传中与争顶的关联性
  3. 按位置、时间等因素深入分析
  4. 可视化展示数据

你可以根据实际数据调整数据格式,或者添加更多分析维度(如对手强度、天气条件等)。

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