太酷了,Python 制作足球可视化图表 | 代码干货
作者 | 小F
来源 | 法纳斯特
大家好,我是小F。
最近不少小伙伴都会熬夜看欧洲杯。今年的欧洲杯相比起往年的欧洲杯来说,可谓是冷门频出,出乎意料。
真的不知道,第一会花落谁家~
本期小F就和大家分享一下,用Python和Matplotlib绘制一个足球运动员的数据可视化图表。
来看一下C罗的情况,跟老詹一样高龄,真的佩服。
数据来源于下面两个网站,Understat和Fbref。
链接:https://understat.com/
链接:https://fbref.com/en/
欧洲足球五大联赛,英超、意甲、西甲、德甲、法甲。
先看一下射门数据的可视化,本质上和篮球的出手点图差不多,都是散点图类型。
导入相关的Python库:
import requests
from bs4 import BeautifulSoup as soup
import json
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
import matplotlib as mpl
从Understat网站爬取射门数据,使用BeautifulSoup、JSON和pandas解析和处理数据。
# 请求数据, C罗的ID为2371
url = 'https://understat.com/player/2371'
html = requests.get(url)# 解析处理数据
parse_soup = soup(html.content, 'lxml')
scripts = parse_soup.find_all('script')
strings = scripts[3].stringind_start = strings.index("('")+2
ind_end = strings.index("')")
json_data = strings[ind_start:ind_end]
json_data = json_data.encode('utf8').decode('unicode_escape')
data = json.loads(json_data)
print(data)
# 处理数据, 包含射门位置、预期进球、射门结果、赛季
x = []
y = []
xg = []
result = []
season = []
for i, _ in enumerate(data):for key in data[i]:if key == 'X':x.append(data[i][key])if key == 'Y':y.append(data[i][key])if key == 'xG':xg.append(data[i][key])if key == 'result':result.append(data[i][key])if key == 'season':season.append(data[i][key])
columns = ['X', 'Y', 'xG', 'Result', 'Season']
df_understat = pd.DataFrame([x, y, xg, result, season], index=columns)
df_understat = df_understat.T
df_understat = df_understat.apply(pd.to_numeric, errors='ignore')
# 得到最终的结果
print(df_understat)
此处的ID,通过查询球员名字可知:
查询中国球员武磊,点击访问,在地址栏处,可以看到球员ID。
得到数据如下:
包含射门位置(x、y)、xG(预期进球)、射门结果、赛季。
其中x、y的坐标值为0~1之间,不适合在Matplotlib显示,所以选择放大100倍。
df_understat['X'] = df_understat['X'].apply(lambda x: x*100)
df_understat['Y'] = df_understat['Y'].apply(lambda x: x*100)
print(df_understat)
得到结果如下:
既然已经成功获取Understat网站的数据,就可以去获取Fbref网站的数据啦。
这里是球员的一些个人信息,以及赛季的平均数据。
比如全名、国家、位置、俱乐部、联赛、年龄、出生年份、上场时间、得分数据等等。
因为网页的数据是表格形式,所以直接使用pandas的read_html函数,解析表格爬取数据。
这个网站需要取消一下证书验证,要不然连接不成功。
# 全局取消证书验证import ssl
ssl._create_default_https_context = ssl._create_unverified_context
获取球员的相关数据:
def readfromhtml(filepath):# 选择第二个表格df = pd.read_html(filepath)[0]column_lst = list(df.columns)for index in range(len(column_lst)):column_lst[index] = column_lst[index][1]df.columns = column_lstdf.drop(df[df['Player'] == 'Player'].index, inplace=True)df = df.fillna('0')df.set_index('Rk', drop=True, inplace=True)try:df['Comp'] = df['Comp'].apply(lambda x: ' '.join(x.split()[1:]))df['Nation'] = df['Nation'].astype(str)df['Nation'] = df['Nation'].apply(lambda x: x.split()[-1])except:print('Error in uploading file:' + filepath)finally:df = df.apply(pd.to_numeric, errors='ignore')return df# 获取2020-2021欧洲五大联赛球员数据
df_fbref = readfromhtml('https://fbref.com/en/comps/Big5/shooting/players/Big-5-European-Leagues-Stats')
print(df_fbref)
得到结果如下:
数据都已经准备好了,那么我们就可以将数据绘制到图表上。
# 安装
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple mplsoccer
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple highlight_text
先安装mplsoccer、highlight_text这两个Python库。
其中mplsoccer库可以自定义绘制足球场,无需我们自己绘制场地图。
想了解更多,可以访问它的GitHub地址:
https://github.com/andrewRowlinson/mplsoccer
初始化一些设置,画布背景色、字体颜色、默认字体,字体大小,此处选择中文字体。
from highlight_text import ax_text,fig_text
import mplsoccer# 背景色
background = '#D6DBD9'
# 字体颜色
text_color = 'black'
mpl.rcParams['xtick.color'] = text_color
mpl.rcParams['ytick.color'] = text_color
mpl.rcParams['text.color'] = text_color
# 中文字体
mpl.rcParams['font.family'] = 'Songti SC'
mpl.rcParams['legend.fontsize'] = 12
新建一个画布:
# 新建画布
fig, ax = plt.subplots(figsize=(10, 8))
# 关闭坐标轴
ax.axis('off')
# 背景色填充
fig.set_facecolor(background)
plt.show()
显示如下:
绘制19-20赛季,C罗的进球情况。
# 垂直方向半个足球场
pitch = mplsoccer.VerticalPitch(half=True, pitch_type='opta', line_zorder=3, pitch_color='grass')
# 图表大小
ax_opta1 = fig.add_axes((0.05, 0.06, 0.45, 0.4))
ax_opta1.patch.set_facecolor(background)
pitch.draw(ax=ax_opta1)
plt.show()
通过设置mplsoccer的参数,绘制半个足球场。
果然,左下方有半个足球场。
将射门数据用散点图表示,分为进球得分和未成功进球得分两种情况。
# 2019-2020赛季, C罗射门位置散点图(未得分), 透明度0.6
df_fil = df_understat.loc[df_understat['Season'] == 2019]pitch.scatter(df_fil[df_fil['Result'] != 'Goal']['X'], df_fil[df_fil['Result'] != 'Goal']['Y'],s=np.sqrt(df_fil[df_fil['Result'] != 'Goal']['xG'])*100, marker='o', alpha=0.6,edgecolor='black', facecolor='grey', ax=ax_opta1)
plt.show()
未得分射门散点图:
得分散点图:
# 2019-2020赛季, C罗射门位置散点图(得分), 透明度0.9
pitch.scatter(df_fil[df_fil['Result'] == 'Goal']['X'], df_fil[df_fil['Result'] == 'Goal']['Y'],s=np.sqrt(df_fil[df_fil['Result'] == 'Goal']['xG'])*100, marker='o', alpha=0.9,edgecolor='black', facecolor='#6778d0', ax=ax_opta1, label='Goal')plt.show()
结果如下,失败的比成功的多。
这样,我们就将C罗在2019-2020赛季的所有射门点数据可视化出来了。
其中散点的大小,是预期进球的大小。
添加标签及图例,设置相应的位置、文字、字体等设置。
# 添加图例
ax_opta1.legend(loc='lower right').get_texts()[0].set_color("black")# 文字信息
ax_opta1.text(30, 61, '得分次数 : '+str(len(df_fil[df_fil['Result'] == 'Goal'])), weight='bold', size=11)
ax_opta1.text(30, 64, f"预期进球 : {round(sum(df_fil['xG']),2)}", weight='bold', size=11)
ax_opta1.text(30, 58, '射门次数 : '+str(len(df_fil)), weight='bold', size=11)
ax_opta1.text(90, 60, '2019-20赛季', weight='bold', size=14)plt.show()
成功添加附加信息:
显示赛季、xG、得分次数、射门次数信息。
同样将20-21赛季的数据绘制出来,放置在19-20赛季的右侧。
# 2020-2021赛季, C罗射门位置散点图
ax_opta2 = fig.add_axes((0.50, 0.06, 0.45, 0.4))
ax_opta2.patch.set_facecolor(background)
pitch.draw(ax=ax_opta2)# 根据条件, 筛选数据
df_fil = df_understat.loc[df_understat['Season'] == 2020]
# 未得分
pitch.scatter(df_fil[df_fil['Result'] != 'Goal']['X'], df_fil[df_fil['Result'] != 'Goal']['Y'],s=np.sqrt(df_fil[df_fil['Result']!='Goal']['xG'])*100, marker='o', alpha=0.6,edgecolor='black', facecolor='grey', ax=ax_opta2)
# 得分
pitch.scatter(df_fil[df_fil['Result']=='Goal']['X'], df_fil[df_fil['Result'] == 'Goal']['Y'],s=np.sqrt(df_fil[df_fil['Result'] == 'Goal']['xG'])*100, marker='o', alpha=0.9,edgecolor='black', facecolor='#6778d0', ax=ax_opta2, label='Goal')# 添加图例, 文字信息
ax_opta2.legend(loc='lower right').get_texts()[0].set_color("black")ax_opta2.text(30, 61, '得分次数 : '+str(len(df_fil[df_fil['Result'] == 'Goal'])), weight='bold', size=11)
ax_opta2.text(30, 64, f"预期进球 : {round(sum(df_fil['xG']),2)}", weight='bold', size=11)
ax_opta2.text(30, 58, '射门次数 : '+str(len(df_fil)), weight='bold', size=11)
ax_opta2.text(90, 60, '2020-21赛季', weight='bold', size=14)plt.show()
结果如下:
C罗老当益壮啊,状态一点也没有下滑。
下面接着绘制所有球员的数据散点图,看看C罗的数据能在哪一档?
# 初始化
ax_scatter = fig.add_axes([0.52, 0.57, 0.4, 0.35])
ax_scatter.patch.set_facecolor(background)
plt.show()
创建一个坐标轴:
首先对数据进行筛选,上场时间最少要有900s,而且位置为前锋此类的。
毕竟我们不能拿个守门员,跟C罗比数据吧,参考意义不大。
# 得到散点图的X, Y坐标值
no_90s = 10
df_fil = df_fbref[df_fbref['90s'] >= no_90s]
# 前锋位置
df_fil = df_fil[df_fil['Pos'].apply(lambda x: x in ['FW', 'MF,FW', 'FW,MF'])]# 每90s预期进球和得分次数
x, y = (df_fil['xG']/df_fil['90s']).to_list(), (df_fil['Gls']/df_fil['90s']).to_list()# 生成所有前锋位置, 数据散点图
ax_scatter.scatter(x, y, alpha=0.3, c='#EF8804')plt.show()
所有球员每90s预期进球和得分次数的数据情况。
现在我们筛选出C罗的数据,在散点图上用不同的颜色及透明度来突出显示它。
# C罗的数据
df_player = df_fil[df_fil['Player'] == 'Cristiano Ronaldo']
ax_scatter.scatter(df_player['xG']/df_player['90s'], df_player['Gls']/df_player['90s'], c='blue')plt.show()
结果如下:
可以看到C罗的数据还是比较高效的,虽不是第一,但也是前几的存在。
最后给散点图添加网格线,以及x轴和y轴标签。
# 添加网格线及标签
ax_scatter.grid(b=True, color='grey',linestyle='-.', linewidth=0.5,alpha=0.4)
ax_scatter.set_xlabel('每90秒的预期进球', fontdict={'fontsize': 12, 'weight': 'bold', 'color': text_color})
ax_scatter.set_ylabel('每90秒得分', fontdict=dict(fontsize=12, weight='bold', color=text_color))plt.show()
结果如下:
不愧是C罗,在2020-21赛季几乎每90秒就能进1颗球。
18年就已经有一个记录!C罗成历史第一位在90分钟内每分钟都有进球的球员。
最后添加文本信息,包含标题,C罗的头像,场上位置、年龄、效力球队。
此处使用hightlight-text库,可以高亮文本。
# 添加C罗的头像
ax_player = fig.add_axes([0.03, 0.53, 0.25, 0.45])
ax_player.axis('off')
im = plt.imread('ronaldo.png')
ax_player.imshow(im)# 添加标题信息
fig_text(0.03, 0.94, "<克里斯蒂亚诺·罗纳尔多(C罗)> 赛季数据", weight='heavy', size=19, highlight_textprops=[{'color': 'blue'}])
fig_text(0.25, 0.85, '位置: <边锋>',weight='bold', size=15, highlight_textprops=[{'color':'#EF8804'}])
fig_text(0.25, 0.81, '年龄: <36>',weight='bold', size=15, highlight_textprops=[{'color':'red'}])# 添加俱乐部logo
ax_team = fig.add_axes([0.27, 0.55, 0.15, 0.15])
ax_team.axis('off')
im = plt.imread('FCJ.png')
ax_team.imshow(im)# 添加备注
fig_text(0.07, 0.03, '本图制作者:<小F> 数据来源:Fbref.com、Understat.com',size=12, highlight_textprops=[{'color': '#EF8804'}], weight='bold')
plt.show()
C罗的头像、效力的队伍logo,都是小F自己制作的。
得到结果如下:
保存为图片:
# 保存为图片
plt.savefig('ronaldo_viz.png', dpi=300, facecolor=background)
看起来还不错哦:
好了,本期的分享就到此结束了,有兴趣的小伙伴可以自行去实践学习。
快给自己喜欢的足球运动员,也制作一个赛季数据面板吧!
代码链接:https://pan.baidu.com/s/18dWd-sYaWPuT8lpUOP3UkA
密码:n0vq
更多精彩推荐
Windows 11 上手机!小米 8、一加 6T、微软 Lumia 950 XL 都可以运行深度学习教你重建赵丽颖的三维人脸Openpose+Tensorflow 这样实现人体姿态估计 | 代码干货点分享点收藏点点赞点在看
相关文章:

