本文目录导读:

在Python中分析“两队后防默契度差异”,首先要明确“默契度”是一个抽象概念,需要将其量化为具体的、可计算的指标。
根据足球数据分析的常见逻辑,后防默契度通常体现在:失球率、防守站位协同(造越位成功率)、解围与拦截的配合、对危险区域的保护等。
这里提供三种由浅入深的Python实现方案,你可以根据手头数据的详细程度选择:
基于基础防守数据对比(最简单的入门案例)
适用场景:只有球队的宏观统计数据(抢断、拦截、解围、失球等)。
核心逻辑:利用“防守成功率”或“防守贡献均衡度”来侧面反映默契,如果后防线的抢断/解围分布非常不均衡,说明可能依赖个别球星,整体配合度可能较低。
import pandas as pd
import numpy as np
# 模拟两支球队的后卫个体数据
data_a = {
'Player': ['后卫A1', '后卫A2', '后卫A3', '后卫A4'],
'Tackles': [5, 6, 2, 1], # 抢断
'Interceptions': [4, 8, 3, 2], # 拦截
'Clearances': [10, 12, 15, 20] # 解围
}
data_b = {
'Player': ['后卫B1', '后卫B2', '后卫B3', '后卫B4'],
'Tackles': [4, 4, 3, 3], # 分布较均匀
'Interceptions': [5, 5, 4, 4],
'Clearances': [12, 11, 13, 12]
}
df_a = pd.DataFrame(data_a)
df_b = pd.DataFrame(data_b)
# 定义“协作度”指标:变异系数(CV)越低,代表防守动作越平均,配合越默契
def calculate_cohesion(df):
# 计算总防守动作
df['Total_Defense'] = df['Tackles'] + df['Interceptions'] + df['Clearances']
mean = df['Total_Defense'].mean()
std = df['Total_Defense'].std()
cv = std / mean # 变异系数
return cv, df['Total_Defense'].sum()
cv_a, total_a = calculate_cohesion(df_a)
cv_b, total_b = calculate_cohesion(df_b)
print("="*50)
print("【评判标准】变异系数越小,个体防守贡献越均匀,潜台词是协防默契度高")
print("="*50)
print(f"球队A的防守变异系数: {cv_a:.2f} (总防守次数: {total_a})")
print(f"球队B的防守变异系数: {cv_b:.2f} (总防守次数: {total_b})")
if cv_a < cv_b:
print(">>> 球队A的后防个体动作更均衡,整体协同性显得更高。")
else:
print(">>> 球队B的后防个体动作更均衡,整体协同性显得更高。")
基于时空热力图分析(进阶 - 分析站位间距)
适用场景:拥有GPS轨迹数据或事件发生坐标(如解围发生在哪个区域)。
核心逻辑:默契度高的后防线,在防守时彼此间的间距保持得更好(不会过于分散导致空当大,也不会过于集中漏掉身后),通过分析后卫们一次防守事件中的坐标,计算平均距离和距离方差。
提示:需要安装 matplotlib 和 scipy 绘制图形来直观展示。
import numpy as np
import matplotlib.pyplot as plt
# 模拟强队A的一次防守站位(x, y坐标,半场横轴0-100,纵轴0-100)
coords_a = np.array([[20, 60], [20, 40], [30, 50], [15, 70]])
# 模拟弱队B的一次防守站位(站位散漫)
coords_b = np.array([[10, 80], [40, 20], [25, 60], [60, 30]])
def pairwise_distance(arr):
# 计算两两之间的欧几里得距离矩阵
diff = arr[:, None, :] - arr[None, :, :]
dist = np.sqrt((diff ** 2).sum(axis=-1))
return dist
dist_a = pairwise_distance(coords_a)
dist_b = pairwise_distance(coords_b)
# 只取上三角部分(排除自身到自身的距离0)
avg_gap_a = dist_a[np.triu_indices(4, k=1)].mean()
avg_gap_b = dist_b[np.triu_indices(4, k=1)].mean()
print(f"A队防线平均间距: {avg_gap_a:.2f} 米")
print(f"B队防线平均间距: {avg_gap_b:.2f} 米")
# 配合默契还看“同步性”:计算相邻后卫距离的方差
std_a = dist_a[np.triu_indices(4, k=1)].std()
std_b = dist_b[np.triu_indices(4, k=1)].std()
print(f"A队防线间距波动(标准差): {std_a:.2f}")
print(f"B队防线间距波动(标准差): {std_b:.2f}")
# 可视化
fig, axes = plt.subplots(1, 2, figsize=(10, 5))
for ax, coords, team in zip(axes, [coords_a, coords_b], ['Team A (默契)', 'Team B (生疏)']):
ax.scatter(coords[:, 0], coords[:, 1], s=100, c='red')
ax.set_title(team)
ax.set_xlim(0, 100)
ax.set_ylim(0, 100)
ax.invert_yaxis() # 让y轴朝上(足球场视角)
plt.tight_layout()
plt.show()
基于“协防网络”图论分析(最高阶)
适用场景:拥有逐场逐次防守成功(抢断、解围)的Pass/Event数据,明确知道哪两名后卫共同参与了同一次防守(抢断后传递给队友解围、两人包夹)。
核心逻辑:将后卫视为节点(Node),如果两人在1个赛季中有超过N次直接协防配合,就在两人之间连一条线。默契度 = 网络密度(实际连线数量 / 最大可能连线数量)。
import networkx as nx
# 模拟A队赛季中,“后卫i”与“后卫j”共同参与防守(拦截、解围、夹击)的次数
pairs_a = [('A1', 'A2'), ('A1', 'A2'), ('A1', 'A2'), ('A2', 'A3'), ('A3', 'A4')] # 极度依赖A1-A2组合
pairs_b = [('B1', 'B2'), ('B1', 'B2'), ('B2', 'B3'), ('B3', 'B4'), ('B4', 'B1'), ('B2', 'B4')] # 互动更广泛
G_a = nx.Graph()
G_b = nx.Graph()
G_a.add_edges_from(pairs_a)
G_b.add_edges_from(pairs_b)
# 计算网络密度:实际连线数 / 理论最大连线数(n(n-1)/2)
density_a = nx.density(G_a)
density_b = nx.density(G_b)
print(f"球队A后防协作网络密度: {density_a:.2f}")
print(f"球队B后防协作网络密度: {density_b:.2f}")
print(">> 密度越大,代表后防线上人人参与协防,没有明显的防守盲区,默契度评分越高。")
# 也可以计算平均相速度(连接的两个节点共同出场的频率标准差)
如何选择?
| 数据条件 | 推荐方案 | 核心洞察 |
|---|---|---|
| 只有Excel统计表 | 方案一 | 看个体防守数据的离散程度 |
| 拥有GPS轨迹数据 | 方案二 | 看防守阵型的紧凑度和间距稳定性 |
| 拥有详细事件日志 | 方案三 | 看后防人员之间的协防连接关系 |
最重要的提醒:任何单一指标都不能完全代表默契度,建议将方案一(基础统计)作为筛选工具,找到差异大的比赛,然后用方案二或三去定向回看录像验证逻辑是否正确,在代码中加入 print() 输出关键指标的逻辑是最重要的。