python案例统计禁区内射门次数对比?

wen python案例 2

本文目录导读:

python案例统计禁区内射门次数对比?

  1. 功能特点:
  2. 可自定义:

我来为您创建一个足球比赛禁区内外射门统计的Python案例。

import matplotlib.pyplot as plt
import matplotlib.patches as patches
import numpy as np
from matplotlib.font_manager import FontProperties
# 设置中文字体
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
class FootballShotAnalyzer:
    def __init__(self):
        # 球场尺寸(单位:米)
        self.field_length = 105
        self.field_width = 68
        # 禁区尺寸(标准禁区)
        self.penalty_area_length = 16.5
        self.penalty_area_width = 40.32
        # 球门尺寸
        self.goal_width = 7.32
    def generate_sample_data(self):
        """生成示例射门数据"""
        # 格式:球队A和球队B的射门数据
        # 坐标基于进攻方向(假设进攻方向为从左到右)
        team_a_shots = [
            # (x坐标, y坐标, 射门结果, 球员)
            (85, 30, 'goal', '前锋1'),
            (88, 35, 'goal', '前锋2'),
            (78, 25, 'save', '中场1'),
            (92, 40, 'wide', '前锋1'),
            (83, 20, 'block', '中场2'),
            (95, 32, 'goal', '前锋2'),
            (80, 38, 'save', '前锋1'),
            (75, 28, 'wide', '中场3'),
            (90, 33, 'block', '前锋3'),
            (87, 37, 'save', '中场1'),
        ]
        team_b_shots = [
            (82, 32, 'goal', '前锋4'),
            (79, 29, 'save', '前锋5'),
            (91, 36, 'save', '中场4'),
            (86, 34, 'wide', '前锋4'),
            (93, 31, 'block', '前锋5'),
            (77, 27, 'goal', '前锋6'),
            (89, 39, 'save', '中场5'),
            (84, 30, 'goal', '前锋4'),
            (96, 33, 'wide', '前锋6'),
            (81, 35, 'block', '中场4'),
        ]
        return {
            'team_a': {'shots': team_a_shots, 'name': '主队'},
            'team_b': {'shots': team_b_shots, 'name': '客队'}
        }
    def is_in_penalty_area(self, x, y):
        """判断射门位置是否在禁区内"""
        # 判断坐标是否在禁区内(基于进攻方向)
        if x >= 105 - self.penalty_area_length:  # 在禁区内
            if abs(y - self.field_width/2) <= self.penalty_area_width/2:
                return True
        return False
    def analyze_shots(self, data):
        """分析射门数据"""
        analysis = {}
        for team_key, team_data in data.items():
            team_shots = team_data['shots']
            team_name = team_data['name']
            # 统计限定在对方半场(x > 50)
            filter_shots = [shot for shot in team_shots if shot[0] > 50]
            in_area = []
            out_area = []
            for shot in filter_shots:
                x, y, result, player = shot
                if self.is_in_penalty_area(x, y):
                    in_area.append(shot)
                else:
                    out_area.append(shot)
            analysis[team_key] = {
                'team_name': team_name,
                'in_area': in_area,
                'out_area': out_area,
                'in_area_count': len(in_area),
                'out_area_count': len(out_area),
                'in_area_goals': sum(1 for s in in_area if s[2] == 'goal'),
                'out_area_goals': sum(1 for s in out_area if s[2] == 'goal')
            }
        return analysis
    def plot_comparison(self, analysis):
        """绘制禁区内外射门对比图"""
        fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(2, 2, figsize=(14, 10))
        teams = list(analysis.keys())
        teams_name = [analysis[team]['team_name'] for team in teams]
        in_counts = [analysis[team]['in_area_count'] for team in teams]
        out_counts = [analysis[team]['out_area_count'] for team in teams]
        # 1. 射门次数对比柱状图
        x = np.arange(len(teams))
        width = 0.35
        bars1 = ax1.bar(x - width/2, in_counts, width, label='禁区内', color='#2196F3')
        bars2 = ax1.bar(x + width/2, out_counts, width, label='禁区外', color='#FFC107')
        ax1.set_xlabel('球队')
        ax1.set_ylabel('射门次数')
        ax1.set_title('禁区内外射门次数对比')
        ax1.set_xticks(x)
        ax1.set_xticklabels(teams_name)
        ax1.legend()
        # 在柱状图上添加数值
        for bar in bars1:
            height = bar.get_height()
            ax1.text(bar.get_x() + bar.get_width()/2., height,
                    f'{int(height)}', ha='center', va='bottom')
        for bar in bars2:
            height = bar.get_height()
            ax1.text(bar.get_x() + bar.get_width()/2., height,
                    f'{int(height)}', ha='center', va='bottom')
        # 2. 饼图对比
        ax2.pie([in_counts[0], out_counts[0]], 
                labels=['禁区内', '禁区外'], 
                autopct='%1.1f%%',
                colors=['#2196F3', '#FFC107'])
        ax2.set_title(f'{teams_name[0]}射门分布')
        ax4.pie([in_counts[1], out_counts[1]], 
                labels=['禁区内', '禁区外'], 
                autopct='%1.1f%%',
                colors=['#4CAF50', '#FF5722'])
        ax4.set_title(f'{teams_name[1]}射门分布')
        # 3. 球场示意图
        self.plot_field(ax3, analysis)
        plt.tight_layout()
        return fig
    def plot_field(self, ax, analysis):
        """绘制球场示意图"""
        # 绘制球场
        ax.set_xlim(0, self.field_length)
        ax.set_ylim(0, self.field_width)
        ax.set_aspect('equal')
        ax.set_title('射门位置分布图')
        # 绘制球场边界
        ax.add_patch(patches.Rectangle((0, 0), self.field_length, self.field_width, 
                                       fill=False, edgecolor='green', linewidth=2))
        # 绘制中线
        ax.axvline(x=self.field_length/2, color='green', linewidth=1)
        # 绘制禁区(右上角,进攻方向)
        penalty_start = self.field_length - self.penalty_area_length
        penalty_y_start = (self.field_width - self.penalty_area_width)/2
        ax.add_patch(patches.Rectangle((penalty_start, penalty_y_start), 
                                      self.penalty_area_length, self.penalty_area_width,
                                      fill=False, edgecolor='green', linewidth=1.5))
        # 绘制球门
        goal_y_start = (self.field_width - self.goal_width)/2
        ax.plot([self.field_length, self.field_length], 
                [goal_y_start, goal_y_start + self.goal_width], 
                color='red', linewidth=3)
        # 绘制各球员射门位置
        colors_map = {
            'team_a': '#2196F3',
            'team_b': '#4CAF50'
        }
        markers_map = {
            'goal': 'o',
            'save': 's',
            'wide': '^',
            'block': 'D'
        }
        for team_key, team_data in analysis.items():
            color = colors_map[team_key]
            # 绘制禁区内射门
            for shot in team_data['in_area']:
                x, y, result, player = shot
                marker = markers_map.get(result, 'o')
                ax.scatter(x, y, c=color, marker=marker, s=100, 
                          edgecolors='black', linewidths=1, alpha=0.7)
            # 绘制禁区外射门
            for shot in team_data['out_area']:
                x, y, result, player = shot
                marker = markers_map.get(result, 'o')
                ax.scatter(x, y, c=color, marker=marker, s=100, 
                          edgecolors='black', linewidths=1, alpha=1.0,
                          facecolors='none')
        # 添加图例
        legend_elements = [
            plt.Line2D([0], [0], marker='o', color='w', label='进球', 
                      markerfacecolor='blue', markersize=10),
            plt.Line2D([0], [0], marker='s', color='w', label='扑出', 
                      markerfacecolor='blue', markersize=10),
            plt.Line2D([0], [0], marker='^', color='w', label='射偏', 
                      markerfacecolor='blue', markersize=10),
            plt.Line2D([0], [0], marker='D', color='w', label='被封堵', 
                      markerfacecolor='blue', markersize=10)
        ]
        ax.legend(handles=legend_elements, loc='upper left')
        # 添加禁区标注
        ax.text(penalty_start + 5, self.field_width/2 + 25, '禁区', 
                color='green', fontsize=10)
    def print_summary(self, analysis):
        """打印分析摘要"""
        print("="*60)
        print("射门统计报告")
        print("="*60)
        for team_key, data in analysis.items():
            print(f"\n{data['team_name']}统计:")
            print(f"  总射门次数: {data['in_area_count'] + data['out_area_count']}")
            print(f"  禁区内射门: {data['in_area_count']} 次")
            print(f"  禁区外射门: {data['out_area_count']} 次")
            print(f"  禁区内进球: {data['in_area_goals']} 个")
            print(f"  禁区外进球: {data['out_area_goals']} 个")
            if data['in_area_count'] > 0:
                in_rate = data['in_area_goals'] / data['in_area_count'] * 100
                print(f"  禁区内进球转化率: {in_rate:.1f}%")
            if data['out_area_count'] > 0:
                out_rate = data['out_area_goals'] / data['out_area_count'] * 100
                print(f"  禁区外进球转化率: {out_rate:.1f}%")
            print("  " + "-"*40)
            print(f"  禁区内射门结果分布:")
            self.print_result_distribution(data['in_area'])
            print(f"  禁区外射门结果分布:")
            self.print_result_distribution(data['out_area'])
    def print_result_distribution(self, shots):
        """打印射门结果分布"""
        results = {'goal': 0, 'save': 0, 'wide': 0, 'block': 0}
        result_names = {'goal': '进球', 'save': '被扑出', 'wide': '射偏', 'block': '被封堵'}
        for shot in shots:
            results[shot[2]] += 1
        for result, count in results.items():
            if count > 0:
                print(f"    {result_names[result]}: {count} 次")