便捷,轻巧的Groovy数据库操作
本文主要介绍Groovy对数据的CRUD操作,熟悉groovy.sql包,测试使用的数据库是H2。1.数据库连接配置//数据库连接配置 def db [url:jdbc:h2:mem:groovy,user:root,password:root,driver:org.h2.Driver ];2.创建数据库连接,这里使用到Groovy的Sq…

Linux查看CPU和内存使用情况详解
在系统维护的过程中,随时可能有需要查看 CPU 使用率,并根据相应信息分析系统状况的需要。在 CentOS 中, 可以通过 top 命令来查看 CPU 使用状况。运行 top 命令后,CPU 使用状态会以全屏的方式显示,并且会处在对话的 模…

Fatal Error: Out of memory php内存溢出处理三种方法
有时候我们在运行php程序的时候会发现 Fatal Error: Out of memory 这样的提示,这有可能是程序中用到了大量了变量和对象,导致分配的内存不够用。 修改php.ini文件里的memory_limit参数 方法一:修改php.ini文件里的memory_limit默认参数128M&…

腾讯联合国家天文台启动探星计划,优图AI可提升120倍数据处理效率
7月9日,2021世界人工智能大会腾讯论坛在上海举办,腾讯云副总裁、腾讯优图实验室总经理吴运声发表了“人工智能的可持续发展之道”主题演讲,宣布全新推出腾讯云TI ONE、TI Matrix、TI DataTruth三大AI底层平台,可以提供包括算法开发…

