我来为您设计一个综合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()
运行结果示例
运行程序后会生成:
- 球员综合排名表 - 展示所有球员的各项指标
- 高速跑动距离对比图 - 柱状图+饼图+散点图+排名图
- 多维性能雷达图 - 对比前4名球员的综合表现
- 位置对比分析图 - 不同位置球员的特点
- 相关性热力图 - 展示各项指标之间的关系
- 文字分析洞察 - 关键发现和结论
代码特点
- 模块化设计:数据分析、可视化、统计分离
- 完整的数据流:从数据生成到可视化展示
- 多维度分析:球员个体、位置对比、指标相关性
- 直观可视化:5种以上图表展示不同视角
- 实用的分析洞察:自动输出关键发现
这个案例涵盖了Python数据分析的完整流程,包括数据处理、统计分析、可视化呈现等多个方面,适合作为综合实践项目。