综合python案例,高速跑动距离对比?

wen python案例 2

我来为您设计一个综合Python案例,分析足球比赛中不同球员的高速跑动距离对比。

综合python案例,高速跑动距离对比?

项目:足球运动员高速跑动分析系统

数据生成模块

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from datetime import datetime, timedelta
import warnings
warnings.filterwarnings('ignore')
# 设置中文显示
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
class PlayerPerformanceAnalyzer:
    """足球运动员跑动性能分析器"""
    def __init__(self):
        self.players_data = None
        self.speed_threshold = 25  # 高速跑动阈值 (km/h)
        self.sprint_threshold = 30  # 冲刺速度阈值 (km/h)
    def generate_player_data(self, num_players=8, matches_per_player=10):
        """生成模拟球员跑动数据"""
        players = []
        positions = ['前锋', '中场', '后卫', '边锋']
        # 各位置速度特征(平均值,标准差)
        position_speeds = {
            '前锋': (27.5, 2.0),
            '中场': (24.5, 1.8),
            '后卫': (23.0, 1.5),
            '边锋': (28.0, 2.2)
        }
        for player_id in range(num_players):
            position = positions[player_id % len(positions)]
            for match_num in range(matches_per_player):
                # 生成比赛时间戳(90分钟比赛)
                match_duration = 90
                timestamp = np.arange(0, match_duration, 0.1)
                # 根据位置生成基础速度
                base_speed_mean, base_speed_std = position_speeds[position]
                # 模拟跑动速度变化(加入一些随机性和比赛节奏变化)
                speed_noise = np.random.normal(base_speed_mean, base_speed_std, len(timestamp))
                match_rhythm = np.sin(timestamp/10) * 5  # 模拟比赛节奏
                fatigue_factor = np.linspace(1, 0.85, len(timestamp))  # 模拟疲劳
                speeds = np.abs(speed_noise + match_rhythm) * fatigue_factor
                speeds = np.clip(speeds, 4, 38)  # 限制在合理范围
                # 计算距离(km/h * 时间(h))
                distance_per_sample = speeds * (0.1/3600)  # 每个采样点的距离(km)
                # 累加生成球员比赛数据
                player_data = {
                    'player_id': f'Player_{player_id+1:02d}',
                    'player_name': f'球员{player_id+1:02d}',
                    'position': position,
                    'match_id': f'Match_{match_num+1:02d}',
                    'total_distance': np.sum(distance_per_sample),  # 总距离(km)
                    'avg_speed': np.mean(speeds),  # 平均速度(km/h)
                    'max_speed': np.max(speeds),  # 最大速度(km/h)
                    'high_speed_distance': np.sum(distance_per_sample[speeds >= self.speed_threshold]),  # 高速跑动距离
                    'sprint_distance': np.sum(distance_per_sample[speeds >= self.sprint_threshold]),  # 冲刺距离
                    'high_speed_runs': np.sum(speeds >= self.speed_threshold),  # 高速跑动次数
                    'sprint_runs': np.sum(speeds >= self.sprint_threshold),  # 冲刺次数
                    'high_speed_duration': np.sum(speeds >= self.speed_threshold) * 0.1/3600,  # 高速跑动时间(h)
                    'speed_percentiles': np.percentile(speeds, [25, 50, 75, 90])  # 速度分位数
                }
                players.append(player_data)
        self.players_data = pd.DataFrame(players)
        return self.players_data
    def analyze_high_speed_performance(self):
        """分析高速度跑动表现"""
        if self.players_data is None:
            raise ValueError("请先加载或生成数据")
        # 按球员分组汇总
        player_summary = self.players_data.groupby(['player_id', 'player_name', 'position']).agg({
            'high_speed_distance': 'mean',  # 平均每场高速跑动距离
            'sprint_distance': 'mean',
            'high_speed_runs': 'mean',
            'sprint_runs': 'mean',
            'max_speed': 'max',
            'total_distance': 'mean',
            'high_speed_duration': 'mean'
        }).round(2)
        player_summary.columns = ['场均高速跑动(km)', '场均冲刺距离(km)', 
                                 '高速跑动次数', '冲刺次数', 
                                 '最大速度(km/h)', '总跑动距离(km)', 
                                 '高速跑动时间(min)']
        # 添加高速跑动占比
        player_summary['高速跑动占比(%)'] = (player_summary['场均高速跑动(km)'] / 
                                           player_summary['总跑动距离(km)'] * 100).round(2)
        # 计算综合得分
        player_summary['综合得分'] = (player_summary['场均高速跑动(km)'] * 0.4 + 
                                    player_summary['冲刺次数'] * 0.3 +
                                    player_summary['最大速度(km/h)'] * 0.3).round(2)
        return player_summary.sort_values('综合得分', ascending=False)

