足球数据在python中的应用(1)

文章讲述了如何使用Statsbomb的Python包statsbombpy获取并分析足球比赛的深度数据,包括世界杯比赛,如2018年法国对阵阿根廷的赛事。通过爬虫和数据可视化,揭示比赛中的战术和球员表现。
摘要由CSDN通过智能技术生成
  • 前言

每一分钟的足球比赛都孕育着能够激发人们高品质洞察力的数据,这些数据可以用于球员招募、比赛分析,并帮助教练做出更明智的决策。然而,遗憾的是,目前大多数免费的在线数据集仅包含基本统计信息,如积分、球队名称和比赛日期。仅凭这些基本统计数据,我们无法获得太多有价值的信息。为了获取更深入的统计数据,可以尝试进行爬虫,但是要花费大量的时间,所以我们可以探索一些免费分享的数据。在本文中,我们将探索Statsbomb在其Python包statsbombpy中分享的所有免费足球数据。这些数据将让我们深入了解比赛,解析在数字背后的足球故事。不再是些基础统计数据,我们将能够探索足球世界的布局,挖掘球员的精彩瞬间,揭示精彩的奥妙。让我们一起探索这些数据,为你对足球理解注入新的能量。接下来,让我们开始启程。

准备工作

1.1安装statsbombpy

获取Statsbomb分享的所有足球数据,我们需要安装statsbombpy

pip install statsbombpy

1.2导入statsbombpy

安装之后,我们将其导入

from statsbombpy import sb

1.3查看免费比赛

查看 Statsbomb 免费分享的所有比赛,您只需运行sb.competition()

competitions=sb.competitions()

如果仅显示比赛,也可以在country_namecompetition_name列中删除重复项。

sb.competitions().drop_duplicates(['country_name', 'competition_name'])

运行结果


我们可以看到,Statsbomb的免费数据有世界杯、欧冠、西甲、英超等联赛。如果想获取Statsbomb 有更多的比赛数据,只有付费购买,通过 API 访问来获取。OK,接下来让我们探索一下数据集中提供的比赛数据:2018 年世界杯!

探索数据

2.1查找数据

要探索 2018 年世界杯的数据,我们将需要competition_idseason_id。从提供的信息来看,2018年世界杯的competition_id是43,对应的competition_id是3

WorldCup_2018 = sb.matches(competition_id=43, season_id=3)
WorldCup_2018.head(5)

运行结果


2.2探索2018年世界杯

该WorldCup_2018数据框包含 22 列,为我们足球分析提供了良好的基础。为了获得有关特定比赛的更多信息,我们将需要match_id很遗憾小编是意大利球迷在2018年世界杯并没有看到他们的身影,但是对足球的热爱仍在继续。接下来我们查询2018 年世界杯淘汰赛法国队与阿根廷队的比赛 ,ID 为 7580。

WorldCup_2018_FRA_ARG = 7580
FRA_ARG=WorldCup_2018[WorldCup_2018['match_id']==WorldCup_2018_FRA_ARG]

 

运行结果


结果显示7580是该比赛的id,现在让我们来看看这场惊心动魄的比赛发生了什么事情吧!

2.2.1查看比赛阵容

我们来看看法国vs阿根廷的阵容吧!

lineups = sb.lineups(match_id=7580)

当我们查看lineups的数据类型是会发现他是字典( dict)。所以我们打印他的键(key)列表。

lineups.keys()
Out[23]: dict_keys(['France', 'Argentina'])

下一步我们通过键(key)来了解两队的阵容

法国队

France_lineups=lineups['France']

结果显示


阿根廷队

Argentina_lineups=lineups['Argentina']

结果显示


2.2.2查看比赛事件

如果想要查看比赛事件,我们需要再次查看比赛的id。

FRA_ARG_events = sb.events(match_id=7580)

让我们看看FRA_ARG_events的所有列吧!

FRA_ARG_events_columns=FRA_ARG_events.columns