C++:STL标准入门汇总
学无止境!!! 第一部分:(参考百度百科) 一、STL简介 STL(Standard Template Library,标准模板库)是惠普实验室开发的一系列软件的统称。它是由Alexander Stepanov、Meng Lee和David R…

C#精髓【月儿原创】第三讲 C#泛型有什么好处
说明:准备出一个系列,所谓精髓讲C#语言要点。这个系列没有先后顺序,不过尽量做到精。可能会不断增删整理,本系列最原始出处是csdn博客,谢谢关注。 C#精髓 第三讲 C#泛型有什么好处 作者:清清月儿 主页:…

腾讯汤道生:人工智能最大的价值是“服务于人”
7月9日,2021世界人工智能大会腾讯论坛在上海拉开帷幕,腾讯高级执行副总裁、云与智慧产业事业群CEO汤道生开场致辞。汤道生表示,人工智能的最大价值是“服务于人”,让衣食住行实现“以消费者为中心”的智慧化供给,让生产…

[转]在Eclipse中使用JUnit4进行单元测试(中级篇)
我们继续对初级篇中的例子进行分析。初级篇中我们使用Eclipse自动生成了一个测试框架,在这篇文章中,我们来仔细分析一下这个测试框架中的每一个细节,知其然更要知其所以然,才能更加熟练地应用JUnit4。 一、 包含必要地Package…

