本文目录导读:

根据你的需求,我为你准备了一个足球战术分析脚本,用于统计“界外球进攻威胁次数”。
⚠️ 重要提示:由于“威胁”是主观定义,我提供了两种统计模式(基础传球模式 & 智能威胁模式),你可以根据视频/图表数据源的详细程度来选择。
- 数据输入:支持从 CSV 文件读取事件数据(时间戳、球员、动作类型、坐标)。
- 统计维度:
- 总界外球次数。
- 形成“有效进攻”的次数(至少完成一次成功传接)。
- 进攻三区(危险区域) 触球次数。
- 最终形成射门 / 绝佳机会(Big Chance)的次数。
- 输出:控制台打印统计报告 + 生成可视化热力图(可选)。
基础版(基于事件标签统计)
适用于:你有包含 Throw-in(界外球)、Pass(传球)、Shot(射门)等标签的 XML/CSV 数据。
import csv
from collections import defaultdict
def analyze_throw_in_threats(file_path):
"""
统计界外球进攻威胁
:param file_path: CSV文件路径,需包含列:event_type, start_x, start_y, end_x, end_y, outcome, team
"""
# 1. 数据加载与筛选
throw_ins = []
passes = []
shots = []
with open(file_path, 'r', encoding='utf-8') as f:
reader = csv.DictReader(f)
for row in reader:
event = row['event_type']
if event == 'Throw-in':
throw_ins.append(row)
elif event == 'Pass' and row['outcome'] == 'Successful':
passes.append(row)
elif event == 'Shot' or event == 'Attempt':
shots.append(row)
# 2. 分析阶段:追踪每次界外球的后续串联
threats = []
for t in throw_ins:
# 找该界外球的球队和对位
team = t['team']
start_loc = (float(t['start_x']), float(t['start_y']))
# 模拟:在接下来的5个事件内寻找该队的有效进攻
threat_chain = {
'total': 1,
'possession_starts': 0,
'danger_area_touches': 0,
'shots_generated': 0
}
# 实际逻辑需根据数据时间顺序关联,这里简化示例
# 找出紧随其后的5个该队事件
# ... (这里需要关联你的数据)
# 危险区域判定:假设对方半场 罚球区(18码) 定义为 X>75
if start_loc[0] > 75:
threat_chain['danger_area_touches'] += 1
threats.append(threat_chain)
# 3. 输出统计报表
total_throws = len(throw_ins)
danger_touches = sum(t['danger_area_touches'] for t in threats)
shot_from_throw = sum(1 for s in shots if s['team'] in [t['team'] for t in throw_ins] and float(s['start_x']) > 75)
print(f"===== 界外球进攻威胁统计 =====")
print(f"总界外球数: {total_throws}")
print(f"形成进攻三区触球: {danger_touches} 次")
print(f"由界外球策动的射门: {shot_from_throw} 次")
print(f"界外球转化射门率: {shot_from_throw/total_throws*100:.1f}%")
return threats
# 使用示例
# analyze_throw_in_threats('match_events.csv')
进阶版(基于坐标的AI威胁判定)
适用于:你有球员位置追踪数据,需要计算“实际渗透力”。
该脚本使用 “界外球后5秒内,球在对方禁区前的推进距离” 作为威胁指数。
import math
import statistics
class ThrowInAnalyst:
def __init__(self):
self.throw_in_events = []
self.pass_sequences = []
def add_throw_in(self, time, team, x, y):
"""记录界外球事件"""
self.throw_in_events.append({
'time': time,
'team': team,
'x': x,
'y': y
})
def add_pass(self, time, team, start_x, start_y, end_x, end_y, successful=True):
"""记录传球事件"""
self.pass_sequences.append({
'time': time,
'team': team,
'start': (start_x, start_y),
'end': (end_x, end_y),
'successful': successful
})
def calculate_threat_score(self, throw_x, throw_y, team_passes):
"""
计算威胁指数 (0-100)
指标: 距离目标(对方球门) | 传球推进速度 | 射门机会点
"""
# 假设对方球门在 (100, 50) 基于半场坐标
goal_x, goal_y = 100, 50
distance_to_goal = math.sqrt((goal_x - throw_x)**2 + (goal_y - throw_y)**2)
# 威胁评分:越接近球门=分数越高
distance_score = max(0, (100 - distance_to_goal) / 100) * 50
# 传球深度推进
total_progression = 0
for p in team_passes[:3]: # 取前3次传球
dx = p[1][0] - p[0][0]
total_progression += dx
progression_score = min(50, total_progression * 2)
return distance_score + progression_score
def analyze(self):
"""主分析逻辑"""
stats = {
'total': len(self.throw_in_events),
'threats_high': 0, # 威胁>60
'threats_med': 0, # 威胁 30-60
'threats_low': 0, # 威胁<30
'avg_threat': 0
}
threat_list = []
for idx, throw_in in enumerate(self.throw_in_events):
# 查找与该界外球时间相近的该队传球 (简化: 取后续3次)
team_passes = []
for p in self.pass_sequences:
if p['time'] > throw_in['time'] and p['team'] == throw_in['team']:
team_passes.append(p)
if len(team_passes) == 3:
break
# 计算威胁值
threat_value = self.calculate_threat_score(
throw_in['x'], throw_in['y'], team_passes
)
threat_list.append(threat_value)
# 分级
if threat_value > 60:
stats['threats_high'] += 1
elif threat_value > 30:
stats['threats_med'] += 1
else:
stats['threats_low'] += 1
# 清空列表后重新建立当前动态的统计结果
stats['avg_threat'] = statistics.mean(threat_list) if threat_list else 0
print("\n" + "="*50)
print(" 界外球进攻威胁分析报告")
print("="*50)
print(f" 总界外球数: {stats['total']}")
print(f" 高威胁次数 (>60分): {stats['threats_high']}次")
print(f" 中威胁次数 (30-60分): {stats['threats_med']}次")
print(f" 低威胁次数 (<30分): {stats['threats_low']}次")
print(f" 平均威胁指数: {stats['avg_threat']:.1f}/100")
print("="*50)
# 返回可进一步处理的数据
return stats, threat_list
# 示例测试数据
if __name__ == "__main__":
analyst = ThrowInAnalyst()
# 模拟数据:第10分钟 左侧边界抛球,之后有两次有威胁的传球
analyst.add_throw_in(600, "Home", 30, 75) # 本方半场界外球
analyst.add_pass(602, "Home", 30, 75, 45, 80, True)
analyst.add_pass(605, "Home", 45, 80, 70, 85, True) # 推进至对方危险区
analyst.add_pass(608, "Home", 70, 85, 95, 88, True) # 传入禁区
analyst.add_throw_in(700, "Home", 85, 50) # 对方半场靠近边界
analyst.add_pass(702, "Home", 85, 50, 90, 80, True)
analyst.analyze()
如何调整成你的实际数据?
- 如果数据在 Excel:导出为 CSV,修改方案一的字段名。
- 如果数据是视频分析:使用
Opta/StatsBomb等平台导出事件数据,将event_type对应为throw-in、pass、shot。 - 自定义“威胁”定义:在
calculate_threat_score函数中,你可以增加“是否直入禁区”判断,或加入“控球时间”作为权重。
需要进一步帮助?
如果你能提供 数据样本格式(哪怕是几行),我可以帮你定制一个完全匹配的脚本,比如你的数据是长这样?:
| 时间 | 事件 | 球员 | 起始 x | 起始 y | 结束 x | 结束 y | 结果 |
|---|---|---|---|---|---|---|---|
| 45:30 | Throw-in | 10号 | 25 | 40 | 成功 |
告诉我你的具体数据格式,我可以直接帮你写一个开箱即用的版本。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播