python案例统计门球短传配合成功率?

wen python案例 6

本文目录导读:

python案例统计门球短传配合成功率?

  1. 完整的Python实现
  2. 功能特点说明
  3. 输出示例

我来为您设计一个门球短传配合成功率的统计分析Python案例,这个案例将模拟和处理门球比赛中短传配合的数据。

完整的Python实现

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from datetime import datetime
import random
# 设置中文显示
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
class GateBallPassAnalyzer:
    """门球短传配合成功率分析器"""
    def __init__(self):
        self.data = None
        self.pass_records = []
    def generate_sample_data(self, num_matches=10, num_passes_per_match=30):
        """生成模拟数据"""
        np.random.seed(42)
        records = []
        players = ['张伟', '李强', '王芳', '赵敏', '刘洋', '陈静']
        positions = ['1号位', '2号位', '3号位', '4号位', '5号位', '6号位']
        for match_id in range(1, num_matches + 1):
            for pass_num in range(num_passes_per_match):
                # 随机生成传球数据
                passer = random.choice(players)
                receiver = random.choice([p for p in players if p != passer])
                # 传球距离(米)- 短传距离一般为3-8米
                distance = round(random.uniform(3, 8), 1)
                # 传球成功率(80-95%基础成功率,随距离增加而降低)
                base_success = random.uniform(0.85, 0.95)
                distance_factor = 1 - (distance - 3) * 0.02
                success_prob = base_success * distance_factor
                # 判断是否成功
                success = np.random.choice([True, False], p=[success_prob, 1-success_prob])
                # 传球速度(米/秒)
                speed = round(random.uniform(3, 8), 1)
                # 防守压力等级(1-5)
                pressure = random.randint(1, 5)
                # 比赛时间(分钟)
                minute = random.randint(1, 30)
                records.append({
                    'match_id': match_id,
                    'pass_number': pass_num + 1,
                    'passer': passer,
                    'receiver': receiver,
                    'passer_position': random.choice(positions),
                    'receiver_position': random.choice(positions),
                    'distance': distance,
                    'speed': speed,
                    'pressure': pressure,
                    'minute': minute,
                    'success': success,
                    'catches': success  # 是否接住
                })
        self.data = pd.DataFrame(records)
        return self.data
    def calculate_success_rate(self):
        """计算总体成功率"""
        if self.data is None:
            return None
        total_passes = len(self.data)
        successful_passes = self.data['success'].sum()
        success_rate = successful_passes / total_passes * 100
        return {
            'total_passes': total_passes,
            'successful_passes': successful_passes,
            'success_rate': round(success_rate, 2)
        }
    def analyze_by_player(self):
        """按球员分析传球成功率"""
        if self.data is None:
            return None
        player_stats = {}
        # 传球成功统计
        passer_stats = self.data.groupby('passer')['success'].agg(['count', 'sum', 'mean'])
        passer_stats.columns = ['总传球数', '成功次数', '成功率']
        passer_stats['成功率'] = passer_stats['成功率'] * 100
        # 接球成功统计
        receiver_stats = self.data.groupby('receiver')['catches'].agg(['count', 'sum', 'mean'])
        receiver_stats.columns = ['总接球数', '成功次数', '接球成功率']
        receiver_stats['接球成功率'] = receiver_stats['接球成功率'] * 100
        # 综合统计
        all_players = set(self.data['passer'].unique()) | set(self.data['receiver'].unique())
        for player in all_players:
            if player in passer_stats.index:
                pass_rate = passer_stats.loc[player, '成功率']
                total_passes = passer_stats.loc[player, '总传球数']
            else:
                pass_rate = 0
                total_passes = 0
            if player in receiver_stats.index:
                receive_rate = receiver_stats.loc[player, '接球成功率']
                total_receives = receiver_stats.loc[player, '总接球数']
            else:
                receive_rate = 0
                total_receives = 0
            player_stats[player] = {
                '传球次数': total_passes,
                '传球成功率': round(pass_rate, 2),
                '接球次数': total_receives,
                '接球成功率': round(receive_rate, 2)
            }
        return pd.DataFrame(player_stats).T
    def analyze_by_distance(self):
        """按传球距离分析"""
        if self.data is None:
            return None
        # 将距离分段
        self.data['distance_group'] = pd.cut(self.data['distance'], 
                                            bins=[0, 4, 6, 8, 10], 
                                            labels=['3-4米', '4-6米', '6-8米', '8米以上'])
        distance_stats = self.data.groupby('distance_group')['success'].agg(['count', 'sum', 'mean'])
        distance_stats.columns = ['传球次数', '成功次数', '成功率']
        distance_stats['成功率'] = distance_stats['成功率'] * 100
        return distance_stats
    def analyze_by_pressure(self):
        """按防守压力分析"""
        if self.data is None:
            return None
        pressure_stats = self.data.groupby('pressure')['success'].agg(['count', 'sum', 'mean'])
        pressure_stats.columns = ['传球次数', '成功次数', '成功率']
        pressure_stats['成功率'] = pressure_stats['成功率'] * 100
        return pressure_stats
    def analyze_by_minute(self):
        """按比赛时间分析"""
        if self.data is None:
            return None
        self.data['time_period'] = pd.cut(self.data['minute'], 
                                         bins=[0, 10, 20, 30], 
                                         labels=['开场(0-10分)', '中段(11-20分)', '末段(21-30分)'])
        minute_stats = self.data.groupby('time_period')['success'].agg(['count', 'sum', 'mean'])
        minute_stats.columns = ['传球次数', '成功次数', '成功率']
        minute_stats['成功率'] = minute_stats['成功率'] * 100
        return minute_stats
    def analyze_combinations(self):
        """分析球员组合成功率"""
        if self.data is None:
            return None
        self.data['combination'] = self.data['passer'] + ' → ' + self.data['receiver']
        combo_stats = self.data.groupby('combination')['success'].agg(['count', 'sum', 'mean'])
        combo_stats.columns = ['传球次数', '成功次数', '成功率']
        combo_stats['成功率'] = combo_stats['成功率'] * 100
        combo_stats = combo_stats.sort_values('传球次数', ascending=False)
        return combo_stats.head(10)
    def visualize_results(self):
        """可视化分析结果"""
        if self.data is None:
            return
        fig = plt.figure(figsize=(16, 12))
        # 1. 总体成功率
        ax1 = plt.subplot(2, 3, 1)
        overall = self.calculate_success_rate()
        colors = ['#2ecc71' if success else '#e74c3c' for success in [True, False]]
        plt.pie([overall['successful_passes'], overall['total_passes'] - overall['successful_passes']],
                labels=['成功', '失败'],
                colors=colors,
                autopct='%1.1f%%',
                startangle=90)
        plt.title(f'总体成功率: {overall["success_rate"]}%')
        # 2. 球员传球成功率
        ax2 = plt.subplot(2, 3, 2)
        player_stats = self.analyze_by_player()
        player_stats['传球成功率'].plot(kind='bar', ax=ax2, color='#3498db')
        plt.title('球员传球成功率')
        plt.xlabel('球员')
        plt.ylabel('成功率 (%)')
        plt.xticks(rotation=45)
        plt.ylim(0, 100)
        # 3. 距离分析
        ax3 = plt.subplot(2, 3, 3)
        distance_stats = self.analyze_by_distance()
        distance_stats['成功率'].plot(kind='bar', ax=ax3, color='#9b59b6')
        plt.title('传球距离与成功率')
        plt.xlabel('距离区间')
        plt.ylabel('成功率 (%)')
        plt.xticks(rotation=45)
        plt.ylim(0, 100)
        # 4. 防守压力分析
        ax4 = plt.subplot(2, 3, 4)
        pressure_stats = self.analyze_by_pressure()
        pressure_stats['成功率'].plot(kind='bar', ax=ax4, color='#e67e22')
        plt.title('防守压力与成功率')
        plt.xlabel('防守压力等级')
        plt.ylabel('成功率 (%)')
        plt.xticks(rotation=0)
        plt.ylim(0, 100)
        # 5. 时间段分析
        ax5 = plt.subplot(2, 3, 5)
        minute_stats = self.analyze_by_minute()
        minute_stats['成功率'].plot(kind='bar', ax=ax5, color='#1abc9c')
        plt.title('比赛时间与成功率')
        plt.xlabel('时间区间')
        plt.ylabel('成功率 (%)')
        plt.xticks(rotation=45)
        plt.ylim(0, 100)
        # 6. 组合分析
        ax6 = plt.subplot(2, 3, 6)
        combo_stats = self.analyze_combinations()
        combo_stats['成功率'].head(5).plot(kind='barh', ax=ax6, color='#e74c3c')
        plt.title('最佳传球组合Top5')
        plt.xlabel('成功率 (%)')
        plt.xlim(0, 100)
        plt.tight_layout()
        plt.show()
    def save_report(self, filename='门球短传配合报告.txt'):
        """保存分析报告"""
        with open(filename, 'w', encoding='utf-8') as f:
            f.write("=" * 60 + "\n")
            f.write("门球短传配合成功率分析报告\n")
            f.write("=" * 60 + "\n\n")
            # 总体统计
            overall = self.calculate_success_rate()
            f.write("【总体统计】\n")
            f.write(f"总传球次数: {overall['total_passes']}\n")
            f.write(f"成功次数: {overall['successful_passes']}\n")
            f.write(f"总成功率: {overall['success_rate']}%\n\n")
            # 球员统计
            f.write("【球员统计】\n")
            player_stats = self.analyze_by_player()
            f.write(player_stats.to_string())
            f.write("\n\n")
            # 距离统计
            f.write("【距离统计】\n")
            distance_stats = self.analyze_by_distance()
            f.write(distance_stats.to_string())
            f.write("\n\n")
            # 防守压力统计
            f.write("【防守压力统计】\n")
            pressure_stats = self.analyze_by_pressure()
            f.write(pressure_stats.to_string())
            f.write("\n\n")
            # 最佳组合
            f.write("【最佳传球组合Top5】\n")
            combo_stats = self.analyze_combinations()
            f.write(combo_stats.head().to_string())
            f.write("\n")
        print(f"报告已保存至: {filename}")