linux下磁盘镜像软件DRBD的使用
一、 什么是DRBD DRBD的全称为:Distributed Replicated Block Device (DRBD)分布式块设备复制,DRBD是由内核模块和相关脚本而构成,用以构建高可用性的集群。其实现方式是通过网络来镜像整个设备。它允许用户在远程机器上建立一个本地块设备的实时镜像。与…

ASP.NET2.0轻松搞定统计图表【月儿原创】
ASP.NET2.0轻松搞定统计图表 作者:清清月儿 主页:http://blog.csdn.net/21aspnet/ 时间:2007.3.27 本文讲述如何绘制条形图,折线图,柱形图,面积图等常见图形。 效果图: 手把手…

基于 Python 的 8 种常用抽样方法
抽样是统计学、机器学习中非常重要,也是经常用到的方法,因为大多时候使用全量数据是不现实的,或者根本无法取到。所以我们需要抽样,比如在推断性统计中,我们会经常通过采样的样本数据来推断估计总体的样本。上面所说的…

RegularExpressions(4) RegularExpressions 成员(一)
为什么80%的码农都做不了架构师?>>> 主要成员有: IRegex、ICapture、IMatch、IMatchCollection、IGroup、IGroupCollection 先看: ICapture; 常用的 IMatch、IGroup 都是从它继承而来; 作为一个底层接口一般不会被直接使用. 它为 IMatch、IGroup 提供了…

