<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 Enriching Shooting Data
Goal
Step1:  The query in the below box no longer works thanks to the NBA restricting access to the data.
Step2:  Wrapping data merge into a function
Step3:  Drawing NBA Court to Scale
Step4:  Unfortunately, the NBA has blocked access to the data that was used to construct the following shot charts. Prior to about February, they had data that contained very interesting metrics on individual shots. One of those metrics was the proximity of the nearest defender. 
The following charts basically graph circles around the shot location on court that mark where the defender was at the time of shot. A bigger circle means the shooter was more wide-open. We do not know where on the circle the defender as, only that the defender was somewhere on the perimeter of the circle
<ASSISTANT_TASK:>
Python Code:
# Getting Basic Data
import goldsberry
import pandas as pd
%matplotlib inline
import matplotlib.pyplot as plt
import seaborn as sns
pd.set_option("display.max_columns", 50)
pd.options.mode.chained_assignment = None 
print goldsberry.__version__
print pd.__version__
# Getting Players List
players_2015 = goldsberry.PlayerList(Season='2015-16')
players_2015 = pd.DataFrame(players_2015.players())
harden_id = players_2015.loc[players_2015['DISPLAY_LAST_COMMA_FIRST'].str.contains("Harden"), 'PERSON_ID']
#XY Shot Charts
harden_shots = goldsberry.player.shot_chart(harden_id.values.tolist()[0], Season='2015-16')
harden_shots = pd.DataFrame(harden_shots.chart())
harden_shots.shape
harden_shots.head()
Explanation: Enriching Shooting Data
Goal: Visualize every shot a player takes during a single game with information on the closest defender
Steps:
Merge Advanced Shot Log with Shot Chart
Scatter plot each shot
Add ring to each shot using the distance of nearest defender as radius
Shade in each ring to represent in-your-face to WTFO
Change shape of each shot to represent Make/Miss
Funtionalize the whole process so that it takes a playerID and GameID as arguments and returns a chart with titles
End of explanation
dashboard = goldsberry.player.shot_dashboard(harden_id)
pd.DataFrame(dashboard.dribble())
#Sort XY Shots and Assign a Shot Number
#ShotNumber will be used to merge the two datasets.
harden_shots.sort(['GAME_ID', 'GAME_EVENT_ID'], inplace=True)
harden_shots['SHOT_NUMBER'] = harden_shots.groupby(['GAME_ID', 'PLAYER_ID'])['GAME_EVENT_ID'].cumcount()+1
#Merge data into a single dataframe
harden_shots_full = pd.merge(harden_shots, harden_shots_advanced, on=['GAME_ID', 'SHOT_NUMBER'], how='left')
harden_shots_full.head()
Explanation: The query in the below box no longer works thanks to the NBA restricting access to the data.
End of explanation
sns.set_style("white")
sns.set_color_codes()
plt.figure(figsize=(12,11))
plt.scatter(harden_shots.LOC_X, harden_shots.LOC_Y)
plt.show()
Explanation: Wrapping data merge into a function
End of explanation
def draw_court(ax=None, color='black', lw=2, outer_lines=False):
    # If an axes object isn't provided to plot onto, just get current one
    if ax is None:
        ax = plt.gca()
    # Create the various parts of an NBA basketball court
    # Create the basketball hoop
    # Diameter of a hoop is 18" so it has a radius of 9", which is a value
    # 7.5 in our coordinate system
    hoop = Circle((0, 0), radius=7.5, linewidth=lw, color=color, fill=False)
    # Create backboard
    backboard = Rectangle((-30, -7.5), 60, -1, linewidth=lw, color=color)
    # The paint
    # Create the outer box 0f the paint, width=16ft, height=19ft
    outer_box = Rectangle((-80, -47.5), 160, 190, linewidth=lw, color=color,
                          fill=False)
    # Create the inner box of the paint, widt=12ft, height=19ft
    inner_box = Rectangle((-60, -47.5), 120, 190, linewidth=lw, color=color,
                          fill=False)
    # Create free throw top arc
    top_free_throw = Arc((0, 142.5), 120, 120, theta1=0, theta2=180,
                         linewidth=lw, color=color, fill=False)
    # Create free throw bottom arc
    bottom_free_throw = Arc((0, 142.5), 120, 120, theta1=180, theta2=0,
                            linewidth=lw, color=color, linestyle='dashed')
    # Restricted Zone, it is an arc with 4ft radius from center of the hoop
    restricted = Arc((0, 0), 80, 80, theta1=0, theta2=180, linewidth=lw,
                     color=color)
    # Three point line
    # Create the side 3pt lines, they are 14ft long before they begin to arc
    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)
    # 3pt arc - center of arc will be the hoop, arc is 23'9" away from hoop
    # I just played around with the theta values until they lined up with the 
    # threes
    three_arc = Arc((0, 0), 475, 475, theta1=22, theta2=158, linewidth=lw,
                    color=color)
    # Center Court
    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)
    # List of the court elements to be plotted onto the axes
    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:
        # Draw the half court line, baseline and side out bound lines
        outer_lines = Rectangle((-250, -47.5), 500, 470, linewidth=lw,
                                color=color, fill=False)
        court_elements.append(outer_lines)
    # Add the court elements onto the axes
    for element in court_elements:
        ax.add_patch(element)
    return ax
