前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >分析梅西和罗纳尔多的比赛数据

分析梅西和罗纳尔多的比赛数据

作者头像
老齐
发布2020-06-23 14:46:44
7580
发布2020-06-23 14:46:44
举报
文章被收录于专栏:老齐教室老齐教室
作者:Adil Moujahid

翻译:老齐


2003年,迈克尔·刘易斯出版了《点球成金》,这是一本关于比利·比恩的书,他是奥克兰运动家棒球队队的总经理,他将统计分析应用于棒球,以确定和招募被低估的棒球运动员。通过数据的运用,比利·比恩所取得的胜利与薪资水平翻倍的球队一样多,并且从2000年到2003年连续4年参加了附加赛。

2011年,《点球成金》被改编成电影,由布拉德·皮特饰演比利·比恩。这本书和这部电影都很成功,极大地促进了利用数据提高比赛成绩的理念。对体育数据进行分析,进而提交竞技比赛成绩,通常称之为体育分析(Sport analytics)。

在棒球中,这项运动的性质使得收集大量关于比赛中的数据点比较容易。你可以从这个链接下载数据(http://www.seanlahman.com/baseball-archive/statistics/),其中包含了自1871年以来的关于球员和球队的比赛数据和其他统计数据。如果你对分析棒球数据感兴趣,你可以本微信公众号关注相关的文章。

然而,收集足球数据就变得复杂多了。在足球场上,22个队员无时不刻不在运动中,他们在球场上的位置和移动路径的可能可以说有无穷种,幸运的是,在这几年里,随着传感器技术和视频分析技术的进步,获得高质量的足球比赛数据也称为了可能,从而可以利用这些数据对比赛、球队和球员的情况进行分析。在本文中,我们将使用公开的足球数据集,分析梅西和罗纳尔多在2017-2018赛季中的有关数据,并为此开发一个网页,在网页上,我们以交互的方式来比较这两名球员在场上的位置。

非常感谢Luca Pappalardo博士(https://lucapappalardo.com/)和他的同事们,感谢他们为公众提供了这么伟大的数据集。

下面的动画,就是这个应用的简单演示,你可以到github仓库中得到源码(https://github.com/adilmoujahid/streamlit-messi-ronaldo)。

1. 数据准备

过去十年里,梅西和罗纳尔多共获得11个金球奖(梅西6个,罗纳尔多5个),可以说统治当时的世界足球。这两位球员都被认为是有史以来最伟大的球员之一,所以也经常被拿来比较。

我们将分析这两位球员在2017-2018赛季西班牙联赛中的表现,这是罗纳尔多转会尤文图斯之前在西班牙的最后一个赛季。

1.1 获取数据

首先,我们要下载有关数据集,下载地址是:https://figshare.com/collections/Soccer_match_event_dataset/4415000/5。然后关注如下部分:

  • matches/matches_Spain.json: 西班牙联赛2017-18赛季有关信息。
  • events/events_Spain.json: 西班牙联赛2017-18赛季中每场比赛的所有事件。
  • players.json: 参加了7场国际国内重要比赛的所有球员(意大利、西班牙、发过、德国和英超联赛,2018年世界杯,2016年欧洲杯)。
  • teams.json: 参加了7场国际国内重要比赛的所有球队。
  • tags2name.csv: 标记符和标记名称的对应关系

1.2 读入数据

下面是我们使用的Python库:

代码语言:javascript
复制
import json
import unicodedata
import numpy as np
import pandas as pd

然后从players.json文件,根据id读入两个球员的数据:

  • 梅西的id是3359
  • 罗纳尔多的id是3322

再从teams.json文件中根据id找到他们所在的球队:

  • 巴塞罗那的id是676
  • 皇家马德里的id是675

接下来读入西班牙联赛的比赛数据:

代码语言:javascript
复制
with open('../data/matches/matches_Spain.json') as json_file:
    matches_spain_data = json.load(json_file)

with open('../data/events/events_Spain.json') as json_file:
    events_spain_data = json.load(json_file)

1.3 构造数据

从前述数据中,分别得到皇家马德里和巴塞罗那两个俱乐部的比赛信息。

代码语言:javascript
复制
barca_matches  = [match for match in matches_spain_data if '676' in match['teamsData'].keys()]
real_matches  = [match for match in matches_spain_data if '675' in match['teamsData'].keys()]

将它们转化为DataFrame对象。

代码语言:javascript
复制
barca_matches_df = pd.DataFrame(barca_matches)
real_matches_df = pd.DataFrame(real_matches)
代码语言:javascript
复制
barca_matches_df.head(2)

输出:

代码语言:javascript
复制
  status  roundId  gameweek  teamsData  seasonId  dateutc  winner  venue  wyId  label  date  referees  duration  competitionId
0  Played  4406122  38  {'676': {'scoreET': 0, 'coachId': 92894, 'side...  181144  2018-05-20 18:45:00  676  Camp Nou  2565922  Barcelona - Real Sociedad, 1 - 0  May 20, 2018 at 8:45:00 PM GMT+2  [{'refereeId': 398931, 'role': 'referee'}, {'r...  Regular  795
1  Played  4406122  37  {'676': {'scoreET': 0, 'coachId': 92894, 'side...  181144  2018-05-13 18:45:00  695  Estadio Ciudad de Valencia  2565917  Levante - Barcelona, 5 - 4  May 13, 2018 at 8:45:00 PM GMT+2  [{'refereeId': 420995, 'role': 'referee'}, {'r...  Regular  795

接下来,将梅西和罗纳尔多的有关数据,也生成为DataFrame。

代码语言:javascript
复制
messi_events_data = []
for event in events_spain_data:
    if event['playerId'] == 3359:
        messi_events_data.append(event)
        
messi_events_data_df = pd.DataFrame(messi_events_data)

ronaldo_events_data = []
for event in events_spain_data:
    if event['playerId'] == 3322:
        ronaldo_events_data.append(event)

ronaldo_events_data_df = pd.DataFrame(ronaldo_events_data)

tags2name.csv中选择我们需要的时间标签:

  • 101: Goal(进球)
  • 301: Assist(助攻)
  • 302: key Pass (关键传球)
  • 401: Left Foot(左脚)
  • 402: Right Foot(右脚)

将这些标签加入到DataFrame中作为一列。

代码语言:javascript
复制
def add_tag(tags, tag_id):
    return tag_id in [tag['id'] for tag in tags]
    
 messi_events_data_df.columns

输出:

代码语言:javascript
复制
Index(['eventId', 'subEventName', 'tags', 'playerId', 'positions', 'matchId',
       'eventName', 'teamId', 'matchPeriod', 'eventSec', 'subEventId', 'id'],
      dtype='object')
代码语言:javascript
复制
messi_events_data_df['goal'] = messi_events_data_df['tags'].apply(lambda x: add_tag(x, 101))
messi_events_data_df['assist'] = messi_events_data_df['tags'].apply(lambda x: add_tag(x, 301))
messi_events_data_df['key_pass'] = messi_events_data_df['tags'].apply(lambda x: add_tag(x, 302))
messi_events_data_df['left_foot'] = messi_events_data_df['tags'].apply(lambda x: add_tag(x, 401))
messi_events_data_df['right_foot'] = messi_events_data_df['tags'].apply(lambda x: add_tag(x, 402))

ronaldo_events_data_df['goal'] = ronaldo_events_data_df['tags'].apply(lambda x: add_tag(x, 101))
ronaldo_events_data_df['assist'] = ronaldo_events_data_df['tags'].apply(lambda x: add_tag(x, 301))
ronaldo_events_data_df['key_pass'] = ronaldo_events_data_df['tags'].apply(lambda x: add_tag(x, 302))
ronaldo_events_data_df['left_foot'] = ronaldo_events_data_df['tags'].apply(lambda x: add_tag(x, 401))
ronaldo_events_data_df['right_foot'] = ronaldo_events_data_df['tags'].apply(lambda x: add_tag(x, 402))

messi_events_data_df.head(2)

输出:

代码语言:javascript
复制
  eventId  subEventName  tags  playerId  positions  matchId  eventName  teamId  matchPeriod  eventSec  subEventId  id  goal  assist  key_pass  left_foot  right_foot
0  8  Simple pass  [{'id': 1801}]  3359  [{'y': 50, 'x': 50}, {'y': 50, 'x': 40}]  2565554  Pass  676  1H  1.012047  85  180465950  False  False  False  False  False
1  8  Simple pass  [{'id': 1801}]  3359  [{'y': 64, 'x': 71}, {'y': 67, 'x': 54}]  2565554  Pass  676  1H  51.068905  85

把前面关于比赛的信息也合并过来。

代码语言:javascript
复制
messi_events_data_df = pd.merge(messi_events_data_df, barca_matches_df, left_on='matchId', right_on='wyId', copy=False, how="left")

ronaldo_events_data_df = pd.merge(ronaldo_events_data_df, real_matches_df, left_on='matchId', right_on='wyId', copy=False, how="left")

保存数据。

代码语言:javascript
复制
messi_events_data_df.to_pickle('../data/messi_events_data_df.pkl')
ronaldo_events_data_df.to_pickle('../data/ronaldo_events_data_df.pkl')

接下来,还要讲皇家马德里和巴塞罗那两只球队在2017-18赛季的比赛相关数据读取出来。

代码语言:javascript
复制
barca_matches_dates_df = barca_matches_df[['label', 'date']].copy()
real_matches_dates_df = real_matches_df[['label', 'date']].copy()

barca_matches_dates_df['date'] = pd.to_datetime(barca_matches_df['date'], utc=True).dt.date
real_matches_dates_df['date'] = pd.to_datetime(real_matches_df['date'], utc=True).dt.date

#Change date to string 
barca_matches_dates_df['date'] = barca_matches_dates_df['date'].apply(lambda x: x.strftime('%Y-%m-%d'))
real_matches_dates_df['date'] = real_matches_dates_df['date'].apply(lambda x: x.strftime('%Y-%m-%d'))

barca_matches_dates_df = barca_matches_dates_df.rename(columns={"label": "match"})
real_matches_dates_df = real_matches_dates_df.rename(columns={"label": "match"})

barca_matches_dates_df.head(2)

输出:

代码语言:javascript
复制
                               match  date
0  Barcelona - Real Sociedad, 1 - 0  2018-05-20
1        Levante - Barcelona, 5 - 4  2018-05-13

也保存一下。

代码语言:javascript
复制
barca_matches_dates_df.to_pickle('../data/barca_matches_dates_df.pkl')
real_matches_dates_df.to_pickle('../data/real_matches_dates_df.pkl')

2. 分析数据

在这部分,要分析梅西和罗纳尔多在球场上的表现数据了,我们会利用一些统计分析,以可视化的方式表现他们在球场上的状况。

球员的行为统计。

代码语言:javascript
复制
goals = [messi_events_data_df['goal'].sum(), ronaldo_events_data_df['goal'].sum()]
assists = [messi_events_data_df['assist'].sum(), ronaldo_events_data_df['assist'].sum()]
shots = [messi_events_data_df[messi_events_data_df['eventName'] == 'Shot'].count()['eventName'],
         ronaldo_events_data_df[ronaldo_events_data_df['eventName'] == 'Shot'].count()['eventName']]
free_kicks = [messi_events_data_df[messi_events_data_df['subEventName'] == 'Free kick shot'].count()['subEventName'], 
              ronaldo_events_data_df[ronaldo_events_data_df['subEventName'] == 'Free kick shot'].count()['subEventName']]
passes = [messi_events_data_df[messi_events_data_df['eventName'] == 'Pass'].count()['eventName'],
          ronaldo_events_data_df[ronaldo_events_data_df['eventName'] == 'Pass'].count()['eventName']]

stats_df = pd.DataFrame([goals, assists, shots, free_kicks, passes], 
                        columns=['Messi', 'Ronaldo'], 
                        index=['Goals', 'Assists', 'Shots', 'Free Kicks', 'Passes'])

print(stats_df)

左脚和右脚球比较。

代码语言:javascript
复制
messi_lf_goals = messi_events_data_df[messi_events_data_df['left_foot'] == True]['goal'].sum()
messi_rf_goals = messi_events_data_df[messi_events_data_df['right_foot'] == True]['goal'].sum()

print("Messi's goals with left foot: ", messi_lf_goals)
print("Messi's goals with right foot: ", messi_rf_goals)

# 输出:
Messi's goals with left foot:  32
Messi's goals with right foot:  2
代码语言:javascript
复制
ronaldo_lf_goals = ronaldo_events_data_df[ronaldo_events_data_df['left_foot'] == True]['goal'].sum()
ronaldo_rf_goals = ronaldo_events_data_df[ronaldo_events_data_df['right_foot'] == True]['goal'].sum()

print("Ronaldo's goals with left foot: ", ronaldo_lf_goals)
print("Ronaldo's goals with right foot: ", ronaldo_rf_goals)

# 输出:
Ronaldo's goals with left foot:  7
Ronaldo's goals with right foot:  14

两个球员在球场上的有关数据都保存在了messi_events_data_dfronaldo_events_data_df中,我们可以创建一个坐标写,两个坐标轴的范围都是[0, 100],表示占进攻一方场上的百分比,下面用可视化方式展示。

代码语言:javascript
复制
messi_events_data_df['positions'].head()

输出:

代码语言:javascript
复制
from plots import *
from bokeh.io import output_notebook
from bokeh.plotting import figure, show
output_notebook()

在这里,使用了bokeh可视化模块,涉及到两个简单的函数:

  • draw_pitch():绘制空图的函数
  • plot_events(player_events, event_name, plot_color):输入DataFrame的数据,实现数据可视化。

函数的源码,可以通过连接得到(https://github.com/adilmoujahid/streamlit-messi-ronaldo/blob/master/plots.py)

代码语言:javascript
复制
messi_goals = messi_events_data_df[messi_events_data_df['goal'] == True]['positions']
代码语言:javascript
复制
p_messi = plot_events(messi_goals, 'Goals', 'red')
代码语言:javascript
复制
show(p_messi)

注:如果在调试环境中,会得到动态图示,这里显示的是截图效果。

3. 创建web应用

现在我们知道了如何读取、构造和绘制数据,下面可以开始创建web应用。这个应用的目标是比较梅西和罗纳尔多的比赛,集中在进球、助攻、射门、任意球和传球。

每个动作类型都有一个标签,在选项卡中,我们将显示各种动作的统计数据和位置,分解按比赛计数。该应用还将有一个过滤器,可以使用它来选择左、右脚的动作。

开发中,利用一个开源的框架Streamlit(https://www.streamlit.io/),它是Python中的一个库,可以用pip install安装。Streamlit可以很容实现一个web应用,只需要使用Python,不需要HTML/CSS/JS等代码。

你可以在本项目的代码仓库中下载应用源码,然后在本地执行streamlit run app.py将项目运行起来,并在浏览器打开http://localhost:8501查看效果。

最后

本文,我们分析了梅西和罗纳尔多的有关数据,你其实可以参考本文内容,继续分析其他球员、球队或者每场比赛。

原文链接:http://adilmoujahid.com/posts/2020/06/streamlit-messi-ronaldo/

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-06-18,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 老齐教室 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 数据准备
    • 1.1 获取数据
      • 1.2 读入数据
        • 1.3 构造数据
        • 2. 分析数据
        • 3. 创建web应用
        • 最后
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档