本文目录导读:

我来帮你创建一个统计横传转移球次数的实用脚本,横传转移通常指球场中路的横向传球或大范围转移,我会用Python编写一个可分析的脚本。
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
足球横传转移球统计脚本
统计比赛中横向传球/大范围转移球的次数
"""
import json
import re
from collections import defaultdict
class TransferPassAnalyzer:
"""横传转移球分析器"""
def __init__(self):
# 球场坐标范围(标准足球场105m x 68m)
self.PITCH_LENGTH = 105.0
self.PITCH_WIDTH = 68.0
# 横向转移判定参数
self.MIN_TRANSFER_DISTANCE = 25.0 # 最小转移距离(米)
self.MAX_TRANSFER_ANGLE = 30.0 # 最大传球角度(与横线的夹角)
# 统计结果
self.stats = {
'total_passes': 0,
'transfer_passes': 0,
'transfer_rate': 0.0,
'players': defaultdict(lambda: {'total': 0, 'transfer': 0}),
'areas': defaultdict(int)
}
def analyze_pass(self, x1, y1, x2, y2):
"""
分析单次传球是否为横传转移
参数:
x1, y1: 传球起始坐标
x2, y2: 传球结束坐标
"""
# 计算传球距离
distance = ((x2-x1)**2 + (y2-y1)**2) ** 0.5
# 计算传球角度(相对于横向的夹角)
# 横向传球角度小,纵向传球角度大
if distance > 0:
# 计算与横向(x方向)的夹角
angle = abs(__import__('math').atan2(abs(y2-y1), abs(x2-x1)))
angle_deg = __import__('math').degrees(angle)
else:
angle_deg = 90.0
# 判断是否为横传转移
is_transfer = (
distance >= self.MIN_TRANSFER_DISTANCE and
angle_deg <= self.MAX_TRANSFER_ANGLE
)
return is_transfer, distance, angle_deg
def analyze_match(self, events):
"""
分析整场比赛事件
参数:
events: 传球事件列表,每个事件包含:
{'player': '球员名', 'x1': x, 'y1': y, 'x2': x, 'y2': y, 'team': '队伍'}
"""
transfer_events = []
for event in events:
self.stats['total_passes'] += 1
# 分析传球
is_transfer, distance, angle = self.analyze_pass(
event['x1'], event['y1'], event['x2'], event['y2']
)
# 更新球员统计
player_name = event.get('player', 'unknown')
team = event.get('team', 'unknown')
self.stats['players'][f"{team}-{player_name}"]['total'] += 1
if is_transfer:
self.stats['transfer_passes'] += 1
self.stats['players'][f"{team}-{player_name}"]['transfer'] += 1
# 记录转移区域(前场/中场/后场)
mid_x = (event['x1'] + event['x2']) / 2
if mid_x < self.PITCH_LENGTH / 3:
area = '后场'
elif mid_x < 2 * self.PITCH_LENGTH / 3:
area = '中场'
else:
area = '前场'
self.stats['areas'][area] += 1
transfer_events.append({
**event,
'distance': distance,
'angle': angle,
'type': '横传转移'
})
# 计算转移率
if self.stats['total_passes'] > 0:
self.stats['transfer_rate'] = (
self.stats['transfer_passes'] / self.stats['total_passes'] * 100
)
return transfer_events
def print_report(self):
"""打印统计报告"""
print("=" * 60)
print("横传转移球统计报告")
print("=" * 60)
# 总体统计
print(f"\n总体统计:")
print(f" 总传球次数: {self.stats['total_passes']}")
print(f" 横传转移次数: {self.stats['transfer_passes']}")
print(f" 转移率: {self.stats['transfer_rate']:.2f}%")
# 区域统计
print(f"\n区域分布:")
for area in ['后场', '中场', '前场']:
count = self.stats['areas'].get(area, 0)
percentage = (count / self.stats['transfer_passes'] * 100
if self.stats['transfer_passes'] > 0 else 0)
print(f" {area}: {count}次 ({percentage:.1f}%)")
# 球员统计
print(f"\n球员统计(前10名):")
sorted_players = sorted(
self.stats['players'].items(),
key=lambda x: x[1]['transfer'],
reverse=True
)[:10]
print(f" {'球员':<20} {'总传球':<10} {'横传转移':<10} {'转移率'}")
print(" " + "-" * 55)
for player, data in sorted_players:
rate = (data['transfer'] / data['total'] * 100
if data['total'] > 0 else 0)
print(f" {player:<20} {data['total']:<10} {data['transfer']:<10} {rate:.1f}%")
print("=" * 60)
def load_events_from_file(filepath):
"""从JSON文件加载事件数据"""
try:
with open(filepath, 'r', encoding='utf-8') as f:
return json.load(f)
except FileNotFoundError:
print(f"错误: 找不到文件 {filepath}")
return []
except json.JSONDecodeError:
print(f"错误: 文件 {filepath} 不是有效的JSON格式")
return []
def load_events_from_csv(filepath):
"""从CSV文件加载事件数据"""
import csv
events = []
try:
with open(filepath, 'r', encoding='utf-8') as f:
reader = csv.DictReader(f)
for row in reader:
try:
event = {
'player': row.get('player', 'unknown'),
'team': row.get('team', 'unknown'),
'x1': float(row.get('x1', 0)),
'y1': float(row.get('y1', 0)),
'x2': float(row.get('x2', 0)),
'y2': float(row.get('y2', 0))
}
events.append(event)
except ValueError as e:
print(f"警告: 跳过无效行 {row}: {e}")
except FileNotFoundError:
print(f"错误: 找不到文件 {filepath}")
return events
def generate_sample_data():
"""生成示例数据用于测试"""
import random
events = []
players = [
('张伟', '主队'), ('李强', '主队'), ('王芳', '主队'),
('赵磊', '主队'), ('刘洋', '主队'), ('陈杰', '主队'),
('杨光', '客队'), ('周明', '客队'), ('吴昊', '客队'),
('郑浩', '客队'), ('孙鹏', '客队'), ('马超', '客队')
]
# 生成100个传球事件
for _ in range(100):
player, team = random.choice(players)
# 随机位置
x1 = random.uniform(0, 105)
y1 = random.uniform(0, 68)
# 传球方向:随机偏向横向或纵向
if random.random() < 0.3: # 30%概率横向转移
x2 = x1 + random.uniform(-30, 30)
y2 = y1 + random.uniform(-5, 5)
else: # 其他传球
x2 = x1 + random.uniform(-20, 20)
y2 = y1 + random.uniform(-20, 20)
# 确保在球场范围内
x2 = max(0, min(105, x2))
y2 = max(0, min(68, y2))
events.append({
'player': player,
'team': team,
'x1': x1,
'y1': y1,
'x2': x2,
'y2': y2
})
return events
def main():
"""主函数"""
analyzer = TransferPassAnalyzer()
# 选择数据来源
print("选择数据输入方式:")
print("1. 使用示例数据")
print("2. 从JSON文件加载")
print("3. 从CSV文件加载")
choice = input("请输入选项 (1-3): ").strip()
if choice == '1':
# 生成示例数据
events = generate_sample_data()
print(f"使用示例数据 ({len(events)}次传球)")
elif choice == '2':
filepath = input("请输入JSON文件路径: ").strip()
events = load_events_from_file(filepath)
if not events:
print("未能加载数据,退出")
return
elif choice == '3':
filepath = input("请输入CSV文件路径: ").strip()
events = load_events_from_csv(filepath)
if not events:
print("未能加载数据,退出")
return
else:
print("无效选项")
return
# 分析数据
transfer_events = analyzer.analyze_match(events)
# 输出报告
analyzer.print_report()
# 保存转移球详情
if transfer_events:
save_choice = input("\n是否保存转移球详细数据? (y/n): ").strip().lower()
if save_choice == 'y':
filename = 'transfer_passes.json'
with open(filename, 'w', encoding='utf-8') as f:
json.dump(transfer_events, f, ensure_ascii=False, indent=2)
print(f"详细数据已保存至 {filename}")
if __name__ == "__main__":
main()
这个脚本的使用方法:
功能特点:
-
核心功能:
- 统计横传转移球的次数
- 计算转移球占总传球的比例
- 按区域(前场/中场/后场)统计
- 按球员统计个人转移球数据
-
判定标准:
- 传球距离 ≥ 25米
- 传球角度与横线夹角 ≤ 30度
-
数据输入方式:
- 示例数据(用于测试)
- JSON文件
- CSV文件
使用示例:
# 数据格式示例
pass_events = [
{
"player": "梅西",
"team": "巴萨",
"x1": 45.0, # 出发x坐标
"y1": 20.0, # 出发y坐标
"x2": 70.0, # 到达x坐标
"y2": 22.0 # 到达y坐标
},
# ... 更多传球事件
]
运行脚本:
python3 transfer_pass_analyzer.py
输出示例:
============================================================
横传转移球统计报告
============================================================
总体统计:
总传球次数: 100
横传转移次数: 34
转移率: 34.00%
区域分布:
后场: 12次 (35.3%)
中场: 15次 (44.1%)
前场: 7次 (20.6%)
球员统计(前10名):
球员 总传球 横传转移 转移率
-------------------------------------------------------
主队-王芳 12 5 41.7%
客队-杨光 10 4 40.0%
...
调整参数:
你可以根据需要调整判定标准:
MIN_TRANSFER_DISTANCE:最小转移距离MAX_TRANSFER_ANGLE:最大允许角度
如果需要支持其他格式或更复杂的数据分析,请告诉我!