科比投籃數據可視化小例子
- 2020 年 3 月 3 日
- 筆記
作為一名喜歡籃球的python初學者,一直在尋找利用python分析NBA比賽數據的案例,希望可以通過重複這些案例提高自己的python編程水平,畢竟將相對比較無聊的程式碼和自己的興趣結合起來,可以使學習過程顯得不再那麼單調!下文內容介紹自己找到並完全重複其程式碼的一個案例。
原文地址 How to Create NBA Shot Charts in Python;原文的主要內容是通過可視化的手段展示哈登2014-2015賽季的投籃數據。但是第一部分通過爬蟲獲取數據的過程自己還不是很理解,沒有能夠獲得原文使用的數據集。稍顯遺憾之際想到了自己之前重複過的一個kaggle案例 Kobe Brant Shot Selection —— 科比的投籃選擇。數據集完全匹配,遂用科比的投籃數據來重複原文。
第一部分:使用matplotlib畫一個籃球場
from matplotlib.patches import Circle from matplotlib.patches import Rectangle from matplotlib.patches import Arc def draw_court(ax=None,color='black',lw=2,outer_lines=False): if ax is None: ax = plt.gca() hoop = Circle((0,0),radius=7.5,linewidth=lw,color=color,fill=False) backboard = Rectangle((-30,-7.5),60,-1,linewidth=lw,color=color) outer_box = Rectangle((-80,-47.5),160,190,linewidth=lw,color=color,fill=False) inner_box = Rectangle((-60,-47.5),120,190,linewidth=lw,color=color,fill=False) top_free_throw = Arc((0,142.5),120,120,theta1=0,theta2=180,linewidth=lw,color=color,fill=False) bottom_free_throw = Arc((0,142.5),120,120,theta1=180,theta2=0,linewidth=lw,color=color,linestyle='dashed') restricted = Arc((0,0),80,80,theta1=0,theta2=180,linewidth=lw,color=color) corner_three_a = Rectangle((-220,-47.5),0,140,linewidth=lw,color=color) corner_three_b = Rectangle((220,-47.5),0,140,linewidth=lw,color=color) three_arc = Arc((0,0),475,475,theta1=22,theta2=158,linewidth=lw,color=color) center_outer_arc = Arc((0,422.5),120,120,theta1=180,theta2=0,linewidth=lw,color=color) center_inner_arc = Arc((0,422.5),40,40,theta1=180,theta2=0,linewidth=lw,color=color) court_elements = [hoop, backboard,outer_box,inner_box,top_free_throw,bottom_free_throw,restricted,corner_three_a,corner_three_b,three_arc,center_outer_arc,center_inner_arc] if outer_lines: outer_lines = Rectangle((-250,-47.5),500,470,linewidth=lw,color=color,fill=False) court_elements.append(outer_lines) for element in court_elements: ax.add_patch(element) return ax

Court_1.jpg
第二部分:籃球場結合科比的投籃數據
import pandas as pd import matplotlib.pyplot as plt shot_df = pd.read_csv("data.csv") plt.figure(figsize=(12,11)) plt.scatter(shot_df.loc_x,shot_df.loc_y) draw_court(outer_lines=True) plt.xlim(300,-300) plt.show()

Court_2.jpg
第三部分:jointplot
jointplot是什麼意思自己還不太明白
import seaborn as sns joint_shot_chart = sns.jointplot(shot_df.loc_x,shot_df.loc_y,stat_func=None,kind='scatter',space=0,alpha=0.5) joint_shot_chart.fig.set_size_inches(12,11) ax = joint_shot_chart.ax_joint draw_court(ax) ax.set_xlim(-250,250) ax.set_ylim(422.5,-47.5) ax.set_xlabel('') ax.set_ylabel('') ax.tick_params(labelbottom='off',labelleft='off') ax.set_title('The location and circumstances of every field goal attempted by Kobe Bryant',y=1.2,fontsize=18) ax.text(-250,445,'Data Source: KagglenAuthor:MingYan',fontsize=12) plt.show()

Court_3.jpg
第四部分:抓取一張科比的大頭貼
import urllib.request url = "https://d2cwpp38twqe55.cloudfront.net/req/201902151/images/players/bryanko01.jpg" picture = urllib.request.urlretrieve(url) kobe_picture = plt.imread(picture[0]) plt.imshow(kobe_picture) plt.savefig("Kobe.jpg")

Kobe.jpg
第五部分:將大頭貼和投籃分布圖結合到一起
from matplotlib.offsetbox import OffsetImage cmap = plt.cm.YlOrRd_r joint_shot_chart = sns.jointplot(shot_df.loc_x,shot_df.loc_y,stat_func=None,kind='kde',space=0,color=cmap(0.1),cmap=cmap,n_levels=50) joint_shot_chart.fig.set_size_inches(12,11) ax = joint_shot_chart.ax_joint draw_court(ax) ax.set_xlim(-250,250) ax.set_ylim(422.5,-47.5) ax.set_xlabel('') ax.set_ylabel('') ax.tick_params(labelbottom='off',labelleft='off') ax.set_title('The location of every goal attempted by Kobe Bryabt took during his 20-year career',y=1.2,fontsize=18) ax.text(-250,445,"Data Source: KagglenPorter: MingYan",fontsize=12) img = OffsetImage(kobe_picture,zoom=0.6) img.set_offset((1000,920)) ax.add_artist(img) plt.savefig("Court_4.jpg")

Court_4.jpg
第五部分:換另外一種風格
cmap = plt.cm.gist_heat_r joint_shot_chart = sns.jointplot(shot_df.loc_x,shot_df.loc_y,stat_func=None,kind='hex',space=0,color=cmap(.2),cmap=cmap) joint_shot_chart.fig.set_size_inches(12,11) ax = joint_shot_chart.ax_joint draw_court(ax) ax.set_xlim(-250,250) ax.set_ylim(422.5,-47.5) ax.set_xlabel('') ax.set_ylabel('') ax.tick_params(labelbottom='off',labelleft='off') ax.set_title('The location of every goal attempted by Kobe Bryabt took during his 20-year career',y=1.2,fontsize=18) ax.text(-250,445,"Data Source: KagglenPorter: MingYan",fontsize=12) img = OffsetImage(kobe_picture,zoom=0.6) img.set_offset((1000,920)) ax.add_artist(img) plt.savefig("Court_5.jpg")

Court_5.jpg
第六部分:版本資訊
print('Python version:',sys.version_info) import IPython print('IPython version:', IPython.__version__) print('Urllib.requests version:', urllib.request.__version__) import matplotlib as mpl print('Matplotlib version:', mpl.__version__) print('Seaborn version:', sns.__version__) print('Pandas version:', pd.__version__)
Python version: sys.version_info(major=3, minor=6, micro=3, releaselevel='final', serial=0) IPython version: 6.1.0 Urllib.requests version: 3.6 Matplotlib version: 2.1.0 Seaborn version: 0.5.0 Pandas version: 0.20.3