R语言模拟美式橄榄球比赛数据分析(5):模拟多场由计算决定胜负的比赛

本文使用R语言模拟美式橄榄球比赛数据分析

本文使用R语言模拟美式橄榄球比赛数据,我们将完成以下几部分工作。

  • 获取和清理美式橄榄球比赛数据
  • 分析和理解美式橄榄球比赛数据
  • 构建度量攻防能力的指标
  • 模拟单场由程序决定胜负的比赛
  • 模拟多场由计算决定胜负的比赛

在我们已经完成单场比赛的模拟之后,可以非常方便地进行多场比赛模拟。首先,我们需要通过循环语句实现多场比赛的赛程,并在循环语句内部嵌入单场比赛的模拟;同时,我们需要变量来记录每支球队胜出和失败的数量。下面,我们将一步步展示如何去模拟多场比赛。

准备工作

一旦你已经完成了单场比赛的模拟,我们便已经完成本小节三分之一的代码。

处理流程

按照我们既定的思路完成下面的模拟。

1.如前描述,我们首先需要制定比赛的赛程,即决定每场比赛的对阵双方。在很多种决定方法中,最简单的就是输入真正的比赛赛程。但是,为了更好地展示如何通过程序生成赛程,我们会通过下面的for循环产生自己的赛程。现实中,从球员健康的角度考虑,NFL并不会有长为50周的赛季;但是,在我们的模拟中,一个赛季中可以有任意场球赛。我们通过下面的代码模拟赛程。

games_per_team <- 50

for(week in 1:games_per_team){

home_index <- sample(1:32, 16, replace=F)

home_teams <- data.frame(HomeTeam=offense[home_index, 1])

away_teams <- data.frame(AwayTeam=offense[-home_index, 1])

if(week==1){

schedule <-

cbind(Week=week,HomeTeam=home_teams,AwayTeam=away_teams)

}else{

temp <-

cbind(Week=week,HomeTeam=home_teams,AwayTeam=away_teams)

schedule <- rbind(schedule,temp)

}

}

通过上面的代码,我们得到了下图所示的数据框变量。但是因为sample函数的随机性,读者执行代码产生的主队和客队并不一定完全和这里的队伍名称相匹配。

2016073116

2.在已经确定赛程之后,现在我们可以记录每支队伍的比赛结果。

records <- data.frame(Team=offense$Team)

records$Wins <- 0

records$Losses <- 0

通过执行上面的代码,我们得到下面的数据框。

2016073117

3.现在我们需要通过程序自动实现每场比赛,并更新记录每个球队的输赢记录。我们通过在for循环中嵌入上一个小节中的代码来循环实现多场比赛。我们分步拆分for循环如下。

for(i in 1:nrow(schedule)){

home_team <- schedule[i,2]

away_team <- schedule[i,3]

week <- schedule[i,1]

这段代码确定和模拟赛程中比赛周数相同的循环次数,并且在每次循环中对主队、客队和比赛的周数进行记录。

4.接下来的循环部分就是我们先前的代码。本段代码通过比较比赛双方在传球、冲击和总体能力上的差别来确定每场比赛的获胜者。

off_game <- subset(offense,Team==home_team |

Team==away_team)[,c(1,15,16,19)]

def_game <- subset(defense,Team==home_team |

Team==away_team)[,c(1,14,15,18)]

game <- merge(off_game,def_game,by.x=”Team”,by.y=”Team”)

game$Net_Pass[game$Team==home_team] <-

game$OPassStrength[game$Team==home_team] –

game$DPassStrength[game$Team==away_team]

game$Net_Pass[game$Team==away_team] <-

game$OPassStrength[game$Team==away_team] –

game$DPassStrength[game$Team==home_team]

game$Net_Rush[game$Team==home_team] <-

game$ORushStrength[game$Team==home_team] –

game$DRushStrength[game$Team==away_team]

game$Net_Rush[game$Team==away_team] <-

game$ORushStrength[game$Team==away_team] –

game$DRushStrength[game$Team==home_team]

game$Net_Total[game$Team==home_team] <-

game$OffStrength[game$Team==home_team] –

game$DefStrength[game$Team==away_team]

game$Net_Total[game$Team==away_team] <-

game$OffStrength[game$Team==away_team] –

game$DefStrength[game$Team==home_team]

game$Net_Total <- game$Net_Pass + game$Net_Rush +

game$Net_Total

if(game$Net_Total[game$Team==home_team] >=

game$Net_Total[game$Team==away_team]){

winner <- home_team

loser <- away_team

}else{

winner <- away_team

loser <- home_team

}

5.本段代码记录每场比赛的结果,并更新各个球队在整个赛季里面的输赢记录。

if(i==1){

winnerdf <- data.frame(Winner=winner)

loserdf <- data.frame(Loser=loser)

results <- cbind(winnerdf,loserdf)

}else{

winnerdf <- data.frame(Winner=winner)

loserdf <- data.frame(Loser=loser)

temp <- cbind(winnerdf,loserdf)

results <- rbind(results,temp)

}

records$Wins[records$Team==winner] <-

as.numeric(records$Wins[records$Team==winner]) + 1

records$Losses[records$Team==loser] <-

as.numeric(records$Losses[records$Team==loser]) + 1

print(paste(“Week”, week,”:”, winner, “beat”, loser))

}