运行结果


我们可以看到这个数据集中有很多信息。让我们选择几个重要的列,并对minutes和timestamp列进行排序。

FRA_ARG_df_events=FRA_ARG_events[['timestamp','team', 'type', 'minute', 'location', 'pass_end_location', 'player']]
FRA_ARG_df_events=FRA_ARG_events.sort_values(['minute', 'timestamp'])

让我们看看比赛最后时刻发什么了什么事情吧!

FRA_ARG_df_events_tail=FRA_ARG_df_events.tail(15)

运行结果


python可视化

现在到最激动人心的时候了,我们将数据可视化,首先我们开始做些准备工作!

3.1准备工作

为了方便查找数据以及可视化操作,我们安装mplsoccer库

pip install mplsoccer

接下来就是导入相关的库

import matplotlib.pyplot as plt
import numpy as np
from mplsoccer import Pitch, Sbopen
import pandas as pd

3.2计算球员的平均位置和传球次数

思路:计算每个球员的平均位置和传球次数,在遍历球员列表,合并传球坐标,然后算出平均坐,并计算传球数量。

players = df_pass["player_name"].unique()
scatter_data = [{
    "player_name": name,
    "x": np.mean(np.concatenate([df_pass.loc[df_pass["player_name"] == name, "x"].to_numpy(),
                                 df_pass.loc[df_pass["pass_recipient_name"] == name, "end_x"].to_numpy()])),
    "y": np.mean(np.concatenate([df_pass.loc[df_pass["player_name"] == name, "y"].to_numpy(),
                                 df_pass.loc[df_pass["pass_recipient_name"] == name, "end_y"].to_numpy()])),
    "no": df_pass[df_pass["player_name"] == name].shape[0]
} for name in players]

scatter_df = pd.DataFrame(scatter_data)
max_pass_no = scatter_df['no'].max()
scatter_df['marker_size'] = scatter_df['no'] / max_pass_no * 1500

查看法国队球员在第一次换人之前的传球数

pass_counts = df_pass.groupby("player_name").size()

运行结果


3.3绘制球员在球场上的散点图和球场

def draw_pitch_and_scatter(data_frame, ax, pitch_object):
    pitch_object.scatter(
        data_frame.x, data_frame.y,
        s=data_frame.marker_size,
        color='red',
        edgecolors='grey',
        linewidth=1,
        alpha=1,
        ax=ax["pitch"],
        zorder=3
    )
    for index, row in data_frame.iterrows():
        pitch_object.annotate(
            row.player_name, xy=(row.x, row.y),
            c='black',
            va='center',
            ha='center',
            weight="bold",
            size=16,
            ax=ax["pitch"],
            zorder=4
        )

运行结果


3.4绘制球员之间的连线并且与散点图结合

将数据可视化,用以球员在球场上的位置和他们之间的传球关系。

def draw_lines(lines_df, scatter_df, ax, pitch_object):
    for index, row in lines_df.iterrows():
        players = row["pair_key"].split("_")
        player1, player2 = players[0], players[1]
        player1_coords = scatter_df.loc[scatter_df["player_name"] == player1, ['x', 'y']].iloc[0]
        player2_coords = scatter_df.loc[scatter_df["player_name"] == player2, ['x', 'y']].iloc[0]
        line_width = (row["pass_count"] / lines_df['pass_count'].max() * 10)
        pitch_object.lines(
            player1_coords.x, player1_coords.y,
            player2_coords.x, player2_coords.y,
            alpha=1,
            lw=line_width,
            zorder=2,
            color="red",
            ax=ax["pitch"]
        )

运行结果


这就是法国队这场比赛(第一次换人)球员们之间的传球图,其中红线越粗他们之前的传球频率越多......

结束语

以上就是一些足球数据分析的内容,我们不仅可以可以可视化传球神经网络,还可以绘制出进攻热力图,雷达图等等,让我们在接下来的日子里慢慢来探索吧!

  • 17
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值