公有云环境下应用程序的自动化部署与水平扩展问题
先介绍了一下公有云计算环境下的一些特点,再根据这些特点探讨一下作为云计算用户而言,如何对应用程序做好自动化部署和水平扩展(弹性计算)的问题。阅读本文需要有一定的云计算知识、开发运维知识。 公有云环境的优势及其特点 公有…

另辟蹊径创建移动应用:iOS和Android代码共享
2019独角兽企业重金招聘Python工程师标准>>> 过去几年,移动应用席卷了整个世界,在工作和生活的方方面面改变着我们使用互联网的方式。创建移动应用的各种技术也随之兴起,各种开发流程也 将移动应用视为一等公民,开始考…

从0开始,基于Python探究深度学习神经网络
来源 | Data Science from Scratch, Second Edition作者 | Joel Grus全文共6778字,预计阅读时间50分钟。深度学习1. 张量2. 层(Layer)的抽象3. 线性层4. 神经网络作为一个层的序列5. 损失和优化6. 示例:XOR 重新…

ASP.NET2.0雷霆之怒盗链者的祝福【月儿原创】
ASP.NET2.0雷霆之怒盗链者的祝福 作者:清清月儿 主页:http://blog.csdn.net/21aspnet/ 时间:2007.3.28 所谓盗链就是指其他网站把我们站点的文件链接帖到他们站上,这样白白占用我们的带宽。访问对于网站盗链行为&am…

数通手稿留档——BGP
本文转自Grodd51CTO博客,原文链接:http://blog.51cto.com/juispan/1954062,如需转载请自行联系原作者

ASP.NET2.0打通文件图片处理任督二脉【月儿原创】
ASP.NET2.0打通文件图片处理任督二脉 作者:清清月儿 主页:http://blog.csdn.net/21aspnet/ 时间:2007.4.1 1.最简单的单文件上传(没花头)2.多文件上传3.客户端检查上传文件类型(以上传图片为例)4.服务器端检查上传文件类型(以上…