Explanation: Drawing NBA Court to Scale
End of explanation
plt.figure(figsize=(12,11))
plt.scatter(harden_shots_full.LOC_X[0], harden_shots_full.LOC_Y[0])
draw_court()
defender = Circle(xy, def_dist, alpha=.5)
fig = plt.gcf()
fig.gca().add_artist(defender)
# Descending values along the axis from left to right
plt.xlim(-300,300)
plt.ylim(422.5, -47.5)
len(harden_shots_full)
def draw_defender_radius(df, ax=None, alpha = .25):
    # If an axes object isn't provided to plot onto, just get current one
    if ax is None:
        ax = plt.gca()
    for i in range(len(df)):
        defender = Circle((df.LOC_X[i],df.LOC_Y[i]), 
                          radius = df.CLOSE_DEF_DIST[i]*10, 
                          alpha = alpha)
        ax.add_patch(defender)
    return ax
def fancy_shotchart(df):
    plt.figure(figsize=(12,11))
    plt.scatter(df.LOC_X, df.LOC_Y)
    draw_court()
    draw_defender_radius(df)
    # Descending values along the axis from left to right
    plt.xlim(-300,300)
    plt.ylim(422.5, -47.5)
harden_game = harden_shots_full.ix[harden_shots.GAME_ID == '0021400003']
fancy_shotchart(harden_game)
plt.figure(figsize=(12,11))
plt.scatter(harden_game.LOC_X, harden_game.LOC_Y,
            s=pi*(harden_game.CLOSE_DEF_DIST*10)**2,
            alpha = .25, c = harden_game.SHOT_MADE_FLAG,
            cmap = plt.cm.RdYlGn)
plt.scatter(harden_game.LOC_X, harden_game.LOC_Y, c='black')
draw_court()
# Descending values along the axis from left to right
plt.xlim(-300,300)
plt.ylim(422.5, -47.5)
def fancy_shots(df):
    plt.figure(figsize=(12,11))
    plt.scatter(df.LOC_X, df.LOC_Y,
            s=pi*(df.CLOSE_DEF_DIST*10)**2,
            alpha = .25, c = df.SHOT_MADE_FLAG,
            cmap = plt.cm.RdYlGn)
    plt.scatter(df.LOC_X, df.LOC_Y, c='black')
    draw_court()
    # Descending values along the axis from left to right
    plt.xlim(-300,300)
    plt.ylim(422.5, -47.5)
fancy_shots(harden_shots_full.ix[harden_shots.GAME_ID == '0021400003'])
fancy_shots(harden_shots_full.ix[harden_shots.GAME_ID == '0021400087'])
fancy_shots(harden_shots_full.ix[harden_shots.GAME_ID == '0021400512'])
Explanation: Unfortunately, the NBA has blocked access to the data that was used to construct the following shot charts. Prior to about February, they had data that contained very interesting metrics on individual shots. One of those metrics was the proximity of the nearest defender. 
The following charts basically graph circles around the shot location on court that mark where the defender was at the time of shot. A bigger circle means the shooter was more wide-open. We do not know where on the circle the defender as, only that the defender was somewhere on the perimeter of the circle
End of explanation
<END_TASK>