本文目录导读:

我来为您设计一个足球数据分析中统计高球传中争顶成功率的Python案例。
完整代码实现
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from datetime import datetime
# 设置中文显示
plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号
class AerialDuelsAnalyzer:
"""分析高球传中争顶成功率的类"""
def __init__(self):
self.data = None
self.duel_stats = None
def generate_sample_data(self, n_matches=10, n_players=22):
"""
生成模拟比赛数据
参数:
n_matches: 比赛场次
n_players: 球员数量
"""
np.random.seed(42)
players = []
teams = ['曼联', '曼城', '利物浦', '阿森纳', '切尔西']
for i in range(n_players):
players.append({
'player_id': f'P{i+1:03d}',
'name': f'球员{i+1}',
'team': np.random.choice(teams),
'position': np.random.choice(['前锋', '中场', '后卫', '门将']),
'height': np.random.normal(180, 5), # 身高
'jump_reach': np.random.normal(250, 8) # 弹跳能力
})
# 生成争顶数据
duel_records = []
for match in range(n_matches):
match_date = datetime(2024, 1, 1) + pd.Timedelta(days=match*7)
for player in players:
# 每场比赛每个球员的争顶次数 (近似正态分布)
n_duels = max(0, int(np.random.normal(5, 2)))
for duel in range(n_duels):
# 争顶成功概率与身高、弹跳能力相关
success_prob = 0.5 + (player['height'] - 180) * 0.005 + \
(player['jump_reach'] - 250) * 0.002
success_prob = np.clip(success_prob, 0.1, 0.9)
duel_records.append({
'match_id': match + 1,
'date': match_date,
'player_id': player['player_id'],
'name': player['name'],
'team': player['team'],
'position': player['position'],
'height': player['height'],
'jump_reach': player['jump_reach'],
'success': np.random.binomial(1, success_prob)
})
self.data = pd.DataFrame(duel_records)
return self.data
def calculate_success_rate(self):
"""计算整体和球员级别的争顶成功率"""
# 球员级别统计
player_stats = self.data.groupby(['player_id', 'name', 'team', 'position']).agg({
'success': ['count', 'sum', 'mean']
}).reset_index()
player_stats.columns = ['player_id', 'name', 'team', 'position',
'total_duels', 'won_duels', 'success_rate']
player_stats['success_rate'] = player_stats['success_rate'] * 100
# 球队级别统计
team_stats = self.data.groupby('team').agg({
'success': ['count', 'sum', 'mean']
}).reset_index()
team_stats.columns = ['team', 'total_duels', 'won_duels', 'success_rate']
team_stats['success_rate'] = team_stats['success_rate'] * 100
# 位置级别统计
position_stats = self.data.groupby('position').agg({
'success': ['count', 'sum', 'mean']
}).reset_index()
position_stats.columns = ['position', 'total_duels', 'won_duels', 'success_rate']
position_stats['success_rate'] = position_stats['success_rate'] * 100
self.player_stats = player_stats
self.team_stats = team_stats
self.position_stats = position_stats
return player_stats, team_stats, position_stats
def analyze_height_influence(self, bins=5):
"""分析身高对争顶成功率的影响"""
# 添加身高分组
self.data['height_group'] = pd.cut(self.data['height'],
bins=bins,
labels=['矮', '偏矮', '中等', '偏高', '高'])
height_duels = self.data.groupby('height_group').agg({
'success': ['count', 'sum', 'mean']
}).reset_index()
height_duels.columns = ['height_group', 'total_duels', 'won_duels', 'success_rate']
height_duels['success_rate'] = height_duels['success_rate'] * 100
return height_duels
def calculate_win_probability(self, height, jump_reach):
"""计算争顶成功的概率"""
# 基于历史数据的逻辑回归模型
from sklearn.linear_model import LogisticRegression
X = self.data[['height', 'jump_reach']].values
y = self.data['success'].values
model = LogisticRegression()
model.fit(X, y)
# 预测新数据
prob = model.predict_proba([[height, jump_reach]])[0][1]
return prob, model
def visualize_results(self):
"""可视化分析结果"""
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
# 1. 球队争顶成功率对比
ax1 = axes[0, 0]
sns.barplot(x='team', y='success_rate', data=self.team_stats, ax=ax1)
ax1.set_title('各球队争顶成功率对比')
ax1.set_xlabel('球队')
ax1.set_ylabel('成功率 (%)')
ax1.set_ylim(0, 100)
# 2. 位置争顶成功率对比
ax2 = axes[0, 1]
sns.barplot(x='position', y='success_rate', data=self.position_stats, ax=ax2)
ax2.set_title('不同位置球员争顶成功率')
ax2.set_xlabel('位置')
ax2.set_ylabel('成功率 (%)')
ax2.set_ylim(0, 100)
# 3. 身高与成功率的关系
ax3 = axes[1, 0]
height_duels = self.analyze_height_influence()
sns.barplot(x='height_group', y='success_rate', data=height_duels, ax=ax3)
ax3.set_title('身高与争顶成功率的关系')
ax3.set_xlabel('身高分组')
ax3.set_ylabel('成功率 (%)')
# 4. 球员争顶成功率分布
ax4 = axes[1, 1]
sns.histplot(self.player_stats['success_rate'], bins=10, kde=True, ax=ax4)
ax4.set_title('球员争顶成功率分布')
ax4.set_xlabel('成功率 (%)')
ax4.set_ylabel('人数')
plt.tight_layout()
plt.show()
def get_top_performers(self, n=5):
"""获取争顶表现最好的球员"""
top_players = self.player_stats[
(self.player_stats['total_duels'] >= 10) & # 至少10次争顶
(self.player_stats['success_rate'] > 60) # 成功率超过60%
].sort_values('success_rate', ascending=False).head(n)
return top_players
def analyze_match_trend(self):
"""分析争顶成功率随时间的变化趋势"""
# 按比赛日期统计
self.data['date'] = pd.to_datetime(self.data['date'])
match_trend = self.data.groupby('date').agg({
'success': ['count', 'sum', 'mean']
}).reset_index()
match_trend.columns = ['date', 'total_duels', 'won_duels', 'success_rate']
match_trend['success_rate'] = match_trend['success_rate'] * 100
# 绘制趋势图
plt.figure(figsize=(12, 6))
plt.plot(match_trend['date'], match_trend['success_rate'], marker='o')
plt.title('争顶成功率随时间变化趋势')
plt.xlabel('比赛日期')
plt.ylabel('成功率 (%)')
plt.grid(True, alpha=0.3)
plt.xticks(rotation=45)
plt.tight_layout()
plt.show()
return match_trend
# 使用示例
def main():
# 创建分析器实例
analyzer = AerialDuelsAnalyzer()
# 生成模拟数据
print("正在生成模拟数据...")
analyzer.generate_sample_data(n_matches=20, n_players=30)
# 计算统计数据
player_stats, team_stats, position_stats = analyzer.calculate_success_rate()
print("\n" + "="*50)
print("球队争顶成功率统计")
print("="*50)
print(team_stats.to_string(index=False))
print("\n" + "="*50)
print("位置争顶成功率统计")
print("="*50)
print(position_stats.to_string(index=False))
print("\n" + "="*50)
print("表现最佳球员 (争顶成功率 > 60% 且争顶次数 ≥ 10)")
print("="*50)
top_players = analyzer.get_top_performers()
print(top_players.to_string(index=False))
# 预测特定球员的争顶成功率
print("\n" + "="*50)
print("争顶成功率预测")
print("="*50)
height, jump_reach = 185, 262
prob, model = analyzer.calculate_win_probability(height, jump_reach)
print(f"身高 {height}cm, 弹跳 {jump_reach}cm 的球员预测争顶成功率: {prob:.2%}")
# 可视化结果
print("\n正在生成可视化图表...")
analyzer.visualize_results()
# 分析趋势
match_trend = analyzer.analyze_match_trend()
if __name__ == "__main__":
main()
核心功能说明
这个分析系统包含以下主要功能:
- 数据处理:生成模拟足球比赛争顶数据
- 统计分析:计算各维度的争顶成功率
- 影响因素分析:分析身高、位置等因素的影响
- 预测模型:使用机器学习预测争顶成功率
- 可视化展示:生成直观的图表
主要分析方法
| 分析维度 | 方法 | 输出 |
|---|---|---|
| 整体统计 | 描述性统计 | 成功率、争顶次数等 |
| 团队分析 | 分组统计 | 各队成功率对比 |
| 位置分析 | 分组统计 | 不同位置成功率 |
| 身高影响 | 分箱分析 | 身高与成功率关系 |
| 趋势分析 | 时间序列 | 成功率变化趋势 |
使用场景
这个工具可以用于:
- 足球数据分析部门评估球员表现
- 球探系统评估潜在签约球员
- 教练组制定训练计划
- 比赛战术分析
运行代码前需要安装依赖:pip install pandas numpy matplotlib seaborn scikit-learn