Work originally done on 2018-11-02 - the day after Rose's career high. Code modified on 2019-11-23
Get Data¶
In [1]:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import time
import requests
from pandas.plotting import register_matplotlib_converters
register_matplotlib_converters()
%matplotlib inline
Define functions to access NBA API¶
In [2]:
header = {'Host': 'stats.nba.com',
'Connection': 'keep-alive',
'Accept': 'application/json, text/plain, */*',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97 Safari/537.36',
'Referer': 'https://stats.nba.com/',
'Accept-Encoding': 'gzip, deflate, br',
'Accept-Language': 'en-US,en;q=0.9'}
def playergamelogs(PlayerID,DateFrom='',DateTo='',GameSegment='',LastNGames='0',LeagueID='00',
Location='',MeasureType='Base',Month='0',OpponentTeamID='0',Outcome='',
PORound='0',PaceAdjust='N',PerMode='Totals',Period='0',
PlusMinus='N',Rank='N',Season='2018-19',
SeasonSegment='',SeasonType='Regular Season',ShotClockRange='',
VsConference='',VsDivision=''):
url = 'https://stats.nba.com/stats/playergamelogs?'
api_param = {
'DateFrom' : DateFrom,
'DateTo' : DateTo,
'GameSegment' : GameSegment,
'LastNGames' : LastNGames,
'LeagueID' : LeagueID,
'Location' : Location,
'MeasureType' : MeasureType,
'Month' : Month,
'OpponentTeamID' : OpponentTeamID,
'Outcome' : Outcome,
'PORound' : PORound,
'PaceAdjust' : PaceAdjust,
'PerMode' : PerMode,
'Period' : Period,
'PlayerID' : PlayerID,
'PlusMinus' : PlusMinus,
'Rank' : Rank,
'Season' : Season,
'SeasonSegment' : SeasonSegment,
'SeasonType' : SeasonType,
'ShotClockRange' : ShotClockRange,
'VsConference' : VsConference,
'VsDivision' : VsDivision,
}
response = requests.get(url,params=api_param,headers=header)
data = response.json()
return pd.DataFrame(data['resultSets'][0]['rowSet'],columns=data['resultSets'][0]['headers'])
def seasons_string(start,end):
'''
creates a list of NBA seasons from start-end
'''
years = np.arange(start,end)
seasons = []
for year in years:
string1 = str(year)
string2 = str(year+1)
season = '{}-{}'.format(string1,string2[-2:])
seasons.append(season)
return seasons
Make API calls:¶
I'm adding a sleep of 1 seconds after every API call to make sure we do not exceed the rate limit
In [3]:
rose_id = 201565
data_list = []
for season in seasons_string(2008,2019):
data_list.append(playergamelogs(rose_id,Season=season))
print(season)
time.sleep(1.0)
Convert list of dataframes to a single dataframe
In [4]:
data = pd.concat(data_list,ignore_index=True)
Data cleaning and aggregation¶
In [5]:
data['GAME_DATE'] = pd.to_datetime(data['GAME_DATE'])
data['PTS'] = pd.to_numeric(data['PTS'])
data = data.sort_values(by='GAME_DATE')
data = data.set_index('GAME_DATE')
In [6]:
import matplotlib.dates as mdates
Season averages
In [7]:
season_avg = data.groupby('SEASON_YEAR')['PTS'].mean()
Prepare season averages data for plotting
In [8]:
import datetime as dt
x2 = [dt.datetime(2009,2,1),dt.datetime(2010,2,1),dt.datetime(2011,2,1),
dt.datetime(2012,2,1),dt.datetime(2013,11,1),
dt.datetime(2015,2,1),dt.datetime(2016,2,1),dt.datetime(2017,2,1),
dt.datetime(2018,2,1),dt.datetime(2019,2,1)]
y2 = season_avg.tolist()
Plot data:¶
In [9]:
xlabel = 'Season'
ylabel = 'Points'
title = 'Derrick Rose - Welcome to The 50 Point Club'
name = 'By: DoingTheDishes'
source = 'NBA.COM'
figsize = (1.33*8,8)
bg_color = (0.97,0.97,0.97)
# create figure
fig = plt.figure(figsize=figsize)
# change figure face color
fig.set_facecolor(bg_color)
# create labels and title for figure
fig.text(0.01,0.01,name,fontsize=14.0,color='gray',
horizontalalignment='left',verticalalignment='bottom')
fig.text(0.99,0.01,'Source: '+source,fontsize=14.0,color='gray',
horizontalalignment='right',verticalalignment='bottom')
fig.text(0.01,0.99,title,fontsize=22.0,
horizontalalignment='left',weight="bold",verticalalignment='top')
fig.text(0.53,0.048,xlabel,fontsize=16.0,color='black',
horizontalalignment='center',verticalalignment='center')
fig.text(0.03,0.18+0.77/2,ylabel,fontsize=16.0,color='black',
horizontalalignment='center',verticalalignment='center',rotation=90)
# add axes - the numbers define the left, bottom, width and height of the axes. The axes is where we plot our data.
ax = fig.add_axes([0.1,0.18,0.85,0.77])
# change the color of the axes
ax.set_facecolor(bg_color)
# make the figure look a little better
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)
ax.axes.tick_params(length=0)
ax.tick_params(labelsize=16)
##################################################
# This is where we do the actual plotting
x = data.index
ax.plot_date(data.index,data['PTS'],'o',alpha=0.5,markersize=10,color='#008fd5',label='Game to Game')
ax.plot_date(x2, y2,'k+',ms=14,mew=4,label='Season Average')
# Add arrow with the text career high
ax.annotate('Career High', (mdates.date2num(x[-1])-150, 49.5), xytext=(-100, -50),fontsize=16,
textcoords='offset points', arrowprops=dict(arrowstyle='-|>',color='k'))
# set the x and y limits
ax.set_xlim([mdates.date2num(x[0])-50,mdates.date2num(x[-1])+50])
ax.set_ylim([-1,55])
# define and rotate the x labels
ax.set_xticklabels(seasons_string(2007,2019));
plt.xticks(rotation=45)
# add legend
leg = ax.legend(loc='upper left',numpoints = 1)
frame = leg.get_frame()
frame.set_facecolor((0.97,0.97,0.97))
frame.set_edgecolor((0.97,0.97,0.97))
# save figure
fig.savefig('Rose.png',bbox_inches='tight',facecolor=fig.get_facecolor(), edgecolor='none')
Work done by Adam Reynolds, Tim Long and Eyal Shafran
Comments
comments powered by Disqus