本文目录导读:

我来设计一个足球比赛中统计界外球进攻威胁次数的Python案例。
完整案例:界外球进攻威胁统计系统
import pandas as pd
import numpy as np
from datetime import datetime
import json
class ThrowInThreatAnalyzer:
"""界外球进攻威胁分析器"""
def __init__(self):
# 威胁等级定义
self.threat_levels = {
'极低': 1,
'低': 2,
'中等': 3,
'高': 4,
'极高': 5
}
# 记录所有事件
self.events = []
def add_throw_in_event(self,
team_name,
player_name,
throw_in_position,
receiver_position,
is_long_throw,
is_direct_into_box,
outcome,
minute):
"""
添加一次界外球事件记录
参数:
- team_name: 球队名称
- player_name: 掷球员姓名
- throw_in_position: 掷球位置 (x, y坐标)
- receiver_position: 接球位置 (x, y坐标)
- is_long_throw: 是否为长距离界外球
- is_direct_into_box: 是否直接掷入禁区
- outcome: 结果 ('成功接球', '争抢', '直接射门', '解围', '出界', '犯规')
- minute: 比赛分钟
"""
event = {
'team': team_name,
'player': player_name,
'throw_in_position': throw_in_position,
'receiver_position': receiver_position,
'is_long_throw': is_long_throw,
'is_direct_into_box': is_direct_into_box,
'outcome': outcome,
'minute': minute,
'timestamp': datetime.now()
}
# 计算威胁分数
event['threat_score'] = self._calculate_threat_score(event)
self.events.append(event)
return event
def _calculate_distance_to_goal(self, position, goal_position=(105, 37.5)):
"""计算到球门的距离"""
return np.sqrt((position[0] - goal_position[0])**2 +
(position[1] - goal_position[1])**2)
def _calculate_threat_score(self, event):
"""
计算威胁分数 (1-10分)
考虑因素:
- 掷球位置距离球门的距离
- 接球位置离球门的距离
- 是否为长距离界外球
- 是否直接掷入禁区
- 结果类型
"""
score = 0
# 1. 掷球位置因素 (占总分30%)
throw_in_distance = self._calculate_distance_to_goal(event['throw_in_position'])
if throw_in_distance < 20:
score += 3 # 距离球门很近
elif throw_in_distance < 30:
score += 2 # 靠近禁区
elif throw_in_distance < 40:
score += 1 # 中场附近
# 超过40米不加分
# 2. 接球位置因素 (占总分30%)
receiver_distance = self._calculate_distance_to_goal(event['receiver_position'])
if receiver_distance < 15:
score += 3 # 直接在禁区/小禁区
elif receiver_distance < 25:
score += 2 # 禁区附近
elif receiver_distance < 35:
score += 1 # 大禁区外
# 3. 战术因素 (占总分20%)
if event['is_long_throw']:
score += 1
if event['is_direct_into_box']:
score += 1
# 4. 事件结果因素 (占总分20%)
outcome_scores = {
'直接射门': 2,
'成功接球': 1.5,
'争抢': 1,
'解围': 0.5,
'出界': 0,
'犯规': 0
}
score += outcome_scores.get(event['outcome'], 0)
# 标准化到1-10分
score = min(max(score, 1), 10)
return round(score, 1)
def get_team_threat_summary(self, team_name=None):
"""获取球队威胁统计"""
if team_name:
team_events = [e for e in self.events if e['team'] == team_name]
else:
team_events = self.events
if not team_events:
return {}
summary = {
'total_throw_ins': len(team_events),
'average_threat_score': np.mean([e['threat_score'] for e in team_events]),
'high_threat_count': len([e for e in team_events if e['threat_score'] >= 7]),
'medium_threat_count': len([e for e in team_events if 4 <= e['threat_score'] < 7]),
'low_threat_count': len([e for e in team_events if e['threat_score'] < 4]),
'long_throw_count': len([e for e in team_events if e['is_long_throw']]),
'into_box_count': len([e for e in team_events if e['is_direct_into_box']]),
'dangerous_zone_minutes': [e['minute'] for e in team_events if e['threat_score'] >= 8]
}
return summary
def get_threat_trend_by_minute(self, interval=15):
"""按时间段统计威胁趋势"""
trend = {}
for event in self.events:
period = f"{((event['minute']-1)//interval)*interval + 1}-{((event['minute']-1)//interval)*interval + interval}分钟"
if period not in trend:
trend[period] = {'count': 0, 'total_threat': 0}
trend[period]['count'] += 1
trend[period]['total_threat'] += event['threat_score']
# 计算平均威胁
for period in trend:
trend[period]['average_threat'] = trend[period]['total_threat'] / trend[period]['count']
return trend
def get_player_ranking(self):
"""球员威胁排名"""
player_stats = {}
for event in self.events:
player = event['player']
if player not in player_stats:
player_stats[player] = {
'throw_ins': 0,
'total_threat': 0,
'max_threat': 0,
'high_threat_throws': 0
}
player_stats[player]['throw_ins'] += 1
player_stats[player]['total_threat'] += event['threat_score']
player_stats[player]['max_threat'] = max(player_stats[player]['max_threat'],
event['threat_score'])
if event['threat_score'] >= 7:
player_stats[player]['high_threat_throws'] += 1
# 计算平均威胁并排序
for player in player_stats:
player_stats[player]['average_threat'] = (
player_stats[player]['total_threat'] / player_stats[player]['throw_ins']
)
ranking = sorted(player_stats.items(),
key=lambda x: (x[1]['average_threat'], x[1]['high_threat_throws']),
reverse=True)
return ranking
def identify_dangerous_patterns(self):
"""识别危险模式"""
patterns = []
# 模式1: 连续高威胁界外球
for i in range(len(self.events) - 2):
consecutive = self.events[i:i+3]
if all(e['threat_score'] >= 7 for e in consecutive):
patterns.append({
'type': '连续高威胁界外球',
'team': consecutive[0]['team'],
'minutes': [e['minute'] for e in consecutive],
'total_threat': sum(e['threat_score'] for e in consecutive)
})
# 模式2: 比赛末段界外球比例
late_events = [e for e in self.events if e['minute'] > 75]
if late_events and len(late_events) > len(self.events) * 0.3:
patterns.append({
'type': '比赛末段界外球比例过高',
'late_events_count': len(late_events),
'percentage': len(late_events) / len(self.events) * 100
})
# 模式3: 同一区域多次掷球
from collections import Counter
positions = Counter((round(e['throw_in_position'][0], 1),
round(e['throw_in_position'][1], 1))
for e in self.events)
hot_zones = {pos: count for pos, count in positions.items() if count >= 3}
if hot_zones:
patterns.append({
'type': '热点区域',
'hot_zones': hot_zones
})
return patterns
def generate_report(self):
"""生成完整分析报告"""
report = {
'总界外球次数': len(self.events),
'各队威胁统计': {},
'总体威胁分布': {},
'最危险球员': None,
'危险模式': self.identify_dangerous_patterns()
}
# 球队统计
for team in set(e['team'] for e in self.events):
report['各队威胁统计'][team] = self.get_team_threat_summary(team)
# 威胁分数分布
threat_scores = [e['threat_score'] for e in self.events]
report['总体威胁分布'] = {
'平均威胁': np.mean(threat_scores),
'最高威胁': max(threat_scores),
'最低威胁': min(threat_scores),
'高威胁次数': len([s for s in threat_scores if s >= 7]),
'中等威胁次数': len([s for s in threat_scores if 4 <= s < 7]),
'低威胁次数': len([s for s in threat_scores if s < 4])
}
# 最危险球员
ranking = self.get_player_ranking()
if ranking:
report['最危险球员'] = ranking[0][0]
return report
# 使用示例
def main():
# 初始化分析器
analyzer = ThrowInThreatAnalyzer()
# 模拟一场比赛数据
sample_events = [
# (球队, 球员, 掷球位置, 接球位置, 长掷, 掷入禁区, 结果, 分钟)
("曼联", "卢克·肖", (38, 35), (50, 30), False, False, "成功接球", 5),
("曼联", "卢克·肖", (25, 32), (42, 38), False, True, "争抢", 12),
("利物浦", "罗伯逊", (30, 40), (48, 35), True, True, "直接射门", 15),
("曼联", "马拉西亚", (35, 36), (52, 32), True, False, "成功接球", 20),
("利物浦", "罗伯逊", (20, 38), (35, 42), True, True, "争抢", 25),
("曼联", "卢克·肖", (32, 33), (46, 28), False, True, "解围", 32),
("利物浦", "阿诺德", (15, 35), (28, 40), False, False, "成功接球", 45),
("曼联", "马拉西亚", (28, 30), (44, 36), True, True, "直接射门", 60),
("利物浦", "罗伯逊", (36, 42), (50, 38), False, False, "成功接球", 68),
("利物浦", "罗伯逊", (31, 35), (45, 33), True, True, "争抢", 72),
("曼联", "卢克·肖", (26, 34), (40, 30), False, True, "直接射门", 78),
("利物浦", "阿诺德", (40, 37), (52, 32), False, False, "出界", 82),
("曼联", "马拉西亚", (24, 31), (38, 35), True, True, "争抢", 85),
("利物浦", "罗伯逊", (18, 33), (32, 38), True, True, "直接射门", 88),
("曼联", "卢克·肖", (30, 36), (43, 34), False, True, "成功接球", 90)
]
for event_data in sample_events:
analyzer.add_throw_in_event(
team_name=event_data[0],
player_name=event_data[1],
throw_in_position=event_data[2],
receiver_position=event_data[3],
is_long_throw=event_data[4],
is_direct_into_box=event_data[5],
outcome=event_data[6],
minute=event_data[7]
)
# 生成分析报告
report = analyzer.generate_report()
print("=" * 60)
print("界外球进攻威胁分析报告")
print("=" * 60)
print(f"\n1. 总览")
print(f" - 总界外球次数: {report['总界外球次数']}")
print(f" - 平均威胁分数: {report['总体威胁分布']['平均威胁']:.2f}")
print(f" - 最高威胁: {report['总体威胁分布']['最高威胁']}")
print(f"\n2. 各队威胁统计")
for team, stats in report['各队威胁统计'].items():
print(f" {team}:")
print(f" - 界外球次数: {stats['total_throw_ins']}")
print(f" - 平均威胁: {stats['average_threat_score']:.2f}")
print(f" - 高威胁次数 ({stats['high_threat_count']}次)")
print(f" - 长掷球次数: {stats['long_throw_count']}")
print(f" - 掷入禁区次数: {stats['into_box_count']}")
if stats['dangerous_zone_minutes']:
print(f" - 危险时段: {stats['dangerous_zone_minutes']}")
print(f"\n3. 最危险球员: {report['最危险球员']}")
print(f"\n4. 球员威胁排名")
ranking = analyzer.get_player_ranking()
for i, (player, stats) in enumerate(ranking[:5], 1):
print(f" {i}. {player}: 平均威胁 {stats['average_threat_score']:.2f}, "
f"高威胁次数 {stats['high_threat_throws']}")
print(f"\n5. 危险模式识别")
for pattern in report['危险模式']:
print(f" - {pattern['type']}: {pattern}")
print(f"\n6. 威胁时间段分布")
trend = analyzer.get_threat_trend_by_minute()
for period, stats in trend.items():
print(f" {period}: {stats['count']}次, 平均威胁 {stats['average_threat']:.2f}")
# 输出JSON格式总结
print("\n" + "=" * 60)
print("关键指标摘要")
summary = {
'总进攻威胁': sum(e['threat_score'] for e in analyzer.events),
'球队威胁对比': {
team: stats['average_threat_score']
for team, stats in report['各队威胁统计'].items()
},
'进攻效率': report['总体威胁分布']['高威胁次数'] / report['总界外球次数']
}
print(json.dumps(summary, indent=2, ensure_ascii=False))
if __name__ == "__main__":
main()
可视化分析(可选)
import matplotlib.pyplot as plt
import seaborn as sns
def visualize_threat_analysis(analyzer):
"""可视化威胁分析结果"""
# 1. 威胁分数时间线
plt.figure(figsize=(12, 6))
minutes = [e['minute'] for e in analyzer.events]
scores = [e['threat_score'] for e in analyzer.events]
plt.subplot(2, 2, 1)
plt.plot(minutes, scores, 'o-')
plt.xlabel('比赛分钟')
plt.ylabel('威胁分数')
plt.title('界外球威胁时间线')
plt.grid(True, alpha=0.3)
# 2. 球队对比
teams = set(e['team'] for e in analyzer.events)
team_scores = {team: [] for team in teams}
for event in analyzer.events:
team_scores[event['team']].append(event['threat_score'])
plt.subplot(2, 2, 2)
data = [team_scores[team] for team in teams]
plt.boxplot(data, labels=list(teams))
plt.ylabel('威胁分数')
plt.title('球队威胁分数分布')
# 3. 时间段热力图
trend = analyzer.get_threat_trend_by_minute(10)
periods = list(trend.keys())
avg_threats = [trend[p]['average_threat'] for p in periods]
plt.subplot(2, 2, 3)
plt.bar(periods, avg_threats, color='skyblue')
plt.xlabel('时间段')
plt.ylabel('平均威胁')
plt.title('不同时间段平均威胁')
plt.xticks(rotation=45)
# 4. 位置热力图
plt.subplot(2, 2, 4)
positions = [(e['throw_in_position'][0], e['throw_in_position'][1])
for e in analyzer.events]
x = [p[0] for p in positions]
y = [p[1] for p in positions]
scores = [e['threat_score'] for e in analyzer.events]
scatter = plt.scatter(x, y, c=scores, cmap='RdYlGn', s=100, alpha=0.6)
plt.colorbar(scatter, label='威胁分数')
plt.xlabel('场地横向位置')
plt.ylabel('场地纵向位置')
plt.title('掷球位置与威胁关系')
plt.tight_layout()
plt.show()
# 使用可视化
# visualize_threat_analysis(analyzer)
这个系统包含以下核心功能:
- 事件记录:完整记录每次界外球的详细信息
- 威胁评分:基于位置、战术和结果自动计算威胁分数
- 多维统计:按球队、球员、时间段进行统计分析
- 模式识别:自动识别危险进攻模式
- 报告生成:生成完整的分析报告
这个系统可以帮助教练和分析师:
- 评估球队界外球进攻效率
- 识别关键球员的威胁能力
- 发现比赛中的进攻模式
- 制定针对性的战术方案
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播