PaaS变厚了
通过与包括东方通等在内的众多厂商的合作,华云数据的运营型PaaS变得越来越厚实。借助PaaS Plus的推出,华云数据要把云化的工作前移,在产品开发和测试阶段就开始云化,这会让传统企业的云化取得更好的效果。“PaaS是个筐,…

国内首个零信任技术标准发布 腾讯安全牵头编制
7月7日,中国电子工业标准化技术协会发布了国内首个零信任技术实现标准——T/CESA 1165-2021《零信任系统技术规范》团体标准,填补了国内零信任领域的技术标准空白。 (《零信任系统技术规范》) 据悉,该标准由腾讯安全牵…

集群概述及原理笔记(1)
it你好linux学习文档之集群概述及原理笔记(1) 一 前言 目前,越来越多的网站采用Linux操作系统,提供邮件、Web、文件存储、数据库等服务。也有非常多的公司在企业内部网中利用Linux服务器提供这些服务。随着人们对Linux服务器依赖的加深,对其…

ASP.NET2.0 遍历文件夹下所有图片【月儿原创】
ASP.NET2.0 遍历文件夹下所有图片 作者:清清月儿 主页:http://blog.csdn.net/21aspnet/ 时间:2007.4.4 1.以下目录有若干图片(都是大图片) 2.在页面展现效果图 3.代码 后台代码using System;using Sy…

如何看待那些互相矛盾的论文?
原文:How to Make Sense of Contradictory Science Papers作者:Haixin Dang(利兹大学博士后研究员)、Liam Kofi Bright(伦敦经济学院的哲学系助理教授)译者:武文浩相信你已经读到过一些相互矛盾…

gdb图形化调试工具总结
gdb除了命令行方式等的调试之外,还有图形化的调试工具,下面列举一些供参考 1:insight 2: ddd 3: kgdb 4: xxgdb 其它的工具欢迎补充

ATLAS入门篇之CascadingDropDown控件编程
一、引言本文将通过具体的步骤解释如何借助于数据库(Microsoft SQL Server 2005 Express Edition)数据创建一个ASP.NET AJAX 1.0 CascadingDropDown控件。在本文示例中,我们将使用此层叠下拉列表框控件来选择要显示的汽车模型信息。【作者注】…

ASP.NET2.0 永恒密码之戒【月儿原创】
ASP.NET2.0 永恒密码之戒 作者:清清月儿 主页:http://blog.csdn.net/21aspnet/ 时间:2007.4.8 1.我们经常有这样的情形: 就是用户注册时由于某个信息填写错误要重新填写。但是这个过程经过了服务器PostBack。所以密码…

GitHub 遭抵制!AI 代码生成神器竟成“抄袭工具”?
整理 | 郑丽媛出品 | CSDN(ID:CSDNnews)上周,微软、GitHub、OpenAI 三方联手推出的 AI 代码生成神器 GitHub Copilot 一经官宣便引起巨大关注:试问哪个开发者不想要这么一位“虚拟程序员”来解放自己的双手?…

LAMP的安装及Xcache的配置
LAMP是LinuxApacheMySQLPHP的简称,意指以Linux作为服务器的操作系统,以Apache的HTTPD作为Web服务器,以PHP作为动态网页的解释器,以MySQL作为后端数据库管理系统,由此而搭建起来的一套Web服务器系统。为方便起见&#x…

Windows Server 2003 AD升级到Windows Server 2008 AD的方法及详细步骤
前言: Windows Server 2008 是现在企业比较流行的服务器操作系统,安全性高,配置灵活、方便,集成了Hyper-V虚拟化功能,能够充分发挥硬件的性能。Windows Server 2008改写了底层的网络传输代码,理论上&#x…

ASP.NET2.0 ReportingServices使用详解
ASP.NET2.0 ReportingServices使用详解 作者:清清月儿 主页:http://blog.csdn.net/21aspnet/ 时间:2007.4.9本文先做个简单介绍,更多关于ReportingServices的文章见后续。 1.打开BIDS,这是报表开发工具 2.新建项目 3.选择…