可视化模块

class PerformanceVisualizer:
    """性能可视化类"""
    @staticmethod
    def plot_high_speed_comparison(data, title="球员高速跑动距离对比"):
        """绘制高速跑动距离对比图"""
        fig, axes = plt.subplots(2, 2, figsize=(16, 12))
        # 1. 高速跑动距离柱状图
        ax1 = axes[0, 0]
        bars = ax1.bar(data.index, data['场均高速跑动(km)'], 
                       color=plt.cm.RdYlGn(np.linspace(0.2, 0.8, len(data))))
        ax1.set_title('场均高速跑动距离对比', fontsize=12, fontweight='bold')
        ax1.set_xlabel('球员')
        ax1.set_ylabel('距离 (km)')
        ax1.set_xticklabels(data.index, rotation=45)
        for bar, val in zip(bars, data['场均高速跑动(km)']):
            ax1.text(bar.get_x() + bar.get_width()/2, bar.get_height() + 0.05, 
                    f'{val:.2f}', ha='center', va='bottom', fontsize=9)
        # 2. 高速跑动占比饼图
        ax2 = axes[0, 1]
        explode = [0.03] * len(data[:5])  # 突出前5名
        ax2.pie(data['高速跑动占比(%)'][:5], 
                labels=data.index[:5], 
                autopct='%1.1f%%',
                explode=explode[:len(data[:5])],
                startangle=90)
        ax2.set_title('前5名球员高速跑动占比', fontsize=12, fontweight='bold')
        # 3. 散点图:总距离 vs 高速跑动距离
        ax3 = axes[1, 0]
        scatter = ax3.scatter(data['总跑动距离(km)'], 
                            data['场均高速跑动(km)'],
                            s=data['综合得分']*10,  # 点大小随得分变化
                            c=range(len(data)), 
                            cmap='viridis',
                            alpha=0.6)
        ax3.set_xlabel('总跑动距离 (km)')
        ax3.set_ylabel('高速跑动距离 (km)')
        ax3.set_title('总距离与高速跑动距离关系', fontsize=12, fontweight='bold')
        ax3.set_zorder(2)
        # 为散点添加球员标签
        for idx, label in enumerate(data.index):
            ax3.annotate(label, 
                        (data['总跑动距离(km)'].iloc[idx], 
                         data['场均高速跑动(km)'].iloc[idx]),
                        textcoords="offset points", 
                        xytext=(5,5), 
                        fontsize=8)
        # 4. 综合得分排名条形图
        ax4 = axes[1, 1]
        colors = plt.cm.hot_r(np.linspace(0.2, 1, len(data)))
        bars = ax4.barh(data.index, data['综合得分'], color=colors)
        ax4.set_xlabel('综合得分')
        ax4.set_title('综合得分排名', fontsize=12, fontweight='bold')
        ax4.invert_yaxis()
        # 在条形上添加数值
        for bar, val in zip(bars, data['综合得分']):
            ax4.text(bar.get_width() + 0.5, bar.get_y() + bar.get_height()/2, 
                    f'{val:.1f}', va='center', fontsize=9)
        plt.suptitle(title, fontsize=16, fontweight='bold')
        plt.tight_layout()
        plt.show()
    @staticmethod
    def plot_radar_comparison(data, top_n=4, players=None):
        """雷达图对比多个球员的多维度表现"""
        if players is None:
            players = data.index[:top_n]
        # 选择雷达图指标
        metrics = ['场均高速跑动(km)', '高速跑动次数', '冲刺次数', 
                   '最大速度(km/h)', '高速跑动占比(%)', '综合得分']
        # 数据归一化
        data_selected = data.loc[players, metrics]
        data_normalized = (data_selected - data_selected.min()) / (data_selected.max() - data_selected.min())
        # 设定雷达图角度
        angles = np.linspace(0, 2 * np.pi, len(metrics), endpoint=False).tolist()
        angles += angles[:1]  # 使图形闭合
        fig, ax = plt.subplots(figsize=(10, 10), subplot_kw=dict(polar=True))
        colors = ['#e74c3c', '#3498db', '#2ecc71', '#f39c12']
        for idx, player in enumerate(players):
            values = data_normalized.loc[player].values.tolist()
            values += values[:1]
            ax.plot(angles, values, 'o-', linewidth=2, 
                   label=player, color=colors[idx % len(colors)])
            ax.fill(angles, values, alpha=0.15, color=colors[idx % len(colors)])
        ax.set_xticks(angles[:-1])
        ax.set_xticklabels(metrics)
        ax.set_ylim(0, 1)
        ax.set_title('球员多维性能对比雷达图', fontsize=15, fontweight='bold', pad=20)
        ax.grid(True)
        ax.legend(loc='upper right', bbox_to_anchor=(1.3, 1.0))
        plt.tight_layout()
        plt.show()
    @staticmethod
    def plot_position_comparison(data):
        """按位置对比分析"""
        # 按位置分组统计
        position_data = data.groupby('position').agg({
            '场均高速跑动(km)': 'mean',
            '冲刺次数': 'mean',
            '最大速度(km/h)': 'mean',
            '总跑动距离(km)': 'mean'
        }).round(2)
        fig, axes = plt.subplots(2, 2, figsize=(14, 10))
        metrics_mapping = {
            '场均高速跑动(km)': ('平均高速跑动距离', 'km'),
            '冲刺次数': ('平均冲刺次数', '次'),
            '最大速度(km/h)': ('平均最大速度', 'km/h'),
            '总跑动距离(km)': ('平均总跑动距离', 'km')
        }
        for idx, (metric, (title, unit)) in enumerate(metrics_mapping.items()):
            ax = axes[idx // 2, idx % 2]
            positions = position_data.index.tolist()
            values = position_data[metric].tolist()
            bars = ax.bar(positions, values, 
                         color=['#e74c3c', '#3498db', '#2ecc71', '#f39c12'],
                         edgecolor='black', linewidth=0.5)
            ax.set_title(title, fontsize=11, fontweight='bold')
            ax.set_ylabel(f'平均值 ({unit})')
            # 添加数值标签
            for bar, val in zip(bars, values):
                ax.text(bar.get_x() + bar.get_width()/2, bar.get_height() + 0.1, 
                       f'{val:.2f}', ha='center', va='bottom', fontsize=9)
        plt.suptitle('不同位置的跑动性能对比', fontsize=14, fontweight='bold')
        plt.tight_layout()
        plt.show()

统计分析模块

class StatisticalAnalyzer:
    """统计分析类"""
    @staticmethod
    def calculate_correlations(data):
        """计算相关性矩阵"""
        numeric_cols = ['场均高速跑动(km)', '冲刺距离(km)', '高速跑动次数', 
                       '冲刺次数', '最大速度(km/h)', '总跑动距离(km)', '综合得分']
        # 重命名列
        data_renamed = data.copy()
        if '场均冲刺距离(km)' in data.columns:
            data_renamed.rename(columns={'场均冲刺距离(km)': '冲刺距离(km)'}, inplace=True)
        corr_data = data_renamed[[col for col in numeric_cols if col in data_renamed.columns]]
        corr_matrix = corr_data.corr()
        return corr_matrix
    @staticmethod
    def pair_plot_analysis(data):
        """成对散点图分析"""
        cols = ['场均高速跑动(km)', '冲刺次数', '最大速度(km/h)', '综合得分']
        # 创建成对关系图
        g = sns.PairGrid(data[cols if set(cols).issubset(data.columns) else 
                             [col for col in cols if col in data.columns]])
        g.map_upper(sns.scatterplot, color='crimson')
        g.map_lower(sns.kdeplot, cmap='Reds')
        g.map_diag(sns.histplot, kde=True, color='darkblue')
        g.fig.suptitle('球员性能指标成对分析', y=1.02, fontsize=14, fontweight='bold')
        plt.tight_layout()
        plt.show()

主程序运行

def main():
    """主程序:运行完整分析"""
    print("="*60)
    print("足球运动员高速跑动性能分析系统".center(50))
    print("="*60)
    # 1. 初始化并生成数据
    analyzer = PlayerPerformanceAnalyzer()
    raw_data = analyzer.generate_player_data(num_players=8, matches_per_player=10)
    print(f"\n生成数据成功!共 {len(raw_data)} 条比赛记录")
    print(f"参与分析的球员数量:{raw_data['player_id'].nunique()}")
    print(f"比赛场次:{len(raw_data)}")
    # 2. 数据分析
    print("\n" + "="*60)
    print("数据分析中...".center(50))
    print("="*60)
    player_summary = analyzer.analyze_high_speed_performance()
    # 3. 数据展示
    print("\n球员综合排名表:")
    print("-"*80)
    print(player_summary[['场均高速跑动(km)', '高速跑动次数', '冲刺次数', 
                          '最大速度(km/h)', '综合得分']].head(10))
    # 4. 可视化
    visualizer = PerformanceVisualizer()
    # 4.1 主对比图
    print("\n生成对比图表...")
    visualizer.plot_high_speed_comparison(player_summary)
    # 4.2 雷达图
    print("生成雷达图...")
    visualizer.plot_radar_comparison(player_summary, top_n=4)
    # 4.3 按位置分析
    print("生成位置对比图...")
    visualizer.plot_position_comparison(player_summary)
    # 5. 统计分析
    print("\n计算相关性矩阵...")
    corr_matrix = StatisticalAnalyzer.calculate_correlations(player_summary)
    plt.figure(figsize=(10, 8))
    sns.heatmap(corr_matrix, annot=True, cmap='coolwarm', center=0,
                fmt='.2f', square=True, linewidths=1)
    plt.title('球员性能指标相关性热力图', fontsize=14, fontweight='bold')
    plt.tight_layout()
    plt.show()
    # 6. 输出关键洞察
    print("\n" + "="*60)
    print("关键分析洞察:".center(50))
    print("="*60)
    # 找出最佳球员
    best_player = player_summary.index[0]
    best_value = player_summary.iloc[0]['综合得分']
    print(f"🏆 综合表现最佳球员:{best_player}")
    print(f"   综合得分:{best_value:.2f}")
    # 找出高速跑动最多的球员
    high_speed_player = player_summary['场均高速跑动(km)'].idxmax()
    high_speed_value = player_summary.loc[high_speed_player, '场均高速跑动(km)']
    print(f"⚡ 场均高速跑动最多:{high_speed_player}")
    print(f"   高速跑动距离:{high_speed_value:.2f} km")
    # 位置对比分析
    position_stats = player_summary.groupby('position').agg({
        '综合得分': 'mean'
    }).round(2)
    print("\n📍 位置表现分析:")
    for position, row in position_stats.iterrows():
        print(f"   {position}: 平均得分 {row['综合得分']:.2f}")
    # 相关性强弱
    if '场均高速跑动(km)' in corr_matrix and '冲刺次数' in corr_matrix:
        corr_val = corr_matrix.loc['场均高速跑动(km)', '冲刺次数']
        print(f"\n📊 高速跑动距离与冲刺次数的相关性:{corr_val:.2f}")
        if abs(corr_val) > 0.7:
            print("   两者高度相关,表明高速跑动多的球员也倾向于有更多冲刺")
    print("\n" + "="*60)
    print("分析完成!".center(50))
    print("="*60)
if __name__ == "__main__":
    main()

运行结果示例

运行程序后会生成:

  1. 球员综合排名表 - 展示所有球员的各项指标
  2. 高速跑动距离对比图 - 柱状图+饼图+散点图+排名图
  3. 多维性能雷达图 - 对比前4名球员的综合表现
  4. 位置对比分析图 - 不同位置球员的特点
  5. 相关性热力图 - 展示各项指标之间的关系
  6. 文字分析洞察 - 关键发现和结论

代码特点

  • 模块化设计:数据分析、可视化、统计分离
  • 完整的数据流:从数据生成到可视化展示
  • 多维度分析:球员个体、位置对比、指标相关性
  • 直观可视化:5种以上图表展示不同视角
  • 实用的分析洞察:自动输出关键发现

这个案例涵盖了Python数据分析的完整流程,包括数据处理、统计分析、可视化呈现等多个方面,适合作为综合实践项目。

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