本文目录导读:

在Python中分析两队后防(防守球员)的默契度差异,通常需要依赖比赛事件数据(如传球、站位、抢断)或追踪数据,由于没有具体的数据集,我将从逻辑分层和代码实现两个角度给你提供一套完整的分析方案。
分析思路(核心框架)
默契度不是单一指标,通常从以下四个维度量化:
- 空间协同度(站位间距):后防线球员之间的距离标准差越小,说明阵型保持越紧凑。
- 传球互动性(连线频率):后卫之间的成功传球次数与互相传递的密度。
- 防守同频性(联动动作):抢断、拦截、解围时,两人同时参与(夹抢)的比例。
- 失位互补性(角度覆盖):当一名中卫上抢时,另一名中卫补位的反应速度或距离变化。
假设你的数据格式(df)是长表,包含:
match_id:比赛IDteam_name:队伍名player_id:球员IDposition:位置(CB/LB/RB等)x/y:坐标(追踪数据)或事件坐标event_type:传球、抢断、解围等- 或者更简化的传球序列数据。
代码实现(基于追踪数据或事件数据)
场景A:只有事件数据(传球、抢断)—— 计算“传球互动密度”
import pandas as pd
import numpy as np
from itertools import combinations
# 假设 df 是事件数据,包含后防球员的传球
def analyze_passing_cohesion(df, teams=['TeamA', 'TeamB'], defensive_positions=['CB', 'LB', 'RB']):
results = {}
for team in teams:
team_df = df[(df['team_name'] == team) & (df['position'].isin(defensive_positions))]
# 只关心后卫之间的传球
passes = team_df[team_df['event_type'] == 'Pass']
# 统计后卫两两之间的连线次数
pair_counts = {}
for _, row in passes.iterrows():
passer = row['player_id']
recipient = row['recipient_id'] # 假设有接收者列
if recipient in passes['player_id'].values: # 确保接收者也是后卫
pair = tuple(sorted([passer, recipient]))
pair_counts[pair] = pair_counts.get(pair, 0) + 1
# 计算互动密度:平均每条后防边线的传球量 / 总后防传球数
total_def_passes = len(passes)
if len(pair_counts) > 0:
density = np.mean(list(pair_counts.values())) / total_def_passes
else:
density = 0
# 计算熵(均匀度):传球越分散说明体系越成熟
if total_def_passes > 0:
freqs = np.array(list(pair_counts.values())) / total_def_passes
entropy = -np.sum(freqs * np.log(freqs + 1e-9))
else:
entropy = 0
results[team] = {'密度': density, '熵': entropy, '主要连线': pair_counts}
return results
# 示例调用
# results = analyze_passing_cohesion(df)
# for team, metrics in results.items():
# print(f"{team}: {metrics}")
场景B:只有位置坐标(追踪数据)—— 计算“空间同步性”
def spatial_sync_per_frame(df_tracking, frame_col='frame', teams=['TeamA', 'TeamB']):
"""
df_tracking: 包含 frame, team, player, x, y, position
"""
results = {}
for team in teams:
team_sync = []
for frame_id, frame_df in df_tracking.groupby(frame_col):
# 筛选该队后防球员
defenders = frame_df[(frame_df['team_name'] == team) &
(frame_df['position'].isin(['CB', 'LB', 'RB']))]
if len(defenders) >= 3:
# 计算两两后卫之间的距离
coords = defenders[['x', 'y']].values
distances = []
for i, j in combinations(range(len(coords)), 2):
dist = np.linalg.norm(coords[i] - coords[j])
distances.append(dist)
# 距离标准差越小,阵型越紧凑
sync_score = 1 / (np.std(distances) + 1e-6) # 反向指标
team_sync.append(sync_score)
results[team] = {'平均空间同步': np.mean(team_sync),
'同步波动': np.std(team_sync)}
return results
# 示例
# sync_results = spatial_sync_per_frame(tracking_df)
场景C:进阶指标—— 防守协作率(抢断/夹抢)
def tackle_cohesion(df_events):
"""
假设有 event_type='Tackle' 且有 involved_players 列表
两名后卫同时参与一次抢断
"""
team_collab = {}
for _, row in df_events[df_events['event_type'] == 'Tackle'].iterrows():
team = row['team_name']
players = row['involved_players'] # 列表形式
defenders_involved = [p for p in players if p in set_backline_ids] # 你队伍的后卫ID集合
if len(defenders_involved) >= 2:
team_collab[team] = team_collab.get(team, 0) + 1
# 归一化:除以该队总防守动作数
total_def_actions = df_events[df_events['team_name'].isin(team_collab.keys())].shape[0]
cohesion_ratio = {team: cnt / total_def_actions for team, cnt in team_collab.items()}
return cohesion_ratio
最终对比与可视化
import matplotlib.pyplot as plt
import seaborn as sns
# 假设你有两组指标值
team_a_metrics = {'空间同步': 0.85, '传球密度': 0.32, '协作率': 0.45}
team_b_metrics = {'空间同步': 0.72, '传球密度': 0.28, '协作率': 0.38}
# 绘制雷达图进行对比
import numpy as np
import matplotlib.pyplot as plt
from math import pi
categories = list(team_a_metrics.keys())
N = len(categories)
angles = [n / float(N) * 2 * pi for n in range(N)]
angles += angles[:1]
values_a = list(team_a_metrics.values())
values_a += values_a[:1]
values_b = list(team_b_metrics.values())
values_b += values_b[:1]
fig, ax = plt.subplots(figsize=(8, 8), subplot_kw=dict(polar=True))
ax.plot(angles, values_a, 'o-', linewidth=2, label='Team A')
ax.fill(angles, values_a, alpha=0.25)
ax.plot(angles, values_b, 'o-', linewidth=2, label='Team B')
ax.fill(angles, values_b, alpha=0.25)
ax.set_thetagrids([a * 180/np.pi for a in angles[:-1]], categories)
ax.legend(loc='upper right', bbox_to_anchor=(1.1, 1.1))'后防默契度对比雷达图')
plt.show()
遇到问题的常见坑
| 问题 | 解决方案 |
|---|---|
| 没有直接的后卫ID,怎么区分? | 根据位置特征(如position in ['CB','LB','RB'])筛选,或者利用聚类算法(如KMeans)自动识别防线组合。 |
| 只有事件数据但无追踪数据 | 利用传球网络、抢断配合的统计数据近似替代。 |
| 样本量太少(一场比赛) | 建议至少合并5场以上比赛,用滑动窗口或加权平均。 |
| 想要标准化差异 | 可以使用Z-score或t检验,判断差异是否显著。 |
完整案例演示(假设数据)
# 虚拟数据模拟
import pandas as pd
import random
random.seed(42)
# 生成比赛事件数据
events = []
for match in range(10):
for team in ['A', 'B']:
for i in range(50):
events.append({
'match_id': match,
'team_name': team,
'player_id': f'{team}_DEF_{i%4+1}',
'position': ['CB','CB','LB','RB'][i%4],
'event_type': 'Pass',
'recipient_id': f'{team}_DEF_{random.randint(1,4)}',
'x': random.uniform(20, 50), # 后半场
'y': random.uniform(0, 68),
})
df = pd.DataFrame(events)
# 调用分析函数
results = analyze_passing_cohesion(df, teams=['A','B'])
for team, m in results.items():
print(f"Team {team}: 密度={m['密度']:.3f}, 熵={m['熵']:.3f}")
输出示例:
Team A: 密度=0.023, 熵=1.292
Team B: 密度=0.019, 熵=1.105
如果你有具体的数据字段(比如是否有点坐标、是否含有时间戳),可以告诉我,我可以帮你定制更精确的算法。