python案例如何分析定位球战术的多样性?

wen python案例 2

用Python分析定位球战术多样性的完整案例

下面给你一个可运行的完整案例分析框架,涵盖数据采集、特征工程、多样性度量和可视化四个环节。

python案例如何分析定位球战术的多样性?


分析思路

定位球战术多样性可从以下几个维度量化:

维度 指标示例
战术类型多样性 角球短传/长传/战术配合的种类数与分布熵
落点多样性 落点区域分布的熵、集中度
参与球员多样性 触球球员组合数量、传球链路长度
时间模式 快发 vs 慢发的比例
结果多样性 射门/进球/被解围等结局分布

核心数学工具:香农熵(Shannon Entropy)、基尼-辛普森指数、聚类、序列模式挖掘。


数据准备(模拟数据,可替换为 StatsBomb / Wyscout 数据)

import pandas as pd
import numpy as np
from collections import Counter
import matplotlib.pyplot as plt
import seaborn as sns
from scipy.stats import entropy
from sklearn.cluster import KMeans
np.random.seed(42)
# 模拟一支球队一个赛季的角球数据
n = 120
set_pieces = pd.DataFrame({
    "match_id": np.random.randint(1, 30, n),
    "sp_type": np.random.choice(["corner", "free_kick", "throw_in"], n, p=[0.55, 0.25, 0.20]),
    "tactic": np.random.choice(
        ["short_corner", "long_corner", "near_post", "far_post", "training_ground"],
        n, p=[0.15, 0.30, 0.25, 0.20, 0.10]
    ),
    # 落点坐标(以球场为 120x80 归一化)
    "end_x": np.random.normal(100, 15, n).clip(0, 120),
    "end_y": np.random.normal(40, 20, n).clip(0, 80),
    # 参与球员数
    "n_players_involved": np.random.randint(1, 6, n),
    # 传球次数(战术复杂度)
    "n_passes": np.random.poisson(1.2, n),
    # 快发(1) 或 组织(0)
    "quick_restart": np.random.choice([0, 1], n, p=[0.7, 0.3]),
    # 结局
    "outcome": np.random.choice(["shot", "goal", "cleared", "lost", "foul"], n,
                                p=[0.30, 0.08, 0.35, 0.20, 0.07])
})

核心多样性度量

香农熵 —— 度量战术类型的分布均匀度

def shannon_entropy(series):
    counts = series.value_counts(normalize=True)
    return entropy(counts, base=2)
def simpson_index(series):
    """1 - Σp²,值越大越多样"""
    p = series.value_counts(normalize=True)
    return 1 - (p**2).sum()
# 按定位球类型分别计算战术熵
result = set_pieces.groupby("sp_type").agg(
    tactic_entropy=("tactic", shannon_entropy),
    tactic_simpson=("tactic", simpson_index),
    outcome_entropy=("outcome", shannon_entropy),
    n=("tactic", "size")
)
print(result)

解读:熵值越高说明该类型定位球的战术选择越不可预测,对手越难防守。

落点空间多样性 —— 用核密度 + 网格熵

# 将球场分为 6x4 网格,计算落点分布熵
def grid_entropy(df, bins_x=6, bins_y=4):
    x_bins = np.linspace(0, 120, bins_x + 1)
    y_bins = np.linspace(0, 80, bins_y + 1)
    grid = pd.cut(df["end_x"], x_bins, labels=False) * bins_y + \
           pd.cut(df["end_y"], y_bins, labels=False)
    return shannon_entropy(grid.dropna())
print("落点分布熵:", grid_entropy(set_pieces))

战术复杂度熵(基于参与人数 + 传球次数)

set_pieces["complexity"] = set_pieces["n_players_involved"] + set_pieces["n_passes"]
set_pieces["c_band"] = pd.cut(set_pieces["complexity"], [0,1,2,3,5,10], right=False)
print("复杂度分布熵:", shannon_entropy(set_pieces["c_band"]))