# 使用示例
if __name__ == "__main__":
    # 创建分析器
    analyzer = GateBallPassAnalyzer()
    # 生成模拟数据
    print("正在生成模拟数据...")
    data = analyzer.generate_sample_data(num_matches=10, num_passes_per_match=30)
    print(f"数据生成完成!共{len(data)}次传球。\n")
    # 计算总体成功率
    print("总体统计:")
    overall = analyzer.calculate_success_rate()
    for key, value in overall.items():
        print(f"  {key}: {value}")
    print()
    # 球员分析
    print("\n球员分析:")
    player_stats = analyzer.analyze_by_player()
    print(player_stats.round(2))
    print()
    # 距离分析
    print("\n传球距离分析:")
    distance_stats = analyzer.analyze_by_distance()
    print(distance_stats.round(2))
    print()
    # 可视化结果
    print("\n生成可视化图表...")
    analyzer.visualize_results()
    # 保存报告
    print("\n保存分析报告...")
    analyzer.save_report()
    print("\n分析完成!")

功能特点说明

数据生成

  • 模拟10场比赛,每场30次短传
  • 包含6名球员,多个战术位置
  • 考虑传球距离、速度、防守压力等因素

分析维度

  • 总体成功率:所有传球的基本成功率
  • 球员分析:单独统计每个球员的传球和接球成功率
  • 距离分析:不同传球距离区间的成功率
  • 防守压力:不同防守强度下的成功率
  • 时间分析:比赛不同阶段的成功率变化
  • 组合分析:球员间的默契配合成功率

可视化输出

  • 饼图显示总体成功率
  • 柱状图展示球员、距离、压力、时间等维度的成功率
  • 水平条形图展示最佳传球组合

报告生成

  • 自动生成详细的文本分析报告
  • 包含所有统计分析结果
  • 便于存档和教练员参考

输出示例

总体统计:
  total_passes: 300
  successful_passes: 258
  success_rate: 86.0

这个案例可以帮助教练员和球员了解短传配合的效率,找出需要改进的环节,制定更有针对性的训练计划。

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