本文目录导读:

在足球数据分析中,“横传转移球”通常指的是大范围转移(从一侧边路到另一侧边路的横向长传)或横向疏导球,不同的数据公司(如Opta、Wyscout)定义略有不同。
这里我为你提供两种不同场景下的实用 Python 脚本,你可以根据你的数据结构选择。
基于 StatsBomb 开源数据(带坐标,最精确)
如果你有详细的 x、y 坐标数据(如 StatsBomb 免费数据集),这个脚本能精准识别“横传转移”。
核心逻辑:
- 传球起止点的
y坐标(0-100)跨越了中线(y=50)或跨越了半个场地宽度(>40米)。 - 传球距离较长(> 35 码)。
- 传球方向几乎是横向的(
dx较小,dy较大)。
import pandas as pd
import json
# 假设 df 是你的传球事件 DataFrame,包含以下列:
# 'team': 队伍名称
# 'player': 球员名称
# 'x': 起始X坐标 (0-120)
# 'y': 起始Y坐标 (0-80)
# 'end_x': 结束X坐标
# 'end_y': 结束Y坐标
def calculate_switch_of_play(df):
"""
统计横传转移球(Switch of Play)
规则:传球跨越了场地的中分线,且横向距离超过总宽度的40%(>32)
"""
switches = []
for _, row in df.iterrows():
# 计算横向移动距离(Y轴变化)
dy = abs(row['end_y'] - row['y'])
# 计算纵向移动距离(X轴变化)
dx = abs(row['end_x'] - row['x'])
# 判定条件(以 StatsBomb 标准为例)
# 1. 必须是向前传球或平行传球
# 2. 横向移动距离超过 32(半场宽度80计)
# 3. 纵向推进距离小于横向距离的一半(确保是"横"传,而非"斜"长传)
if (dy >= 32) and (dx <= dy * 1.5) and (dx >= 5): # 最后一项避免把短横敲算进去
switches.append(row)
if not switches:
return pd.DataFrame()
else:
return pd.DataFrame(switches)
# 使用示例:
# switches_df = calculate_switch_of_play(passes_df)
# print(f"共检测到 {len(switches_df)} 次横传转移")
# 如果想按球队看:
# print(switches_df.groupby('team').size())
基于泛用型数据(只有事件描述,无坐标)
很多中文足球论坛的数据只有“传球”事件,没有精确坐标,这个脚本适用于:
- 数据中包含起止区域(如 Zone A, Zone B)
- 或者包含传球类型标签(如“左侧长传至右侧”)
def count_switch_from_zones(df):
"""
规则:
1. 传球起始区域在左路(1/3),结束区域在右路(1/3)
2. 传球起始区域在右路,结束区域在左路
假设数据有以下列:
- 'pass_origin': 传球起始区域 (如 'Left', 'Centre', 'Right')
- 'pass_end': 传球结束区域
"""
# 定义左右路
left_zones = ['Left', 'LW', 'LB', '左路', '左']
right_zones = ['Right', 'RW', 'RB', '右路', '右']
# 过滤条件:起止区域分别是左右路
mask = (
(df['pass_origin'].isin(left_zones) & df['pass_end'].isin(right_zones)) |
(df['pass_origin'].isin(right_zones) & df['pass_end'].isin(left_zones))
)
switches = df[mask]
print(f"找到横传转移次数: {len(switches)} 次")
# 按球队统计
if 'team' in switches.columns:
print(switches.groupby('team').size())
return switches
# 使用示例
# result = count_switch_from_zones(events_df)
绘图可视化(检验识别是否准确)
想直观地看到你统计出来的横传在哪里?这个片段能帮你画出传球线路图:
import matplotlib.pyplot as plt
import pandas as pd
# 假设 df 为包含识别出来的横传事件
def plot_switches(df):
fig, ax = plt.subplots(figsize=(12, 8))
# 画出足球场边框
ax.plot([0, 0, 120, 120, 0], [0, 80, 80, 0, 0], color='black', lw=2)
# 中线
ax.plot([60, 60], [0, 80], color='black', lw=1)
# 禁区
ax.plot([18, 18], [18, 62], color='black')
ax.plot([102, 102], [18, 62], color='black')
# 画出每条转移球路线
for _, row in df.iterrows():
ax.plot(
[row['x'], row['end_x']],
[row['y'], row['end_y']],
color='red', alpha=0.6, lw=1.5
)
ax.set_title(f"横传转移球分布图 (共{len(df)}次)")
ax.set_xlim(0, 120)
ax.set_ylim(0, 80)
plt.show()
# 调用绘图
# plot_switches(switches_df)
重要提示(关于参数调优)
在实际使用中,你需要根据你的数据来源调整阈值:
- 距离阈值:在方案一中,
dy >= 32这个数值可以调。- StatsBomb: 场地宽度 80,通常要求跨越超过40(即过中线)。
- Wyscout: 场地宽度 100,通常要求跨越超过50。
- 角度要求:真正的“转移”一般是横向推进,而不是大纵深长传。
dx远大于dy,那可能是对角长传,不算作经典意义的“横传转移”。
推荐初始参数(通用足球场坐标系):
# 中场宽度为 68米(Opta坐标为50) # 半场宽度为 25,全场宽度为 50 # 建议阈值:dy > 20(穿过半场中线),dx < dy
如果你能告诉我你拥有的数据结构(比如列名是英文还是中文,有无坐标),我可以帮你把脚本改到直接可运行。
版权声明: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直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播