本文使用R语言模拟美式橄榄球比赛数据,我们将完成以下几部分工作。
- 获取和清理美式橄榄球比赛数据
- 分析和理解美式橄榄球比赛数据
- 构建度量攻防能力的指标
- 模拟单场由程序决定胜负的比赛
- 模拟多场由计算决定胜负的比赛
简介
美式橄榄球在美国是最受欢迎的竞技运动,也是全世界第九受欢迎的体育运动。每年,橄榄球迷们都在期待9月开始的新一轮赛季:17周的常规赛,第二年1月开始的季后赛,以及第二年1月底或者2月初举行的争夺总冠军的超级碗。
我们首先通过一些统计指标初步认识和理解本章中所使用的橄榄球比赛数据,并通过比较队伍间的统计指标判定比赛的胜利者。随后,我们可以利用这些指标模拟单场和多场橄榄球比赛。在众多模拟比赛的方式中,虽然我们可以通过收集和利用球队中每个选手参加每场比赛的数据来模拟出非常详实的单场比赛,但是像这样如此细致的模拟仅仅在制作橄榄球电动游戏时是必需的。在本章中,我们会采取比较简单的方式:利用球队粒度的统计数据,就已经可以有效地决定比赛中哪一支队伍应该获得胜利。
本章的目的是展示如何实现一个完整的数据科学项目,包括从网站获取数据,提出指标、公式和计算方法,并解释不同的现实场景。最后,我们可以利用历史数据中总结出来的信息模拟未来的比赛。为了显示R不仅可以进行统计建模,而且是一门编程语言,我们选择使用R来实现项目中的数据获取、处理和显示。
本章中依然遵循数据科学项目实现流程,但会因为处理不同的数据类型和任务类型而做适当的修改。
准备工作
为了完成本章的数据科学项目,你需要一个可以访问互联网的计算机,并且这台计算机上已经安装了R语言和以下R包。
install.packages(“XML”)
install.packages(“RSQLite”)
install.packages(“stringr”)
install.packages(“ggplot2”)
同时需要将上面这些包载入R语言环境中。
library(XML)
library(RSQLite)
library(stringr)
library(ggplot2)
XML包读取网络上的HTML数据,RSQLite和stringr包处理和变换数据,ggplot2可以实现数据的可视化工作。另外,如果读者不熟悉美式橄榄球,可以通过访问http://www.nfl.com/ rulebook/beginnersguidetofootball获取基本的背景知识。
获取和清洗美式橄榄球比赛数据
网络上有很多网站提供美式橄榄球相关数据(赛程安排、比赛分值,以及简单的赛事统计数据)的下载。需要注意的是,当我们在寻找分析数据集的时候,数据的有用性、质量和格式是我们着重考虑的。所以,鉴于http://sports.yahoo.com/是一个可靠的数据来源,而且有着我们所需的数据并且相对较好的数据格式,其数据仅需简单的清洗。我们将从这里下载赛事数据。
准备工作
如果你已经安装和载入了简介中提到的R包,同时设置你当前工作目录为你想存储文件的地方,那么我们就可以开始处理和分析数据了。
处理流程
通过以下步骤获得和清洗数据。
1.首先,我们需要获得每个球队在一个赛季的进攻数据。因为当我们在撰写这本书时,2013赛季是最近的完成赛季,所以我们设置变量year为2013。
year <- 2013
2.其次,我们将设置数据地址的URL中年为2013,并将整个URL赋值给url变量。
url <-
paste(“http://sports.yahoo.com/nfl/stats/byteamgroup=Offense&
cat=Total&conference=NFL&year=season_”,year,”&sort=530&old_cat
egory=Total&old_group=Offense”)
3.当我们有完整的URL时,我们可以从网络上抓取数据。
offense <- readHTMLTable(url, encoding = “UTF-8″,
colClasses=”character”)[[7]]
执行上面的命令可以创建一个存储32个球队在2013赛季所有进攻统计数据的数据框offense,如下图所示。
4.我们首先注意到下载的球队数据中存在很多空白列,而且为了确保数据格式正确,我们需要先进行数据清洗工作。如下所示,我们清除空白的列,并给每列赋予我们需要的数据类型。
offense <- offense[,-c(2,4,6,8,10,12,14,16,18,20,22,24,26,28)]
offense[,1] <- as.character(offense[,1])
offense[,2:13] <- apply(offense[,2:13],2,as.numeric)
offense[,14] <- as.numeric(substr(offense[,14], 1, 2))*60 +
as.numeric(substr(offense[,14], 4, 6))
最后的TOP列是控球时间,或者说是不同球队每场比赛平均进攻的时间。在原始下载的数据中,它的格式是分:秒。我们将它转换成以秒为单位的变量,从而TOP可以反映不同球队在进攻时拥有控球权的平均秒。 |
现在,下载的进攻数据变得干净而且规整,如下图所示。
5.现在我们通过同样的方式获取防守数据。同进攻数据一样,我们在可以获得防守数据的URL中设置年份。
url <-
paste(“http://sports.yahoo.com/nfl/stats/byteamgroup=Defense&
cat=Total&conference=NFL&year=season_”,year,”&sort=530&old_cat
egory=Total&old_group=Defense”)
6.其次,我们将URL传递给readHTMLTable函数并下载数据。
defense <- readHTMLTable(url, encoding = “UTF-8″,
colClasses=”character”)[[7]]
readHTMLTable函数会下载整个网页,所以我们通过在命令的末尾加上[[7]]来选择我们需要的第七列元素。读者也可以尝试修改中括号中的数据,观察所获得的网络元素的变化。 |
下图显示了球队的防守数据。
7.正如我们需要清洗进攻数据,防守数据也需要清洗。我们会使用上面的数据清洗命令,同时将变量offense修改成defense。需要注意的是,因为控球权时间不适用于防守部分,所以defense中将不会包括TOP这一列。
defense <- defense[,-c(2,4,6,8,10,12,14,16,18,20,22,24,26)]
defense[,1] <- as.character(defense[,1])
defense[,2:13] <- apply(defense[,2:13],2,as.numeric)
现在,干净并被赋予恰当数据类型的防守数据如下图所示。
工作原理
R语言中的paste()函数实现字符串的连接(concatenate)。如果你对操作数据陌生,连接(concatenation)指的是将两个字符串拼接在一起。我们利用paste函数来连接下载数据的URL和需要获取数据的年份,从而可以仅仅通过改变year的数值来改变整个下载数据的URL。读者可以尝试在改变year的值为2012或者2011的前提下,重新运行上面的步骤。如果网站服务器中存有2011或者2012的数据,程序便可自动将数据下载下来,存在offense和defense变量中。
另一个非常有用的R函数是apply()。我们可以通过它仅用一行代码同时将多列变量变成数值类型。apply()函数不仅可以用来改变数据类型,也可以执行其他数学计算。举例说明,现在defense数据框中从第2列到第13列都已经被变换成数值类型,如果我们想求得每一列的平均值,通过下面一行代码就可以实现。
means <- apply(defense[,2:13],2,mean)
参考资料
- https://stat.ethz.ch/R-manual/R-devel/library/base/html/paste.html给出了paste()函数的详细使用说明。
- https://stat.ethz.ch/R-manual/R-devel/library/base/html/apply.html给出了apply()函数的详细使用说明。
- http://cran.r-project.org/web/packages/XML/XML.pdf给出了XML包的详细解释。
未完待续~~~
本文摘自《数据科学实战手册(R+Python)》,由人民邮电出版社授权数据分析网发布。
本文采用「CC BY-SA 4.0 CN」协议转载自互联网、仅供学习交流,内容版权归原作者所有,如涉作品、版权和其他问题请给「我们」留言处理。