# 主程序
def main():
    analyzer = FootballShotAnalyzer()
    # 生成数据(实际使用时可以替换为自己的数据)
    data = analyzer.generate_sample_data()
    # 分析数据
    analysis = analyzer.analyze_shots(data)
    # 打印统计摘要
    analyzer.print_summary(analysis)
    # 绘制对比图表
    fig = analyzer.plot_comparison(analysis)
    plt.show()
    # 额外分析:可视化对比数据表格
    print("\n" + "="*60)
    print("数据可视化对比表")
    print("="*60)
    print(f"{'指标':<20} {'主队':<15} {'客队':<15} {'差值':<10}")
    print("-"*60)
    team_a = analysis['team_a']
    team_b = analysis['team_b']
    metrics = [
        ('总射门次数', team_a['in_area_count'] + team_a['out_area_count'], 
         team_b['in_area_count'] + team_b['out_area_count']),
        ('禁区内射门', team_a['in_area_count'], team_b['in_area_count']),
        ('禁区外射门', team_a['out_area_count'], team_b['out_area_count']),
        ('禁区内进球', team_a['in_area_goals'], team_b['in_area_goals']),
        ('禁区外进球', team_a['out_area_goals'], team_b['out_area_goals'])
    ]
    for name, a_val, b_val in metrics:
        diff = a_val - b_val
        diff_str = f"{diff:+d}" if diff != 0 else "0"
        print(f"{name:<20} {a_val:<15} {b_val:<15} {diff_str:<10}")
if __name__ == "__main__":
    main()

这个案例的主要功能:

功能特点:

  1. 数据模拟:生成两队的射门数据,包括位置坐标、射门结果和球员信息
  2. 区域判定:自动判断射门位置是否在禁区内
  3. 统计分析:计算禁区内外射门次数、进球率等指标
  • 统计报告:打印详细的射门统计信息
  • 可视化图表
    • 柱状图对比两队禁区内外射门次数
    • 饼图显示每队的射门分布
    • 球场示意图标注射门位置

可自定义:

您可以修改generate_sample_data()方法中的team_a_shotsteam_b_shots列表来输入实际比赛数据,坐标格式为(x, y, result, player),其中x、y是球场坐标,result是射门结果(goal/save/wide/block),player是球员名。

运行程序后,您会看到详细的统计分析结果和直观的可视化图表,帮助您快速了解比赛中禁区内外射门的情况对比。

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