实用脚本如何分析定位球战术的多样性?

wen 实用脚本 3

实用脚本如何分析定位球战术的多样性

分析定位球战术多样性,核心是把非结构化的定位球事件转化为可量化、可聚类、可对比的数据特征,下面给出一套可落地的脚本思路和代码框架。

实用脚本如何分析定位球战术的多样性?


分析框架(先想清楚要测什么)

定位球多样性可以从四个维度刻画:

维度 含义 示例指标
空间多样性 落点/传球区域分布 落点熵、区域覆盖率
战术类型多样性 战术套路种类 短传/长传/战术跑位占比
执行者多样性 主罚人/接应点 主罚人香农熵
结果多样性 形成的威胁方式 射门/头球/二点球分布

核心量化工具:香农熵(Shannon Entropy) —— 熵越高,战术越多样;熵越低,越单一可预测。


数据准备

需要的数据字段(以足球为例):

# 每条记录 = 一次定位球
{
  "match_id": "M001",
  "team": "A",
  "set_piece_type": "corner",      # corner/free_kick/throw_in/penalty
  "taker": "Player1",
  "delivery_type": "inswing",      # 内旋/外旋/短传/战术
  "target_zone": "near_post",      # 落点区域
  "first_contact": "header",
  "outcome": "shot",               # shot/goal/clearance/lost
  "x_start": 100, "y_start": 0,    # 坐标
  "x_end": 110, "y_end": 5
}

核心脚本

计算多样性熵

import pandas as pd
import numpy as np
from scipy.stats import entropy
from collections import Counter
def diversity_entropy(series):
    """归一化香农熵: 0=完全单一, 1=完全均匀分布"""
    counts = Counter(series.dropna())
    probs = np.array(list(counts.values())) / sum(counts.values())
    if len(probs) <= 1:
        return 0.0
    raw = entropy(probs, base=2)
    return raw / np.log2(len(probs))  # 归一化到[0,1]
def team_setpiece_profile(df):
    """按球队+定位球类型输出多样性画像"""
    results = []
    for (team, sp_type), g in df.groupby(["team", "set_piece_type"]):
        results.append({
            "team": team,
            "set_piece_type": sp_type,
            "count": len(g),
            "zone_diversity":   diversity_entropy(g["target_zone"]),
            "delivery_diversity": diversity_entropy(g["delivery_type"]),
            "taker_diversity":  diversity_entropy(g["taker"]),
            "outcome_diversity":diversity_entropy(g["outcome"]),
        })
    return pd.DataFrame(results)

落点空间分布(网格化 + 覆盖率)

def zone_coverage(df, bins=6, pitch_len=105, pitch_wid=68):
    """把落点映射到网格,计算覆盖率和集中度(基尼系数)"""
    gx = np.clip((df["x_end"] / pitch_len * bins).astype(int), 0, bins-1)
    gy = np.clip((df["y_end"] / pitch_wid * bins).astype(int), 0, bins-1)
    cell = gx * bins + gy
    counts = cell.value_counts()
    total_cells = bins * bins
    coverage = len(counts) / total_cells          # 覆盖了多少格子
    # 基尼系数: 越接近1越集中
    vals = np.sort(counts.values)
    n = len(vals)
    cum = np.cumsum(vals) / vals.sum()
    gini = 1 - 2 * np.trapz(cum, dx=1/n) + 1/n
    return {"coverage": coverage, "gini": gini, "n_zones": len(counts)}

战术聚类(把套路自动归类)

用 KMeans 对轨迹/落点做无监督聚类,再看每队用了多少种"套路"。

from sklearn.cluster import KMeans
from sklearn.preprocessing import StandardScaler
def cluster_routines(df, n_clusters=6):
    feats = df[["x_start","y_start","x_end","y_end"]].dropna()
    X = StandardScaler().fit_transform(feats)
    km = KMeans(n_clusters=n_clusters, n_init=10, random_state=0)
    labels = km.fit_predict(X)
    df = df.loc[feats.index].copy()
    df["routine"] = labels
    return df, km
def routine_usage(df):
    """每队使用了几类套路 + 分布均匀度"""
    out = []
    for team, g in df.groupby("team"):
        usage = g["routine"].value_counts(normalize=True)
        out.append({
            "team": team,
            "n_routines_used": g["routine"].nunique(),
            "routine_entropy": diversity_entropy(g["routine"]),
            "dominant_share": usage.iloc[0],  # 最常用套路占比
        })
    return pd.DataFrame(out)

多样性综合评分

def composite_diversity(profile_df, weights=None):
    weights = weights or {
        "zone_diversity":0.3, "delivery_diversity":0.25,
        "taker_diversity":0.2, "outcome_diversity":0.25
    }
    score = sum(profile_df[k]*w for k,w in weights.items())
    profile_df = profile_df.copy()
    profile_df["diversity_score"] = score
    return profile_df.sort_values("diversity_score", ascending=False)

进阶:预测性分析

关键洞察 —— 多样性 ≠ 有效性,建议同时算:

def predictability_vs_threat(df):
    """可预测性 vs 威胁产出"""
    res = []
    for team, g in df.groupby("team"):
        # 用熵衡量可预测性
        ent = diversity_entropy(g["target_zone"])
        # 威胁产出: 射门率、进球率
        threat = (g["outcome"].isin(["shot","goal"])).mean()
        res.append({"team":team, "entropy":ent, "threat_rate":threat})
    return pd.DataFrame(res)
  • 高熵 + 高威胁 = 战术灵活且致命(理想)
  • 低熵 + 高威胁 = 套路固定但执行强(如经典近门柱)
  • 高熵 + 低威胁 = 变化多但没质量
  • 低熵 + 低威胁 = 单一且无效

可视化(可选)

import matplotlib.pyplot as plt
def plot_zone_heat(df, team):
    g = df[df["team"]==team]
    plt.hexbin(g["x_end"], g["y_end"], gridsize=15, cmap="Reds")
    plt.title(f"{team} 定位球落点分布")
    plt.colorbar(label="次数")
    plt.show()

实操建议

  1. 样本量: 单队单赛事定位球通常 < 100 次,熵值波动大,建议跨赛季/多赛事合并。
  2. 区域定义要先统一: 落点用固定网格(如 6×6),否则无法对比。
  3. 区分定位球类型: 角球、任意球、界外球的战术逻辑完全不同,先分组再算。
  4. 结合视频: 熵只能告诉你"变没变",变的是不是主动设计需回看录像标签。
  5. 对手维度: 同一队伍的多样性会随对手变化,可加 opponent 分组。

如果你告诉我具体场景(足球/篮球?数据来源是 StatsBomb、Opta 还是自采?),我可以把脚本改成直接适配你数据格式的版本。

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