[1] “Week 1 : Denver Broncos beat San Diego Chargers”

[1] “Week 1 : Indianapolis Colts beat Chicago Bears”

[1] “Week 1 : San Francisco 49ers beat Philadelphia Eagles”

[1] “Week 1 : Tennessee Titans beat Dallas Cowboys”

[1] “Week 1 : Cincinnati Bengals beat Baltimore Ravens”

[1] “Week 1 : Seattle Seahawks beat Detroit Lions”

[1] “Week 1 : Green Bay Packers beat New England Patriots”

[1] “Week 1 : Pittsburgh Steelers beat Minnesota Vikings”

for循环之后生成的results变量如下图所示。

2016073118

6.最后,我们通过对每个球队获胜次数的降序排序决定本次模拟赛季的最终获胜者。

records <- records[order(-records$Wins),]

排序之后的数据框架如下图所示。

2016073119

通过和2013赛季真正结果(见下图)的比较,我们可以看到模拟赛季中的前十名中的七支队伍同样榜上有名。这说明我们模拟赛季的结果是合理的。当然,我们还可以通过其他方法进行更精准的赛季模拟。

2016073120

工作原理

在本小节中,我们使用sample函数为每周随机产生对阵双方。

home_index <- sample(1:32, 16, replace=F)

上面的sample函数通过无放回的方式从32支球队中随机选出16队作为主队。其中home_index的队伍是主队,其他的便为客队。

我们同时可以利用for循环来实现每次比赛,并决定每场比赛的胜败队伍。

for (i in times-you-want-to-loop){

do what you want to repeat

}

你可以在for循环中实现任何你想实现的逻辑。而且,正如我们在本小节实现的,for循环中可以嵌入条件表达式。

更多内容

在本章中,我们利用R实现了计算、比较和画图,甚至利用R编程语言的特性完整实现了一个比赛模拟引擎。在这个模拟引擎中,我们可以通过获取每个橄榄球队过去每场比赛的表现,计算他们各自的能力指数,并计算球队间相对的优势和劣势。

通过实现本章的逻辑,我们已经回答了一些基本的问题并给出了一些基本的统计变量。读者完全可以通过对这个项目做更多的探索来锻炼自己使用R的能力。

读者可以尝试提升本章中提出的能力指数计算方式。我们可以在计算能力指数的时候引入更多的变量,或者是为每个变量赋予不同的权重。更甚者,读者可以尝试使用其他或者自己建立的公式。要知道,实践数据科学非常重要的过程就是设计不同的实验来尝试和迭代。所以,做更多的尝试并记录每次实验的结果质量完全可以帮助你探索出更好的计算能力指数的方式。

另外一个探索的方向是实现更贴近现实的模拟。所以,读者可以使用真实的赛程而不是使用我们模拟的赛程。当我们所计算的能力指数显示比赛理应是平局的时候,可以通过引入一个概率变量来解释比赛的结果。同样,在这个方向做更多的尝试和迭代可以帮助读者更好地贴近现实并解释现实。

如果你想为模型增加更多的变量和粒度,你可以引入关于每个球员的统计变量,甚至是球队球员伤势信息,帮助你预测未来球队的表现。

然而,还有一个非常有趣的研究方向是预测来自不同赛季的冠军队伍在对抗中的表现。举例而言,现任超级碗冠军Seattle Seahawks将如何对抗前冠军New England Patriots和New York Giants读者可以设计自己的逻辑来决定过去十年中哪支球队是最棒的。

本文摘自《数据科学实战手册(R+Python)》,由人民邮电出版社授权数据分析网发布。

出处:异步社区
链接:http://www.epubit.com.cn/book/details/4237

本文采用「CC BY-SA 4.0 CN」协议转载自互联网、仅供学习交流,内容版权归原作者所有,如涉作品、版权和其他问题请给「我们」留言处理。

(0)
小胖的头像小胖编辑
上一篇 2016-08-01 06:45
下一篇 2016-08-01 22:06

相关文章

关注我们
关注我们
分享本页
返回顶部