本文目录导读:

这是一个非常有趣且具有实际意义的Python数据分析案例,在足球(或其他体育)数据分析中,“回传次数”确实是衡量一支球队或球员“保守程度”的重要指标之一。
下面,我为你构建一个从数据模拟到分析可视化的完整案例,帮助你理解如何通过统计回传次数来量化保守程度。
核心逻辑
- 定义: 回传(或横传/向后传)通常意味着球队不寻求向前推进或突破,而是通过控制球权来降低风险,回传次数越多,通常代表打法越偏向于控球、安全、谨慎,即“保守”。
- 衡量指标:
- 绝对回传次数: 一场比赛中回传的总数。
- 回传占比:
回传次数 / 总传球次数,这个指标比绝对次数更有说服力,因为它排除了球队控球率整体高低的影响。 - 回传/向前传球比:
回传次数 / 向前传球次数,这是最能体现“拒绝冒险”倾向的指标。
案例设计
我们将模拟一个5轮联赛的数据,包含多支球队,我们将分析:
- 哪支球队最保守(回传占比最高)?
- 每支球队的保守程度随时间(轮次)的变化趋势。
完整Python代码
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
# 设置中文显示(如果有中文标签的需要)
plt.rcParams['font.sans-serif'] = ['SimHei'] # 或者 ['Microsoft YaHei']
plt.rcParams['axes.unicode_minus'] = False
# ------------------- 1. 模拟数据生成 -------------------
np.random.seed(42)
teams = ['勇士FC', '风暴联', '蓝月亮', '红魔队', '银河队']
rounds = 5 # 模拟5轮比赛
data = []
for team in teams:
# 为每支球队设定一个“保守倾向”的基准参数
# 保守队:回传多,向前少;激进队:回传少,向前多
if team == '勇士FC':
base_back = 45 # 基准回传次数
base_forward = 25
elif team == '风暴联':
base_back = 30
base_forward = 40
elif team == '蓝月亮':
base_back = 55 # 最保守
base_forward = 20
elif team == '红魔队':
base_back = 20 # 最激进
base_forward = 50
else: # 银河队
base_back = 40
base_forward = 35
for r in range(1, rounds + 1):
# 添加随机波动,模拟真实比赛变化
back_passes = int(np.random.normal(base_back, 5))
forward_passes = int(np.random.normal(base_forward, 4))
lateral_passes = int(np.random.normal(20, 3))
# 确保传球数不为负
back_passes = max(back_passes, 5)
forward_passes = max(forward_passes, 5)
lateral_passes = max(lateral_passes, 5)
total_passes = back_passes + forward_passes + lateral_passes
data.append({
'球队': team,
'轮次': r,
'回传次数': back_passes,
'向前传球': forward_passes,
'横向传球': lateral_passes,
'总传球': total_passes
})
df = pd.DataFrame(data)
print("原始数据概览(前10行):")
print(df.head(10))
# ------------------- 2. 特征工程:计算保守程度指标 -------------------
df['回传占比'] = df['回传次数'] / df['总传球'] * 100
df['回传/向前比'] = df['回传次数'] / df['向前传球']
print("\n--- 包含保守指标的数据 ---")
print(df[['球队', '轮次', '回传次数', '总传球', '回传占比', '回传/向前比']].head(10))
# ------------------- 3. 分析汇总 -------------------
# 3.1 各球队的场均指标(保守程度排名)
team_stats = df.groupby('球队').agg(
场均回传=('回传次数', 'mean'),
场均总传球=('总传球', 'mean'),
平均回传占比=('回传占比', 'mean'),
平均回传向前比=('回传/向前比', 'mean')
).reset_index()
# 按回传占比降序排列(越保守排名越前)
team_stats_sorted = team_stats.sort_values('平均回传占比', ascending=False)
print("\n=== 球队保守程度排名(按回传占比) ===")
print(team_stats_sorted.to_string(index=False))
# 3.2 识别最保守和最激进的球队
most_conservative = team_stats_sorted.iloc[0]['球队']
most_aggressive = team_stats_sorted.iloc[-1]['球队']
print(f"\n最保守球队: {most_conservative} (回传占比: {team_stats_sorted.iloc[0]['平均回传占比']:.1f}%)")
print(f"最激进球队: {most_aggressive} (回传占比: {team_stats_sorted.iloc[-1]['平均回传占比']:.1f}%)")
# ------------------- 4. 可视化呈现 -------------------
fig, axes = plt.subplots(2, 2, figsize=(14, 10))
# 4.1 各球队回传占比箱线图(离散程度+中位数)
sns.boxplot(data=df, x='球队', y='回传占比', palette='viridis', ax=axes[0, 0])
axes[0, 0].set_title('各球队回传占比分布(越高越保守)')
axes[0, 0].set_ylabel('回传占比(%)')
axes[0, 0].tick_params(axis='x', rotation=15)
# 4.2 回传占比趋势图(随时间变化)
for team in teams:
team_data = df[df['球队'] == team]
axes[0, 1].plot(team_data['轮次'], team_data['回传占比'], marker='o', label=team)
axes[0, 1].set_title('各球队保守程度随轮次变化趋势')
axes[0, 1].set_xlabel('轮次')
axes[0, 1].set_ylabel('回传占比(%)')
axes[0, 1].legend()
axes[0, 1].grid(True, linestyle='--', alpha=0.6)
# 4.3 回传次数 vs 向前传球散点图(每个点代表一场比赛)
colors = {'勇士FC': 'blue', '风暴联': 'green', '蓝月亮': 'purple', '红魔队': 'red', '银河队': 'orange'}
for team in teams:
team_data = df[df['球队'] == team]
axes[1, 0].scatter(team_data['回传次数'], team_data['向前传球'],
c=colors[team], label=team, alpha=0.7, s=80)
# 添加对角线(回传=向前)
max_val = df[['回传次数', '向前传球']].max().max()
axes[1, 0].plot([0, max_val], [0, max_val], 'k--', label='回传=向前')
axes[1, 0].set_xlabel('回传次数')
axes[1, 0].set_ylabel('向前传球次数')
axes[1, 0].set_title('回传 vs 向前传球(点越靠近左上角越保守)')
axes[1, 0].legend()
axes[1, 0].grid(True)
# 4.4 回传/向前比条形图
axes[1, 1].bar(team_stats_sorted['球队'], team_stats_sorted['平均回传向前比'],
color=['darkred', 'red', 'orange', 'lightgreen', 'green'])
axes[1, 1].set_title('平均回传/向前比(越大越保守)')
axes[1, 1].set_ylabel('比值')
axes[1, 1].tick_params(axis='x', rotation=15)
plt.tight_layout()
plt.show()
# ------------------- 5. 进阶分析(可选) -------------------
print("\n--- 进阶洞察 ---")
# 找出轮次回传占比最高的比赛(极端保守案例)
extreme_conserv = df.loc[df['回传占比'].idxmax()]
print(f"最保守的单场比赛: {extreme_conserv['球队']} 第{extreme_conserv['轮次']}轮, "
f"回传占比: {extreme_conserv['回传占比']:.1f}%, "
f"回传/向前比: {extreme_conserv['回传/向前比']:.2f}")
# 找出轮次回传占比最低的比赛(极端激进案例)
extreme_aggressive = df.loc[df['回传占比'].idxmin()]
print(f"最激进的单场比赛: {extreme_aggressive['球队']} 第{extreme_aggressive['轮次']}轮, "
f"回传占比: {extreme_aggressive['回传占比']:.1f}%, "
f"回传/向前比: {extreme_aggressive['回传/向前比']:.2f}")
代码运行结果解读
运行上述代码,你将看到:
-
控制台输出(示例):
- 球队保守程度排名表,显示每支球队的场均回传占比。
- “蓝月亮”可能是最保守的(回传占比最高),“红魔队”是最激进的。
- 极端单场比赛案例。
-
可视化图表(Key Insights):
- 箱线图: 展示每支球队5场比赛的回传占比分布,中位数越高,球队越保守;箱子越宽,风格波动越大。
- 趋势图: 观察各队风格是否稳定,有的球队可能始终保守,有的可能根据对手或比分调整战术(例如领先时回传增多,变得保守)。
- 散点图: 每个点代表一场比赛。点越靠近左上角(回传多,向前少),说明该队在这场比赛越保守。点越靠近右下角,越激进。
- 柱状图: 直观对比各队的
回传/向前比,比值大于1意味着回传比向前传球还多,这是非常保守的体现。
深入讨论:为什么要用“占比”而非“次数”?
- 绝对次数(回传次数) 容易受球队总控球时间或比赛节奏影响,一支全场控球70%的球队,各项传球数自然都高。
- 回传占比 和 回传/向前比 是风格指标,它们揭示了在球队所有传球选择中,有多少比例是偏向安全的,这能更准确地反映“保守程度”。
扩展应用(真实场景)
如果要用真实比赛数据,你可以通过以下方式获取:
- StatsBomb 开源数据: 包含详细的传球事件(x, y坐标),可以精确判断方向。
- WhoScored / Opta API: 专业体育数据提供商。
- Web Scraping: 从一些体育数据网站(如Understat、FBref)爬取。
真实场景的进阶分析:
- 区域分析: 统计在后场(本方半场)的回传次数 vs 前场。
- 球员分析: 中后卫和防守型中场的回传占比通常极高,而边锋的前插传球多,通过
df.groupby('球员')可以对比不同位置的保守程度。 - 上下文分析: 结合“控球率”、“比分状态”、“对手强度”进行多变量分析(当球队领先时,回传占比平均上升10%)。
通过Python对回传次数进行统计和可视化,可以非常有效地量化一支球队或球员的决策倾向(是否愿意冒险),从而评估其“保守程度”,这是一个典型的“数据驱动体育分析”案例。