本文目录导读:

“撞墙式配合”在足球里通常指 二过一(one-two)/ 踢墙配合:A 传给 B,B 不停球直接回做给 A,A 再接球推进。
如果你要“用脚本统计完成了几次”,关键不是写脚本本身,而是先定义什么算一次成功撞墙。
下面给你一个可落地的统计思路 + Python 示例脚本框架,你可以根据你手里的数据格式(事件数据、追踪数据、视频标注)替换。
先定义“成功撞墙式配合”的规则
建议至少满足:
- 球员 A 传球给球员 B
- B 在很短时间内(如 0.5~2 秒内)直接回传/做球给 A
- B 基本没有带球推进(触球次数很少,1 次)
- A 接到回做球后,球权仍在本方
- 可选:A 接球后向前推进/突破,才算“成功完成”
如果太宽松,会把普通回传也算进去;太严格,会漏掉。
如果你有事件数据(推荐)
常见字段类似:
| 字段 | 含义 |
|---|---|
| match_id | 比赛 |
| period | 上/下半场 |
| timestamp | 时间 |
| team_id | 球队 |
| player_id | 球员 |
| event_type | pass / reception / carry |
| receiver_id | 接球人 |
| x, y | 位置 |
| end_x, end_y | 传球终点 |
判断逻辑
按时间排序后,扫描连续事件:
- 事件1:A 传球给 B
- 事件2:B 传球给 A
- 两者时间差 ≤ 阈值
- 两队相同
- B 中间没有 carry / dribble / 被抢断
- A 接到 B 的回传后,本方仍控球
Python 示例
import pandas as pd
# 读取事件数据
df = pd.read_csv("events.csv")
# 假设字段:
# match_id, period, timestamp, team_id, player_id, event_type, receiver_id, x, y, end_x, end_y
df = df.sort_values(["match_id", "period", "timestamp"]).reset_index(drop=True)
def is_wall_pass(ev1, ev2, max_gap=2.0):
"""
判断 ev1, ev2 是否构成一次撞墙配合
ev1: A -> B
ev2: B -> A
"""
# 1. 都是传球
if ev1["event_type"] != "pass" or ev2["event_type"] != "pass":
return False
# 2. 同队
if ev1["team_id"] != ev2["team_id"]:
return False
# 3. 时间差
if ev2["timestamp"] - ev1["timestamp"] > max_gap:
return False
# 4. A -> B, B -> A
a1 = ev1["player_id"]
b1 = ev1["receiver_id"]
b2 = ev2["player_id"]
a2 = ev2["receiver_id"]
if not (b1 == b2 and a1 == a2):
return False
return True
def count_wall_passes(df, max_gap=2.0):
results = []
n = len(df)
i = 0
while i < n - 1:
ev1 = df.iloc[i]
ev2 = df.iloc[i + 1]
if is_wall_pass(ev1, ev2, max_gap=max_gap):
results.append({
"match_id": ev1["match_id"],
"period": ev1["period"],
"time": ev1["timestamp"],
"player_a": ev1["player_id"],
"player_b": ev1["receiver_id"],
"team_id": ev1["team_id"]
})
i += 2 # 避免重复计数
else:
i += 1
return pd.DataFrame(results)
wall_df = count_wall_passes(df, max_gap=2.0)
print("撞墙配合次数:", len(wall_df))
print(wall_df.head())
# 按球队统计
print(wall_df.groupby("team_id").size().sort_values(ascending=False))
# 按球员组合统计
print(wall_df.groupby(["player_a", "player_b"]).size().sort_values(ascending=False).head(10))
如果你只有追踪数据
追踪数据没有“传球事件”,就要自己检测:
- 检测球权归属变化
- 检测球从 A 附近移动到 B 附近
- 再快速回到 A 附近
- 中间 B 触球时间很短
- 球整体推进方向符合“撞墙”意图
伪逻辑:
找到球附近球员 A 球离开 A,接近 B B 触球时间 < 0.4s 球快速返回 A A 再次触球 => 记一次撞墙
这种误判会比较多,通常要加:
- 最小传球距离
- 最大回传时间
- 防守球员距离
- 是否向前推进
如果你只有视频
那就需要:
- 目标检测:球员、球
- 跟踪:ID 分配
- 事件切分:传球/触球
- 再套上面的逻辑
常见工具:
- YOLO + ByteTrack / DeepSORT
- SoccerNet 数据集
- SportsMOT
- 自标注事件
更严谨的“成功”定义
如果你要统计的是真正打成的撞墙配合,建议加这些条件:
- A 回接后向前推进超过 3 米
- 或 A 回接后 3 秒内完成射门/关键传球
- 或这次配合让球队突破了一条防线
- B 回做时没有停球调整
- 回做方向与 A 前进方向一致
否则“后卫互相倒脚”也可能被算进去。
你可以直接用的最小版本
如果你的数据就是简单表:
time,team,from,to 10.1,A,1,2 10.8,A,2,1 15.2,A,3,4 16.0,A,4,3
脚本:
import csv
rows = []
with open("passes.csv") as f:
for row in csv.DictReader(f):
rows.append(row)
count = 0
i = 0
while i < len(rows) - 1:
p1 = rows[i]
p2 = rows[i+1]
same_team = p1["team"] == p2["team"]
a_to_b = p1["from"] == p2["to"]
b_to_a = p1["to"] == p2["from"]
time_gap = float(p2["time"]) - float(p1["time"])
if same_team and a_to_b and b_to_a and time_gap <= 2.0:
count += 1
i += 2
else:
i += 1
print("撞墙配合次数:", count)
统计“撞墙式配合完成了几次”,核心是:
- 定义成功标准
- 按时间扫描连续传球事件
- 判断 A→B→A 且时间间隔短
- 排除带球、丢球、死球
- 按球队/球员/比赛汇总
如果你把数据格式发我(CSV 字段、追踪数据还是视频),我可以直接帮你写一版能跑的完整脚本。