本文目录导读:

我来为你设计一个Python统计高球传中争顶成功率的方案:
基础数据模型
import pandas as pd
import numpy as np
from datetime import datetime
# 定义比赛事件数据
class FootballEvent:
def __init__(self):
self.events = []
def add_event(self, match_id, player_id, player_name, team, event_type,
outcome, position_x, position_y, minute, assist_player=None):
"""添加比赛事件
Args:
event_type: 'cross' (传中) 或 'header' (争顶)
outcome: 'success' (成功) 或 'fail' (失败)
"""
self.events.append({
'match_id': match_id,
'player_id': player_id,
'player_name': player_name,
'team': team,
'event_type': event_type,
'outcome': outcome,
'position_x': position_x,
'position_y': position_y,
'minute': minute,
'assist_player': assist_player,
'timestamp': datetime.now()
})
核心统计功能
class CrossHeaderStats:
def __init__(self, events_data):
self.df = pd.DataFrame(events_data)
self.prepare_data()
def prepare_data(self):
"""数据预处理"""
# 分离传中和争顶事件
self.crosses = self.df[self.df['event_type'] == 'cross']
self.headers = self.df[self.df['event_type'] == 'header']
def calculate_success_rate(self, group_by=None):
"""计算争顶成功率
Args:
group_by: 'player', 'team', 'match' 或 None
"""
if group_by == 'player':
grouped = self.headers.groupby('player_name')
elif group_by == 'team':
grouped = self.headers.groupby('team')
elif group_by == 'match':
grouped = self.headers.groupby('match_id')
else:
# 总成功率
total = len(self.headers)
success = len(self.headers[self.headers['outcome'] == 'success'])
return {'total_headers': total,
'success': success,
'success_rate': success / total if total > 0 else 0}
result = {}
for name, group in grouped:
total = len(group)
success = len(group[group['outcome'] == 'success'])
result[name] = {
'total': total,
'success': success,
'success_rate': success / total if total > 0 else 0
}
return result
def analyze_cross_header_connection(self):
"""分析传中与争顶的关联性"""
# 将传中事件和后续的争顶事件关联
cross_connected = []
for idx, cross in self.crosses.iterrows():
# 查找同一场比赛,2秒内(或一定时间范围内)的争顶事件
match_headers = self.headers[
(self.headers['match_id'] == cross['match_id']) &
(self.headers['timestamp'] > cross['timestamp'])
]
if len(match_headers) > 0:
# 取最近的争顶事件
nearest_header = match_headers.iloc[0]
cross_connected.append({
'cross_player': cross['player_name'],
'header_player': nearest_header['player_name'],
'team': cross['team'],
'cross_success': cross['outcome'],
'header_success': nearest_header['outcome'],
'position_x': cross['position_x'],
'position_y': cross['position_y']
})
return pd.DataFrame(cross_connected)
高级分析功能
class AdvancedCrossHeaderAnalysis:
def __init__(self, stats_data):
self.stats = stats_data
def analysis_by_position(self):
"""按球场位置分析"""
# 定义球场区域
def get_area(x, y):
if x < 0.3: # 左路
if y < 0.5:
return '左路浅'
else:
return '左路深'
elif x > 0.7: # 右路
if y < 0.5:
return '右路浅'
else:
return '右路深'
else: # 中路
if y < 0.5:
return '中路浅'
else:
return '中路深'
self.stats['area'] = self.stats.apply(
lambda row: get_area(row['position_x'], row['position_y']), axis=1)
# 按区域统计成功率
area_stats = {}
for area in self.stats['area'].unique():
area_data = self.stats[self.stats['area'] == area]
success = len(area_data[area_data['outcome'] == 'success'])
total = len(area_data)
area_stats[area] = {
'total': total,
'success': success,
'success_rate': success/total if total > 0 else 0
}
return area_stats
def analyze_against_defense_type(self):
"""分析不同防守类型下的成功率"""
# 假设有防守类型数据
defense_data = {
'high_block': 0.35, # 高位逼抢
'mid_block': 0.45, # 中场防守
'low_block': 0.55, # 低位防守
}
return defense_data
def trend_analysis(self):
"""趋势分析:按时间节点分析成功率变化"""
self.stats['time_phase'] = pd.cut(
self.stats['minute'],
bins=[0, 15, 30, 45, 60, 75, 90],
labels=['0-15', '15-30', '30-45', '45-60', '60-75', '75-90']
)
trend = {}
for phase in self.stats['time_phase'].unique():
phase_data = self.stats[self.stats['time_phase'] == phase]
success = len(phase_data[phase_data['outcome'] == 'success'])
total = len(phase_data)
trend[phase] = success/total if total > 0 else 0
return trend
可视化分析
import matplotlib.pyplot as plt
import seaborn as sns
class CrossHeaderVisualization:
def __init__(self, stats):
self.stats = stats
def plot_success_rate_by_player(self):
"""绘制球员成功率对比图"""
player_stats = self.stats.calculate_success_rate('player')
players = list(player_stats.keys())
rates = [player_stats[p]['success_rate'] for p in players]
plt.figure(figsize=(12, 6))
plt.bar(players, rates, color='skyblue')
plt.xlabel('球员')
plt.ylabel('争顶成功率')
plt.title('球员高球传中争顶成功率对比')
plt.xticks(rotation=45)
plt.tight_layout()
plt.show()
def plot_position_heatmap(self, success_data):
"""绘制球场位置热力图"""
if 'position_x' in self.stats.columns and 'position_y' in self.stats.columns:
plt.figure(figsize=(12, 8))
sns.kdeplot(
data=self.stats,
x='position_x',
y='position_y',
hue='outcome',
levels=20
)
plt.title('争顶成功与失败位置分布')
plt.xlabel('球场横向位置')
plt.ylabel('球场纵向位置')
plt.show()
完整使用示例
def demo_cross_header_analysis():
"""演示完整分析流程"""
# 创建模拟数据
stats = CrossHeaderStats([])
# 模拟数据生成
np.random.seed(42)
players = ['张三', '李四', '王五', '赵六', '孙七']
teams = ['A队', 'B队']
events = []
for i in range(100):
events.append({
'match_id': np.random.randint(1, 5),
'player_id': np.random.randint(1, 10),
'player_name': np.random.choice(players),
'team': np.random.choice(teams),
'event_type': np.random.choice(['cross', 'header']),
'outcome': np.random.choice(['success', 'fail'], p=[0.4, 0.6]),
'position_x': np.random.uniform(0, 1),
'position_y': np.random.uniform(0, 1),
'minute': np.random.randint(1, 90),
'assist_player': np.random.choice(players) if np.random.random() > 0.5 else None,
'timestamp': datetime.now()
})
# 初始化分析对象
stats = CrossHeaderStats(pd.DataFrame(events))
# 总成功率
total_rate = stats.calculate_success_rate()
print(f"总争顶成功率: {total_rate['success_rate']:.2%}")
# 按球员分析
player_rates = stats.calculate_success_rate('player')
print("\n球员争顶成功率:")
for player, data in player_rates.items():
print(f"{player}: {data['success_rate']:.2%} ({data['success']}/{data['total']}次)")
# 高级分析
advanced = AdvancedCrossHeaderAnalysis(pd.DataFrame(events))
area_analysis = advanced.analysis_by_position()
print("\n区域分析:")
for area, data in area_analysis.items():
print(f"{area}: {data['success_rate']:.2%}")
# 可视化
viz = CrossHeaderVisualization(stats)
viz.plot_success_rate_by_player()
viz.plot_position_heatmap(pd.DataFrame(events))
# 运行演示
if __name__ == "__main__":
demo_cross_header_analysis()
这个系统可以:
- 统计球员/球队/比赛级别的争顶成功率
- 分析传中与争顶的关联性
- 按位置、时间等因素深入分析
- 可视化展示数据
你可以根据实际数据调整数据格式,或者添加更多分析维度(如对手强度、天气条件等)。