聚类发现战术"原型"

from sklearn.preprocessing import StandardScaler
features = set_pieces[["end_x", "end_y", "n_players_involved", "n_passes"]]
X = StandardScaler().fit_transform(features)
km = KMeans(n_clusters=4, random_state=42, n_init=10)
set_pieces["cluster"] = km.fit_predict(X)
# 每个簇的战术原型
for c in sorted(set_pieces["cluster"].unique()):
    sub = set_pieces[set_pieces["cluster"] == c]
    print(f"\n簇 {c} (n={len(sub)})")
    print(f"  主要战术: {sub['tactic'].mode()[0]}")
    print(f"  平均落点: ({sub['end_x'].mean():.1f}, {sub['end_y'].mean():.1f})")
    print(f"  平均参与人数: {sub['n_players_involved'].mean():.1f}")
    print(f"  平均传球: {sub['n_passes'].mean():.2f}")

这一步能告诉你:球队实际上会打几种"套路",每个套路的核心特征是什么。


可视化

fig, axes = plt.subplots(1, 3, figsize=(16, 4))
# 1. 战术类型分布
set_pieces["tactic"].value_counts().plot.bar(ax=axes[0], color="steelblue")
axes[0].set_title("定位球战术类型分布")
# 2. 落点热图
sns.kdeplot(data=set_pieces, x="end_x", y="end_y", fill=True,
            cmap="rocket_r", ax=axes[1])
axes[1].set_xlim(0, 120); axes[1].set_ylim(0, 80)
axes[1].set_title("落点空间分布")
# 3. 不同定位球类型的战术熵对比
result["tactic_entropy"].plot.bar(ax=axes[2], color="coral")
axes[2].set_title("各类型定位球战术熵")
plt.tight_layout()
plt.show()

进阶:序列模式挖掘(传球链路)

真实事件数据有 pass_sequence,可用 PrefixSpan / SPADE 挖掘高频战术链:

# pip install prefixspan
from prefixspan import PrefixSpan
# 示例:每条定位球的战术动作序列
sequences = [
    [0, 0, 1], [1, 0], [0, 0, 2, 1], [0, 1], [2, 0, 0, 1], [1], [0, 0, 1],
    [0, 1, 0], [1, 0, 0, 1]
]  # 编码:0=短传, 1=传中, 2=回做
ps = PrefixSpan(sequences)
patterns = ps.frequent(2)  # 至少出现 2 次
for freq, pat in sorted(patterns, reverse=True)[:10]:
    print(f"  频次 {freq}: {pat}")

对比不同球队/赛季的序列模式集合 → 用 Jaccard 相似度量化战术打法多样性差异。


如何解读结论

结合指标,给出可落地的分析(示例):

现象 数据证据 战术含义
角球打法单一 战术熵 < 1.0,某簇占 60%+ 对手易于针对性布置
落点高度集中 网格熵低、近柱簇主导 缺远柱威胁
复杂度双峰 复杂度熵有 2 个峰 只打"快"或"稳",缺中间层次
序列模式雷同 前 3 个模式覆盖 80% 缺乏假动作/二次配合

提升建议:增加多样性 = 提升熵 + 扩展序列模式覆盖面,例如引入短角球变体、反跑配合、二次进攻设计。


真实数据对接

  • StatsBomb Open Data:免费,含 pass, shot, set_piece 事件 → statsbombpy 库
  • Wyscout:商业,事件 + 追踪
  • FBref:统计层面,便于做结果验证
# statsbombpy 示例
from statsbombpy import sb
events = sb.events(match_id=3788741)
corners = events[events["pass_type"] == "Corner"]

需要我帮你在真实 StatsBomb 数据上跑一遍完整流程,或者进一步深入序列模式/贝叶斯不确定性度量中的某一环吗?

抱歉,评论功能暂时关闭!