Table of Contents
http://moderndata.plot.ly/nba-shots-analysis-using-plotly-shapes/
import requests as r
# Chrome's user-agent string, to simulate a browser visiting the webpage
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.101 Safari/537.36'
}
# Stephen Curry's player id
player_id = 201939
# season details
season = '2015-16'
season_type = 'Regular Season'
# request parameters
req_params = {
'AheadBehind': '',
'ClutchTime': '',
'ContextFilter': '',
'ContextMeasure': 'FGA',
'DateFrom': '',
'DateTo': '',
'EndPeriod': '',
'EndRange': '',
'GameID': '',
'GameSegment': '',
'LastNGames': 0,
'LeagueID': '00',
'Location': '',
'Month': 0,
'OpponentTeamID': 0,
'Outcome': '',
'Period': 0,
'PlayerID': player_id,
'PointDiff': '',
'Position': '',
'RangeType': '',
'RookieYear': '',
'Season': season,
'SeasonSegment': '',
'SeasonType': season_type,
'StartPeriod': '',
'StartRange': '',
'TeamID': 0,
'VsConference': '',
'VsDivision': ''
}
res = r.get('http://stats.nba.com/stats/shotchartdetail', params=req_params, headers=headers)
import pandas as pd
res_json = res.json()
# column names
rows = res_json['resultSets'][0]['headers']
# row content
shots_data = res_json['resultSets'][0]['rowSet']
shots_df = pd.DataFrame(shots_data, columns=rows)
import numpy as np
shots_df['EVENT_TYPE'].unique()
np.array([u'Made Shot', u'Missed Shot'], dtype=object)
array([u'Made Shot', u'Missed Shot'], dtype=object)
# scatter chart of the *missed* shots by curry
import plotly.graph_objs as go
from plotly.offline import init_notebook_mode, iplot
init_notebook_mode()
shot_trace = go.Scatter(
x = shots_df[shots_df['EVENT_TYPE'] == 'Missed Shot']['LOC_X'],
y = shots_df[shots_df['EVENT_TYPE'] == 'Missed Shot']['LOC_Y'],
mode = 'markers'
)
data = [shot_trace]
layout = go.Layout(
showlegend=False,
height=600,
width=600
)
fig = go.Figure(data=data, layout=layout)
iplot(fig)
# repeat for made shots
shot_trace = go.Scatter(
x = shots_df[shots_df['EVENT_TYPE'] == 'Made Shot']['LOC_X'],
y = shots_df[shots_df['EVENT_TYPE'] == 'Made Shot']['LOC_Y'],
mode = 'markers'
)
data = [shot_trace]
layout = go.Layout(
showlegend=False,
height=600,
width=600
)
fig = go.Figure(data=data, layout=layout)
iplot(fig)
The X-axis and Y-axis of our court chart will range from -300 to 300 and -100 to 500 respectively, 10 units on the chart scale is equal to 1 feet.
For reference to the court dimensions, we are using this image linked in the post by Savvas Tjortjoglou.
The boundary of the court looks like a rectangle of the size 50(ft.) X 94(ft.), we are drawing just the half (47 ft.) of it in length.
Here, the points (x0, y0) and (x1, y1) represents the bottom-left and top-right points of the rectangle.
# list containing all the shapes
court_shapes = []
outer_lines_shape = dict(
type='rect',
xref='x',
yref='y',
x0='-250',
y0='-47.5',
x1='250',
y1='422.5',
line=dict(
color='rgba(10, 10, 10, 1)',
width=1
)
)
court_shapes.append(outer_lines_shape)
We will draw it using a circle shape. The center of the circle is at the origin of the graph, with the radius being 7.5 unit.
# create the hoop
hoop_shape = dict(
type='circle',
xref='x',
yref='y',
x0='7.5',
y0='7.5',
x1='-7.5',
y1='-7.5',
line=dict(
color='rgba(10, 10, 10, 1)',
width=1
)
)
court_shapes.append(hoop_shape)
The Backboard is a raised vertical board with a basket attached. It’s 72 inches (60 unit) wide.
# backboard
backboard_shape = dict(
type='rect',
xref='x',
yref='y',
x0='-30',
y0='-7.5',
x1='30',
y1='-6.5',
line=dict(
color='rgba(10, 10, 10, 1)',
width=1
),
fillcolor='rgba(10, 10, 10, 1)'
)
court_shapes.append(backboard_shape)
It’s a rectangle with 16 ft. in width and 19 ft. in length.
outer_three_sec_shape = dict(
type='rect',
xref='x',
yref='y',
x0='-80',
y0='-47.5',
x1='80',
y1='143.5',
line=dict(
color='rgba(10, 10, 10, 1)',
width=1
)
)
court_shapes.append(outer_three_sec_shape)
It’s a rectangle with 12 ft. in width and 19 ft. in length.
inner_three_sec_shape = dict(
type='rect',
xref='x',
yref='y',
x0='-60',
y0='-47.5',
x1='60',
y1='143.5',
line=dict(
color='rgba(10, 10, 10, 1)',
width=1
)
)
court_shapes.append(inner_three_sec_shape)
The left side line of the Three-point line, 14 ft. in length.
The points (x0, y0) and (x1, y1) represents the edges of the line.
left_line_shape = dict(
type='line',
xref='x',
yref='y',
x0='-220',
y0='-47.5',
x1='-220',
y1='92.5',
line=dict(
color='rgba(10, 10, 10, 1)',
width=1
)
)
court_shapes.append(left_line_shape)
The right side line of the Three-point line.
right_line_shape = dict(
type='line',
xref='x',
yref='y',
x0='220',
y0='-47.5',
x1='220',
y1='92.5',
line=dict(
color='rgba(10, 10, 10, 1)',
width=1
)
)
court_shapes.append(right_line_shape)
three_point_arc_shape = dict(
type='path',
xref='x',
yref='y',
path='M -220 92.5 C -70 300, 70 300, 220 92.5',
line=dict(
color='rgba(10, 10, 10, 1)',
width=1
)
)
court_shapes.append(three_point_arc_shape)
This circle has a radius of 6 feets.
center_circe_shape = dict(
type='circle',
xref='x',
yref='y',
x0='60',
y0='482.5',
x1='-60',
y1='362.5',
line=dict(
color='rgba(10, 10, 10, 1)',
width=1
)
)
court_shapes.append(center_circle_shape)
--------------------------------------------------------------------------- NameError Traceback (most recent call last) <ipython-input-21-da917c3bef83> in <module>() 13 ) 14 ---> 15 court_shapes.append(center_circle_shape) NameError: name 'center_circle_shape' is not defined
This circle has a radius of 2 feets.
res_circle_shape = dict(
type='circle',
xref='x',
yref='y',
x0='20',
y0='442.5',
x1='-20',
y1='402.5',
line=dict(
color='rgba(10, 10, 10, 1)',
width=1
)
)
court_shapes.append(res_circle_shape)
This circle has a radius of 6 feets.
free_throw_circle_shape = dict(
type='circle',
xref='x',
yref='y',
x0='60',
y0='200',
x1='-60',
y1='80',
line=dict(
color='rgba(10, 10, 10, 1)',
width=1
)
)
court_shapes.append(free_throw_circle_shape)
We are using the dash property to style the circle, it has a radius of 6 feet.
res_area_shape = dict(
type='circle',
xref='x',
yref='y',
x0='40',
y0='40',
x1='-40',
y1='-40',
line=dict(
color='rgba(10, 10, 10, 1)',
width=1,
dash='dot'
)
)
court_shapes.append(res_area_shape)
missed_shot_trace = go.Scatter(
x = shots_df[shots_df['EVENT_TYPE'] == 'Missed Shot']['LOC_X'],
y = shots_df[shots_df['EVENT_TYPE'] == 'Missed Shot']['LOC_Y'],
mode = 'markers',
name = 'Missed Shot',
marker = dict(
size = 5,
color = 'rgba(255, 255, 0, .8)',
line = dict(
width = 1,
color = 'rgb(0, 0, 0, 1)'
)
)
)
made_shot_trace = go.Scatter(
x = shots_df[shots_df['EVENT_TYPE'] == 'Made Shot']['LOC_X'],
y = shots_df[shots_df['EVENT_TYPE'] == 'Made Shot']['LOC_Y'],
mode = 'markers',
name = 'Made Shot',
marker = dict(
size = 5,
color = 'rgba(0, 200, 100, .8)',
line = dict(
width = 1,
color = 'rgb(0, 0, 0, 1)'
)
)
)
data = [missed_shot_trace, made_shot_trace]
layout = go.Layout(
title='Shots by Stephen Curry in NBA session 2015-16',
showlegend=True,
xaxis=dict(
showgrid=False,
range=[-300, 300]
),
yaxis=dict(
showgrid=False,
range=[-100, 500]
),
height=1200,
width=1300,
shapes=court_shapes
)
fig = go.Figure(data=data, layout=layout)
iplot(fig)
import plotly.plotly as py
py.plot(fig, filename='stephen-curry')
u'https://plot.ly/~takanori/175'