本文目录导读:
- 📑 目录导读
- 为什么用Python分析足球射门数据?
- 数据准备:从哪获取禁区内外射门数据?
- 核心代码实现:统计、清洗与聚合
- 可视化对比:禁区内外射门的效率差异
- 进阶延伸:结合机器学习预测射门转化率
- 常见问题解答(FAQ)
Python实战:用数据科学统计足球禁区内外射门次数——完整代码与可视化案例**
📑 目录导读
- 为什么用Python分析足球射门数据?
- 数据准备:从哪获取禁区内外射门数据?
- 核心代码实现:统计、清洗与聚合
- 可视化对比:禁区内外射门的效率差异
- 进阶延伸:结合机器学习预测射门转化率
- 常见问题解答(FAQ)
为什么用Python分析足球射门数据?
在现代足球 analytics 领域,“禁区内外射门次数” 是最基础也最具战术价值的统计指标之一,禁区(Penalty Area)内的射门通常意味着更高的得分概率(约18%~22%),而禁区外远射的转化率往往不足5%,通过 Python 对这类数据进行批量统计和对比,可以帮助教练组优化进攻策略,也能让球迷更直观地理解比赛走向。
与手动观看录像逐帧标记不同,Python 配合 Pandas 和 Matplotlib 能在数秒内处理整个赛季数千次射门事件,并输出精确的百分比差异,这也是为什么越来越多的 sports analytics 团队将 Python 作为首选工具。
数据准备:从哪获取禁区内外射门数据?
在使用代码之前,你需要准备一份包含射门位置坐标的数据集,常见来源包括:
- StatsBomb 开放数据(GitHub 上有官方免费仓库,包含英超、西甲等赛事)
- WhoScored / Understat 的爬虫接口(注意遵守 robots 协议)
- 自定义 CSV 文件(至少包含
x和y坐标,单位通常是 0~100 的相对球场坐标)
一个标准的 CSV 数据示例格式如下:
match_id,team_name,player_name,shot_x,shot_y,is_goal 12345,Arsenal,Saka,93.5,42.1,0 12345,Chelsea,Palmer,88.2,49.8,1
shot_x 表示射门点到球门线的水平距离(0为底线,100为对方球门线),shot_y 表示相对于球场中轴线的横向距离(0为左边线,100为右边线)。判定的标准:shot_x >= 83.5 且 5 <= shot_y <= 71.5,则视为禁区内射门。
核心代码实现:统计、清洗与聚合
以下是一个可直接运行的 Python 脚本,它读取 CSV 文件,自动标记射门区域,并输出对比结果。
import pandas as pd
import matplotlib.pyplot as plt
# 读取数据
df = pd.read_csv('shots_data.csv')
# 定义禁区判断函数(基于相对坐标)
def is_inside_box(x, y):
# 标准球场宽度为100,高度为100;禁区范围:x>=83.5, 28.5<=y<=71.5
return (x >= 83.5) and (28.5 <= y <= 71.5)
# 应用函数生成新列
df['area'] = df.apply(lambda row: 'Inside' if is_inside_box(row['shot_x'], row['shot_y']) else 'Outside', axis=1)
# 统计次数与进球数
stats = df.groupby('area').agg(
total_shots=('shot_x', 'count'),
goals=('is_goal', 'sum')
).reset_index()
# 计算转化率
stats['conversion_rate'] = (stats['goals'] / stats['total_shots'] * 100).round(2)
print(stats)
输出示例:
| area | total_shots | goals | conversion_rate |
|---|---|---|---|
| Inside | 320 | 61 | 06 |
| Outside | 185 | 7 | 78 |
可视化对比:禁区内外射门的效率差异
单纯的数据表格不够直观,我们使用 Matplotlib 绘制柱状图与散点热力图。
# 绘制转化率柱状图
fig, ax = plt.subplots(figsize=(8,5))
bars = plt.bar(stats['area'], stats['conversion_rate'], color=['#d32f2f', '#1976d2'])
plt.ylabel('Conversion Rate (%)')'Shot Conversion Rate: Inside vs Outside the Box')
# 添加数值标签
for bar in bars:
height = bar.get_height()
plt.text(bar.get_x() + bar.get_width()/2., height + 0.5, f'{height:.1f}%', ha='center')
plt.tight_layout()
plt.show()

你还可以用 scatter 绘制所有射门的坐标分布,红色为禁区外,蓝色为禁区内,能直观看出密集区域与得分点的空间关系。
进阶延伸:结合机器学习预测射门转化率
当你掌握了基础统计后,可以进一步训练一个逻辑回归模型,输入特征包括:射门角度、距球门距离、是否禁区、是否头球等,输出该次射门的得分概率,核心代码只用4行:
from sklearn.linear_model import LogisticRegression
X = df[['shot_x', 'shot_y']] # 简化特征,实际可加更多
y = df['is_goal']
model = LogisticRegression().fit(X, y)
print(f'Feature coefficients: {model.coef_}')
这样你的文章就从“统计次数”升级到了“预测概率”,极大提高内容深度与SEO关键词覆盖。
常见问题解答(FAQ)
Q1:如果数据坐标是绝对距离(比如米),怎么判断禁区?
答:如果你用的是以米为单位(球场长105米,宽68米),那么禁区范围约为:距底线 16.5 米以内,且距两侧边线 20.15 米以内,换算比例判断即可。
Q2:有没有现成的Python库处理足球事件?
答:有的。StatsBombPy 和 kloppy 是专业的足球数据解析库,内置了场地坐标转换与事件过滤功能,推荐你优先使用它们。
Q3:代码中 is_inside_box 的阈值为什么是83.5?
答:因为 StatsBomb 坐标系中,球门线为x=100,而禁区线(大禁区的宽度)恰好是从球门线到罚球区的边缘距离,罚球区距球门线 16.5 米,折算成相对比例约为 100 - (16.5/105)*100 ≈ 84.3,取近似值 83.5 是为了留出误差容限。
通过 Python 对禁区内外射门次数进行统计对比,不仅仅是一个简单的计数,而是战术洞察的开端,从数据清洗到可视化,再到机器学习预测,这条技术路径能帮助数据分析师和足球爱好者挖掘更深的比赛规律,希望本文的代码能成为你下一个 sports analytics 项目的坚实基础。
如果你觉得有用,欢迎收藏本文,并在评论区告诉我你想分析的另一项足球数据(比如传球成功率、跑动距离),我会继续更新 Python 实现案例。