言簡意賅的分享下在團隊競技類問題中一些有用的數據可視化、分析方法,不一樣的領域下對數據的處理確實千差萬別,每次遇到都深感本身的不足,幸虧有各位大佬們的分享,跪謝;php
https://www.kaggle.com/c/nfl-big-data-bowl-2020html
https://www.kaggle.com/holoong9291/nfl-tracking-wrangling-voronoi-and-sonars-pythonpython
繪製的必要性:想象這樣一種狀況,咱們拿到的都是比賽方的表格數據,不只枯燥,並且不夠直觀,即使咱們足夠了解橄欖球,依然沒法經過數據感覺到場上緊張的氛圍,進攻方的戰術安排,防守方的防守計劃等等,而這些實際上都是隱藏在數據中的,這就好像是玩LOL或者Dota(我我的兩個都玩過,目前主要玩Dota),我給你十個英雄的座標、移動速度、朝向、裝備,你很難理解當前的狀況,可是若是看看遊戲中的小地圖(假設小地圖能看到所有10個英雄),我相信大部分玩家都能看出當前是在爭奪肉山(搶大龍)、上高地、團戰、局部團戰等,所以繪製一個相似遊戲中的小地圖是很是有用的,會幫助咱們更深入的瞭解比賽;github
繪製代碼思路:機器學習
下面是相關代碼:工具
plt.figure(figsize=(30, 15)) plt.suptitle("Sample plays, standardized, Offense moving left to right") plt.xlabel("Distance from offensive team's own end zone") plt.ylabel("Y coordinate") i=1 for gp,chance in sample_chart_v2.groupby('PlayId'): play_id = gp rusher = chance[chance.NflId==chance.NflIdRusher].iloc[0] offense = chance[chance.IsOnOffense] defense = chance[~chance.IsOnOffense] plt.subplot(3,2,i) i+=1 plt.xlim(0,120) plt.ylim(-10,63) plt.scatter(offense.X_std,offense.Y_std,marker='o',c='red',s=55,alpha=0.5,label='OFFENSE') plt.scatter(defense.X_std,defense.Y_std,marker='o',c='green',s=55,alpha=0.5,label='DEFENSE') plt.scatter([rusher.X_std],[rusher.Y_std],marker='o',c='black',s=30,label='RUSHER') for line in range(10,130,10): plt.plot([line,line],[-100,100],c='silver',linewidth=0.8,linestyle='-') plt.plot([rusher.YardsFromOwnGoal,rusher.YardsFromOwnGoal],[-100,100],c='black',linewidth=1.5,linestyle=':') plt.plot([10,10],[-100,100],c='black',linewidth=2) plt.plot([110,110],[-100,100],c='black',linewidth=2) plt.title(play_id) plt.legend() plt.show()
下面是效果圖:
學習
能夠看到,一般對比賽實況的可視化,能夠清晰的看到當前處於哪一個半場,距離達陣還有多遠,進攻方、防守方的站位分別是怎樣,持球人周圍的隊友、對手數量、距離等,這很是有利於後續的分析挖掘;大數據
繪製的目的:上面的繪製能看出是靜態的,並且並無用上球員的速度、加速度、面向、移動方向等數據,而咱們知道球員老是處於不斷運動當中的,他們的當前狀態很重要,可是1s後,2s後可能更重要,這就是這一部分繪製的目的,強調每一個球員在一段時間後的狀態,固然,這部分繪製有一個前提假設,那就是球員當前的速度、加速度、面向、移動方向等信息在短期內是不變的,這一點也符合實際狀況(),固然繪製與現實會有一些出入,可是這些差別不影響咱們分析比賽;spa
繪製的代碼:
plt.figure(figsize=(12, 8)) plt.suptitle("Playid:20170910001102") plt.xlabel("Distance from offensive team's own end zone") plt.ylabel("Y coordinate") for gp,chance in sample_20170910001102.groupby('PlayId'): play_id = gp rusher = chance[chance.NflId==chance.NflIdRusher].iloc[0] offense = chance[chance.IsOnOffense] defense = chance[~chance.IsOnOffense] plt.subplot(1,1,1) i+=1 x_min, x_max = chance.X_std.min()-5, chance.X_std.max()+5 y_min, y_max = chance.Y_std.min()-5, chance.Y_std.max()+5 plt.xlim(x_min,x_max) plt.ylim(y_min,y_max) plt.scatter(offense.X_std,offense.Y_std,marker='o',c='green',s=55,alpha=0.5,label='OFFENSE') plt.scatter(defense.X_std,defense.Y_std,marker='o',c='red',s=55,alpha=0.5,label='DEFENSE') plt.scatter([rusher.X_std],[rusher.Y_std],marker='o',c='black',s=30,label='RUSHER') for idx, row in chance.iterrows(): _color='black' if row.IsBallCarrier else('green' if row.IsOnOffense else 'red') plt.arrow(row.X_std,row.Y_std,row.X_std_end-row.X_std,row.Y_std_end-row.Y_std,width=0.05,head_width=0.3,ec=_color,fc=_color) for line in range(10,130,10): plt.plot([line,line],[-100,100],c='silver',linewidth=0.8,linestyle='-') plt.plot([rusher.YardsFromOwnGoal,rusher.YardsFromOwnGoal],[-100,100],c='black',linewidth=1.5,linestyle=':') plt.plot([10,10],[-100,100],c='black',linewidth=2) plt.plot([110,110],[-100,100],c='black',linewidth=2) plt.title(play_id) plt.legend() plt.show()
下面是效果圖:
繪製的必要性:百度百科定義點泰森多邊形-馮洛諾伊圖,簡單理解就是在一個球場中,每一個球員都是一個個不重合的點,那麼將整個球場劃分到這些點上,那麼能夠認爲每一個點都有本身的一片控制區域,這也常常用於獅羣領土劃分、機場劃分等問題,抽象出來都是同一個問題;
泰森多邊形的侷限:
相對來講,泰森多邊形是對這一類問題的簡單抽象,沒有考慮一些複雜因素,可是也揭示了不少信息;
繪製代碼以下:
from scipy.spatial import Voronoi plt.figure(figsize=(12, 8)) plt.suptitle("Sample plays, standardized, Offense moving left to right") plt.xlabel("Distance from offensive team's own end zone") plt.ylabel("Y coordinate") sample_20171120000963 = train_1[train_1.PlayId==20171120000963].copy() for gp,chance in sample_20171120000963.groupby('PlayId'): play_id = gp rusher = chance[chance.NflId==chance.NflIdRusher].iloc[0] offense = chance[chance.IsOnOffense] defense = chance[~chance.IsOnOffense] plt.subplot(1,1,1) i+=1 x_min, x_max = chance.X_std.min()-2, chance.X_std.max()+2 y_min, y_max = chance.Y_std.min()-2, chance.Y_std.max()+2 #plt.xlim(8,50) # 特定 plt.xlim(x_min,x_max) #plt.ylim(5,40) # 特定 plt.ylim(y_min,y_max) #plt.plot([x_min,x_min,x_max,x_max,x_min],[y_min,y_max,y_max,y_min,y_min],c='black',linewidth=1.5) vor = Voronoi(np.array([[row.X_std,row.Y_std] for index, row in chance.iterrows()])) regions, vertices = voronoi_finite_polygons_2d(vor) for region in regions: polygon = vertices[region] plt.plot(*zip(*polygon),c='black',alpha=0.8) plt.scatter(offense.X_std,offense.Y_std,marker='o',c='green',s=55,alpha=0.5,label='OFFENSE') plt.scatter(defense.X_std,defense.Y_std,marker='o',c='red',s=55,alpha=0.5,label='DEFENSE') plt.scatter([rusher.X_std],[rusher.Y_std],marker='o',c='black',s=30,label='RUSHER') for line in range(10,130,10): plt.plot([line,line],[-100,100],c='silver',linewidth=0.8,linestyle='-') plt.plot([rusher.YardsFromOwnGoal,rusher.YardsFromOwnGoal],[-100,100],c='black',linewidth=1.5,linestyle=':') plt.plot([10,10],[-100,100],c='black',linewidth=2) plt.plot([110,110],[-100,100],c='black',linewidth=2) plt.title(play_id) plt.legend() plt.show()
運行效果圖:
從該圖中,能清晰的看到各個球員的控制區域,有一個量化因子是將這部分區域相加,量化每一個球隊的控制區域大小以及分佈;
這部分的分享目的:這部分分享來自這篇論文,我也還沒看完,因此分享內容會比較少,簡單概述一下。首先你們應該能看到泰森多邊形的不足,首先它沒有考慮速度等動態因素,其次它是針對每一個球員而不是球隊的,可是咱們知道球隊的信息更重要,由於這是團隊競技,所以缺少對球員進行疊加的過程,而這些都是這篇論文重點探討的地方;
實際上這篇論文還有不少內容,且主要內容是關於如何量化球員影響區域的,也就是如何抽象爲一些數學公式上,固然這部分我目前也算不上理解,因此處於外行看熱鬧的階段,不過你們應該能夠從中感覺到數學建模的威力,以及這些東西的普遍應用,但願這篇分享可以幫到你們一點點;
你們能夠到個人Github上看看有沒有其餘須要的東西,目前主要是本身作的機器學習項目、Python各類腳本工具、數據分析挖掘項目以及Follow的大佬、Fork的項目等:
https://github.com/NemoHoHaloAi