模擬美式橄欖球比賽數據(R)
獲得和清洗數據:
1.從網絡上抓取數據
year<-2013 url<-paste("http://sports.yahoo.com/nfl/stats/byteam?group=Offense&cat=Total&conference=NFL&year=season_",year,"&sort=530&old_category=Total&old_group=Offense") offense<-readHTMLTable(url,encoding="UTF-8",colClasses="character")[[7]]
執行上面的命令可以創建一個存儲32個球隊在2013賽季所有進攻統計數據的數據框offense
2.首先註意到下載的球隊數據存在很多空白列,而且為了確保數據格式正確,我們需要先進行數據清洗工作。如下所示,我們清除空白的列,並給每列賦予我們需要的數據類型。
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))
3.通過同樣的方式獲取防守數據。
url<-paste("http://sports.yahoo.com/nfl/stats/byteam?group=Defense&cat=Total&conference=NFL&year=season_",year,"&sort=530&old_category=Total&old_group=Defense") defense<-readHTMLTable(url,encoding="UTF-8",colClasses="character")[[7]]
readHTMLTable函數會下載整個網頁,所以我們通過在命令的末尾加上[[7]]來選擇我們需要的第7列元素。
R語言中的paste()函數實現字符串的連接。如果你對操作數據陌生,連接指的是將兩個字符串拼接在一起。我們利用paste函數來連接下載數據的URL和需要獲取數據的年份,從而可以僅僅通過改變year的數值來改變整個下載數據的URL。另一個非常有用的R函數是apply()。我們可以通過它僅用一行代碼同時將多列變量變成數值類型。apply()函數不僅可以用來改變數據類型,也可以執行其他數學計算。
分析和理解美式橄欖球比賽數據
1.首先,為了方便後續數據研究,我們將offense和defense兩個數據框合並成combined
combined<-merge(offense,defense,by.x="Team",by.y="Team")
因為offense和defense數據框中存在相同的列名稱,為了避免後面操作的混淆,我們需要為重名的列進行唯一命名。同時我們會剔出defense中和offense中重復的比賽數量列。
colnames(combined)[2]<-"Games" colnames(combined)[3]<-"OffPPG" colnames(combined)[4]<-"OffYPG" colnames(combined)[5]<-"OffPassYPG" colnames(combined)[6]<-"OffRushYPG" combined$G.y<-NULL colnames(combined)[15]<-"DefPPG" colnames(combined)[16]<-"DefYPG" colnames(combined)[17]<-"DefRushYPG" colnames(combined)[18]<-"DefPassYPG"
直方圖一直是初步研究數據的最好工具之一。因為它可以通過顯示每列數據的分布而分辨偏低、偏高和在正常範圍內的數值。
首先,我們為每個球隊平均每場進攻得分(offensive points per game)創建一個直方圖
hist(combined$OffPPG,breaks=10,main="Offensive Points Per Game",xlab="Offensive PPG",ylab="Number of Teams")
2.嘗試通過條形圖來理解combined數據集。
條形圖和前面所創建的直方圖經常容易被混淆。在這裏,二者的區別在於,條形圖可以刻畫出每支球隊在不同評價指標上的差異,而直方圖卻是用來顯示出評價指標在不同數值段上的球隊數量的分布
ppg<-transform(combined,Team=reorder(Team,combined$OffPPG)) ggplot(ppg,aes(x=Team,y=OffPPG))+geom_bar(stat=‘identity‘,color="black",fill="blue")+coord_flip()+labs(x="Team",y="Avg Points per Game")+ggtitle("Avg Points per Game")+theme(plot.title=element_text(size=18,face="bold"))3.現在我們再看看每支球隊在失守碼數上的平均表現,命令如下:
ypg<-transform(combined,Team=reorder(Team,-combined$DefYPG)) ggplot(ppg,aes(x=Team,y=OffPPG))+geom_bar(stat=‘identity‘,color="black",fill="blue")+coord_flip()+labs(x="Team",y=“Avg Points per Game”)+ggtitle("Avg points per Game")+theme(plot.title=element_text(size=18,face="bold"))
4.最後我們通過散點圖來觀察兩個變量之間的相關性
ggplot(combined,aes(x=combined$OffYPG,y=combined$OffPPG))+geom_point(shape=5,size=2)+geom_smooth()+labs(x="Yards per Game",y="Points per Game")+ggtitle("Offense Yards vs. Points per Game")+theme(plot.title=element_text(size=18,face="bold"))
構建度量攻防能力的指標
我們按照下面的流程來構造攻防指數:
1.首先,我們計算球隊的進攻傳球能力分值。combined變量中最能能體現傳球能力的是PassYds/G(average passing yards per game),即平均每場傳球碼數。PassYds/G的值越高,說明球隊擁有更強的傳球能力。
offense$OPassStrength<-max(offense[,5])-offense[,5] offense$OPassStrength<-(1-(offense$OPassStrength/max(offense$OPassStrength)))*100
首先我們計算每個球隊的PassYds/G和最大值之間的差值,然後除以最大值。1減去比值的用意是為了使分值的大小和傳球能力的大小成正比,最後將分值歸一到0和100之間。
2.為了計算球隊的進攻沖擊能力,我們可以對數據域RushYds(average rushing yards per game)采取相同的變換。
3.對每場進攻得分和進攻碼數進行上面相同的變化,然後將四個變換之後的變量綜合成用戶的攻擊能力指標。
模擬單場由程序決定勝負的比賽
模擬比賽的基本思路是比賽雙方中自身進攻能力和對手防守能力之間差值較大的隊伍將獲得比賽的勝利
1.選擇兩支參賽的隊伍,為了方便起見,我們稱這兩支球隊分別為主隊和客隊。
home_team<-"Chicago Bears" away_team<-"New Orleans Saints"
2.整合前面所計算的球隊的攻防能力指數
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")
3.基於匯總的參賽雙方數據,我們現在可以通過比較兩者的攻防能力指標來決定理論上應該勝出的隊伍。
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==home_team]-game$DPassStrength[game$Team==home_team]
4.上面我們計算了雙方在傳球能力上的差別,我們現在比較兩支球隊在沖球能力以及總能力上的差別
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]
5.因為球隊的總能力表現是基於傳球、沖擊和總體能力初始差值得到的,我們需要重寫Net_Total列。然後,通過比較兩支球隊的Net_Total,給出虛擬球賽中最終能夠獲勝的球隊
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 } print(paste(winner,"beat",loser))
模擬美式橄欖球比賽數據(R)