python案例统计门前抢点射门次数对比?

wen python案例 2

Python案例:统计门前抢点射门次数对比

下面用一个完整的案例,演示如何统计不同球员/球队门前抢点射门次数并做对比分析。

python案例统计门前抢点射门次数对比?

数据准备

假设我们有一份足球赛事事件数据(CSV 格式),字段如下:

字段 说明
match_id 比赛ID
player 球员姓名
team 球队
event_type 事件类型(shot/goal/pass...)
shot_type 射门方式(抢点/远射/头球/点球...)
x, y 射门位置坐标

示例数据 shots.csv:

match_id,player,team,event_type,shot_type,x,y
1,武磊,上海海港,shot,抢点,88,45
1,武磊,上海海港,shot,抢点,90,50
1,奥斯卡,上海海港,shot,远射,70,40
2,武磊,上海海港,shot,抢点,85,48
2,张玉宁,北京国安,shot,抢点,89,52
2,张玉宁,北京国安,shot,头球,86,50
3,张玉宁,北京国安,shot,抢点,87,49
3,莱昂纳多,山东泰山,shot,抢点,91,47
4,莱昂纳多,山东泰山,shot,抢点,88,46
4,莱昂纳多,山东泰山,shot,远射,65,35

完整代码

import pandas as pd
import matplotlib.pyplot as plt
# ---------- 1. 设置中文显示 ----------
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
# ---------- 2. 读取数据 ----------
df = pd.read_csv('shots.csv')
# ---------- 3. 筛选"门前抢点"射门 ----------
# 只保留 shot 事件 + 抢点方式
grab_shots = df[(df['event_type'] == 'shot') & (df['shot_type'] == '抢点')]
# ---------- 4. 按球员统计抢点次数 ----------
player_grab = (
    grab_shots.groupby('player')
    .size()
    .reset_index(name='抢点次数')
    .sort_values('抢点次数', ascending=False)
)
# ---------- 5. 按球队统计抢点次数 ----------
team_grab = (
    grab_shots.groupby('team')
    .size()
    .reset_index(name='抢点次数')
    .sort_values('抢点次数', ascending=False)
)
# ---------- 6. 对比:抢点射门 vs 总射门 ----------
total_shots = df[df['event_type'] == 'shot'].groupby('player').size().rename('总射门')
grab_count  = grab_shots.groupby('player').size().rename('抢点射门')
compare = pd.concat([total_shots, grab_count], axis=1).fillna(0)
compare['抢点占比(%)'] = (compare['抢点射门'] / compare['总射门'] * 100).round(1)
compare = compare.sort_values('抢点射门', ascending=False)
print("==== 球员抢点射门统计 ====")
print(player_grab)
print("\n==== 球队抢点射门统计 ====")
print(team_grab)
print("\n==== 抢点 vs 总射门对比 ====")
print(compare)
# ---------- 7. 可视化 ----------
fig, axes = plt.subplots(1, 2, figsize=(14, 5))
# 图1:球员抢点次数柱状图
axes[0].bar(player_grab['player'], player_grab['抢点次数'], color='#E63946')
axes[0].set_title('各球员门前抢点射门次数')
axes[0].set_ylabel('次数')
for i, v in enumerate(player_grab['抢点次数']):
    axes[0].text(i, v + 0.05, str(v), ha='center')
# 图2:球员抢点 vs 总射门(分组柱状图)
x = range(len(compare))
axes[1].bar([i - 0.2 for i in x], compare['总射门'], width=0.4, label='总射门', color='#457B9D')
axes[1].bar([i + 0.2 for i in x], compare['抢点射门'], width=0.4, label='抢点射门', color='#E63946')
axes[1].set_xticks(list(x))
axes[1].set_xticklabels(compare.index)
axes[1].set_title('球员抢点射门 vs 总射门')
axes[1].legend()
plt.tight_layout()
plt.savefig('grab_shot_compare.png', dpi=150)
plt.show()

输出结果示例

==== 球员抢点射门统计 ====
      player  抢点次数
0       武磊     3
1     张玉宁     2
2   莱昂纳多     2
3       奥斯卡     0
==== 球队抢点射门统计 ====
      team  抢点次数
0   上海海港     3
1   北京国安     2
2   山东泰山     2
==== 抢点 vs 总射门对比 ====
        总射门  抢点射门  抢点占比(%)
player
武磊       3     3    100.0
张玉宁      3     2     66.7
莱昂纳多     2     2    100.0
奥斯卡      1     0      0.0

进阶扩展

结合射门坐标判断"门前"区域

真实场景中"门前抢点"一般指在小禁区附近(x > 80, 30 < y < 55):

grab_shots = df[
    (df['event_type'] == 'shot')
    & (df['shot_type'] == '抢点')
    & (df['x'] > 80)
    & (df['y'].between(30, 55))
]

计算抢点射门转化率(进球率)

if 'is_goal' in df.columns:
    grab_df = df[(df['shot_type'] == '抢点')]
    conv = grab_df.groupby('player')['is_goal'].agg(['sum', 'count'])
    conv['转化率(%)'] = (conv['sum'] / conv['count'] * 100).round(1)
    print(conv)

多赛季 / 多球队横向对比(热力图)

import seaborn as sns
pivot = df.pivot_table(
    index='player',
    columns='team',
    values='shot_type',
    aggfunc=lambda s: (s == '抢点').sum(),
    fill_value=0,
)
sns.heatmap(pivot, annot=True, cmap='Reds', fmt='g')'球员在各队的抢点射门次数')
plt.show()

小结

步骤 关键 API
筛选抢点射门 df[(df['shot_type']=='抢点')]
分组统计 groupby().size()
对比占比 concat + 除法
可视化对比 matplotlib bar / seaborn heatmap

这个案例可以按需接入真实的 StatsBomb / Opta / 中超官方数据,把 shot_type 替换成实际字段即可复用。

需要我把它改成接入 StatsBomb 开放数据的版本,或者做成网页交互式图表(Plotly)吗?

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

友情链接攻略窝 · 礼包窝 · 配置窝 · 换算窝 · 算法窝 · 查文窝 · 手册窝 · 问答窝 · 全文搜 · 手册库
相关站点礼包窝 · 查文窝