def scatterplot(self): """ Returns a scatterplot of a players shots for the 2014-2015 NBA Season """ plt.figure(figsize=(10, 9)) plt.scatter(self.df.LOC_X, self.df.LOC_Y) draw_court(outer_lines=True) plt.xlim(-250, 250) plt.ylim(395, -47.5) ax = plt.axes([0.8, 0.2, 0.1, 0.2], frameon=True) ax.axis("off") plt.show()
def jointplot(self): """ returns joing plot of players shots, players image, and title (Not functioning) """ joint_shot_chart = sns.jointplot(self.df.LOC_X, self.df.LOC_Y, stat_func=None, kind="scatter", space=0) 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(395, -47.5) ax.set_xlabel("") ax.set_ylabel("") ax.tick_params(labelbottom="off", labelleft="off") ax.set_title("%s FGA \n2014-15 Reg. Season" % self.player, y=1.2, fontsize=18) ax.text(-250, 420, "Data Source: stats.nba.com", fontsize=12) plt.show()
player = shotchartdetail.ShotChartDetail(player_id='1628366', team_id='1610612740') table = player.get_data_frames()[0] #print(table.LOC_X) sns.set_style("white") sns.set_color_codes() # plt.figure(figsize=(12,11)) # draw_court(outer_lines=True) # plt.scatter(table.LOC_X, table.LOC_Y,s=10) # plt.xlim(300,-300) # plt.ylim(-100,500) # plt.show() cmap = plt.cm.gist_heat_r joint_chart = sns.jointplot(table.LOC_X, table.LOC_Y, stat_func=None, kind='hex', space=0, color=cmap(0.2), cmap=cmap) joint_chart.fig.set_size_inches(12, 11) axis = joint_chart.ax_joint draw_court(axis) axis.set_xlim(250, -250) axis.set_ylim(422.5, -47.5) axis.set_xlabel('') axis.set_ylabel('') axis.tick_params(labelbottom='off', labelleft='off') plt.savefig("nbaapp\static/shot_chart.png")
def create_shot_chart(made_shots, missed_shots, filename, title, plot_type='hexbin', hex_size=2, **kwargs): made_x = np.array([shot.shot_x for shot in made_shots]) made_y = np.array([shot.shot_y for shot in made_shots]) missed_x = np.array([shot.shot_x for shot in missed_shots]) missed_y = np.array([shot.shot_y for shot in missed_shots]) num_made = float(len(made_shots)) num_missed = float(len(missed_shots)) frac_made = 100 * (num_made / (num_made + num_missed)) frac_missed = 100 - frac_made shot_distances_made = [euclidean(shot.shot_x, shot.shot_y) for shot in made_shots] shot_distances_missed = [euclidean(shot.shot_x, shot.shot_y) for shot in missed_shots] bins = np.linspace(0, 50, 26) frac_made_arr = np.zeros(len(bins)) shots_taken = np.zeros(len(bins)) for i, bin in enumerate(bins[:-1]): bin_made = [loc for loc in shot_distances_made if loc > bin and loc < bins[i + 1]] bin_missed = [loc for loc in shot_distances_missed if loc > bin and loc < bins[i + 1]] if len(bin_made) != 0 and len(bin_missed) != 0: frac_made_arr[i] = (float(len(bin_made)) / float(len(bin_made) + len(bin_missed))) shots_taken[i] = len(bin_made) + len(bin_missed) if plot_type == 'distance': mpl.clf() ax1 = mpl.subplot(111) # l1 = ax1.plot(bins, frac_made_arr * 100, 'go-', label='% made') ax2 = ax1.twinx() # l2 = ax2.plot(bins, shots_taken, 'rs-', label='shots taken') smooth_x = np.linspace(0, 40, 300) smooth_made = spline(bins, frac_made_arr * 100, smooth_x) smooth_taken = spline(bins, shots_taken, smooth_x) l1 = ax1.plot(smooth_x, smooth_made, 'g-', label='% made') l2 = ax2.plot(smooth_x, smooth_taken, 'r-', label='# shots taken') ax1.set_xlabel('Distance from basket') ax1.set_ylabel('Percentage made') ax2.set_ylabel('Number of shots taken') lns = l1 + l2 labels = [l.get_label() for l in lns] ax1.set_xlim(0, 40) ax2.set_ylim(0, 40) mpl.title(title) mpl.legend(lns, labels) ax1.grid(True) if plot_type == 'hexbin' or plot_type == 'hexbin_contour': return_cells = False if 'return_cells' in kwargs: return_cells = kwargs['return_cells'] hexes = create_hexes(hex_size) fig = mpl.figure() gs = gridspec.GridSpec(1, 2, width_ratios=[1, 10]) ax_cb = mpl.subplot(gs[0,0]) ax = mpl.subplot(gs[0,1]) draw_court(ax) for x, y in zip(made_x, made_y): cell = find_hex_from_xy(hexes, x, y, s=hex_size) if cell is not None: if is_shot_three(x, y): #print x, y, euclidean((x, y), (0, 0)) cell['threes'] += 1 cell['made'] += 1 else: ## this should never happen print 'made shot not in cell: ({}, {})'.format(x, y) for x, y in zip(missed_x, missed_y): cell = find_hex_from_xy(hexes, x, y, s=hex_size) if cell is not None: #if is_shot_three(x, y): # print x, y, euclidean((x, y), (0, 0)) cell['missed'] += 1 else: ## this should never happen print 'missed shot not in cell: ({}, {})'.format(x, y) max_attempts = max([cell['made'] + cell['missed'] for cell in hexes]) min_attempts = min([cell['made'] + cell['missed'] for cell in hexes if cell['made'] + cell['missed'] > 0]) total_attempts = sum([cell['made'] + cell['missed'] for cell in hexes]) max_attempts_frac = 100.0 * max_attempts / total_attempts min_attempts_frac = 100.0 * min_attempts / total_attempts #print 'max_attempts: {}, min_attempts: {}, total_attempts: {}'.format(max_attempts, min_attempts, total_attempts) #print 'max_attempts_frac: {}, min_attempts_frac: {}'.format(max_attempts_frac, min_attempts_frac) if 'scale_factor' in kwargs: max_attempts_frac = max_attempts_frac * kwargs['scale_factor'] else: # default scale factor # max_attempts_frac = min_attempts_frac * 64 pass max_size = hex_size min_size = hex_size / 8.0 if max_attempts > 1: m = (float(max_size) - min_size) / (max_attempts_frac - 1) b = min_size - m else: m = max_size / max_attempts_frac b = 0 #print 'm: {}, b: {}, max_size: {}, min_size: {}'.format(m, b, max_size, min_size) cm = mpl.cm.YlOrBr norm = Normalize(0, 1.5) total_made = 0 total_threes = 0 for cell in hexes: attempts = cell['made'] + cell['missed'] #total_attempts += attempts if attempts > 0: attempts_frac = 100.0 * attempts / total_attempts total_made += cell['made'] total_threes += cell['threes'] efg = (cell['made'] + 0.5 * cell['threes']) / attempts cell['efg'] = efg scaled_attempts = min(attempts_frac, max_attempts_frac) size = scaled_attempts * m + b #print size, scaled_attempts, attempts_frac, max_attempts_frac #print size if plot_type == 'hexbin' and not return_cells: cell['patch'] = RegularPolygon((cell['x'], cell['y']), 6, size, orientation=np.pi/6, color=cm(norm(efg)), alpha=0.75) outline = RegularPolygon((cell['x'], cell['y']), 6, hex_size, orientation=np.pi/6, fill=False, color='y', linestyle='dotted') ax.add_patch(cell['patch']) ax.add_patch(outline) if 'print_pct' in kwargs and kwargs['print_pct'] == True: ax.text(cell['x'] - 1, cell['y'] - 1, '{0:2.2f}'.format(attempts_frac)) if return_cells: return hexes if plot_type == 'hexbin': cb = ColorbarBase(ax_cb, cmap=cm, norm=norm, orientation='vertical') cb.set_label('Effective Field Goal Percentage') mpl.tight_layout() if plot_type == 'hexbin_contour': efg = [] bin_x = [cell['x'] for cell in hexes] bin_y = [cell['y'] for cell in hexes] efg = [cell['efg'] for cell in hexes] xi = np.linspace(-25, 25, 200) yi = np.linspace(0, 47.5, 200) zi = np.griddata(bin_x, bin_y, efg, xi, yi) mpl.contourf(xi, yi, zi, 5, cmap=mpl.cm.YlOrBr) mpl.colorbar() if 'overplot_shots' in kwargs: if kwargs['overplot_shots'] == True: mpl.plot(made_x, made_y, 'go') mpl.plot(missed_x, missed_y, 'rs') ax.text(0.02, 0.96, 'Total attempts: {}'.format(total_attempts), transform=ax.transAxes) ax.text(0.02, 0.93, 'Total made: {}'.format(total_made), transform=ax.transAxes) ax.text(0.02, 0.90, 'Total threes made: {}'.format(total_threes), transform=ax.transAxes) ax.text(0.02, 0.87, 'Total twos made: {}'.format(total_made - total_threes), transform=ax.transAxes) if total_attempts > 0: efg = 100 * (total_made + 0.5 * total_threes) / total_attempts else: efg = 0 ax.text(0.02, 0.84, 'eFG%: {0:2.2f}'.format(efg), transform=ax.transAxes) ax.set_title(title, fontsize='small') if plot_type == 'xo': mpl.plot(made_x, made_y, 'go') mpl.plot(missed_x, missed_y, 'rd') mpl.title(title) if plot_type == '3d': from mpl_toolkits.mplot3d import Axes3D fig = mpl.figure() ax = fig.gca(projection='3d') surf = ax.plot_surface(X, Y, frac_counts, cmap=mpl.cm.coolwarm) mpl.show() plot_dir = os.path.split(filename) if not os.path.exists(plot_dir[0]): os.makedirs(plot_dir[0]) mpl.savefig(filename)
def create_shot_chart(made_shots, missed_shots, filename, title, plot_type='hexbin', hex_size=2, **kwargs): made_x = np.array([shot.shot_x for shot in made_shots]) made_y = np.array([shot.shot_y for shot in made_shots]) missed_x = np.array([shot.shot_x for shot in missed_shots]) missed_y = np.array([shot.shot_y for shot in missed_shots]) num_made = float(len(made_shots)) num_missed = float(len(missed_shots)) frac_made = 100 * (num_made / (num_made + num_missed)) frac_missed = 100 - frac_made shot_distances_made = [ euclidean(shot.shot_x, shot.shot_y) for shot in made_shots ] shot_distances_missed = [ euclidean(shot.shot_x, shot.shot_y) for shot in missed_shots ] bins = np.linspace(0, 50, 26) frac_made_arr = np.zeros(len(bins)) shots_taken = np.zeros(len(bins)) for i, bin in enumerate(bins[:-1]): bin_made = [ loc for loc in shot_distances_made if loc > bin and loc < bins[i + 1] ] bin_missed = [ loc for loc in shot_distances_missed if loc > bin and loc < bins[i + 1] ] if len(bin_made) != 0 and len(bin_missed) != 0: frac_made_arr[i] = (float(len(bin_made)) / float(len(bin_made) + len(bin_missed))) shots_taken[i] = len(bin_made) + len(bin_missed) if plot_type == 'distance': mpl.clf() ax1 = mpl.subplot(111) # l1 = ax1.plot(bins, frac_made_arr * 100, 'go-', label='% made') ax2 = ax1.twinx() # l2 = ax2.plot(bins, shots_taken, 'rs-', label='shots taken') smooth_x = np.linspace(0, 40, 300) smooth_made = spline(bins, frac_made_arr * 100, smooth_x) smooth_taken = spline(bins, shots_taken, smooth_x) l1 = ax1.plot(smooth_x, smooth_made, 'g-', label='% made') l2 = ax2.plot(smooth_x, smooth_taken, 'r-', label='# shots taken') ax1.set_xlabel('Distance from basket') ax1.set_ylabel('Percentage made') ax2.set_ylabel('Number of shots taken') lns = l1 + l2 labels = [l.get_label() for l in lns] ax1.set_xlim(0, 40) ax2.set_ylim(0, 40) mpl.title(title) mpl.legend(lns, labels) ax1.grid(True) if plot_type == 'hexbin' or plot_type == 'hexbin_contour': return_cells = False if 'return_cells' in kwargs: return_cells = kwargs['return_cells'] hexes = create_hexes(hex_size) fig = mpl.figure() gs = gridspec.GridSpec(1, 2, width_ratios=[1, 10]) ax_cb = mpl.subplot(gs[0, 0]) ax = mpl.subplot(gs[0, 1]) draw_court(ax) for x, y in zip(made_x, made_y): cell = find_hex_from_xy(hexes, x, y, s=hex_size) if cell is not None: if is_shot_three(x, y): #print x, y, euclidean((x, y), (0, 0)) cell['threes'] += 1 cell['made'] += 1 else: ## this should never happen print 'made shot not in cell: ({}, {})'.format(x, y) for x, y in zip(missed_x, missed_y): cell = find_hex_from_xy(hexes, x, y, s=hex_size) if cell is not None: #if is_shot_three(x, y): # print x, y, euclidean((x, y), (0, 0)) cell['missed'] += 1 else: ## this should never happen print 'missed shot not in cell: ({}, {})'.format(x, y) max_attempts = max([cell['made'] + cell['missed'] for cell in hexes]) min_attempts = min([ cell['made'] + cell['missed'] for cell in hexes if cell['made'] + cell['missed'] > 0 ]) total_attempts = sum([cell['made'] + cell['missed'] for cell in hexes]) max_attempts_frac = 100.0 * max_attempts / total_attempts min_attempts_frac = 100.0 * min_attempts / total_attempts #print 'max_attempts: {}, min_attempts: {}, total_attempts: {}'.format(max_attempts, min_attempts, total_attempts) #print 'max_attempts_frac: {}, min_attempts_frac: {}'.format(max_attempts_frac, min_attempts_frac) if 'scale_factor' in kwargs: max_attempts_frac = max_attempts_frac * kwargs['scale_factor'] else: # default scale factor # max_attempts_frac = min_attempts_frac * 64 pass max_size = hex_size min_size = hex_size / 8.0 if max_attempts > 1: m = (float(max_size) - min_size) / (max_attempts_frac - 1) b = min_size - m else: m = max_size / max_attempts_frac b = 0 #print 'm: {}, b: {}, max_size: {}, min_size: {}'.format(m, b, max_size, min_size) cm = mpl.cm.YlOrBr norm = Normalize(0, 1.5) total_made = 0 total_threes = 0 for cell in hexes: attempts = cell['made'] + cell['missed'] #total_attempts += attempts if attempts > 0: attempts_frac = 100.0 * attempts / total_attempts total_made += cell['made'] total_threes += cell['threes'] efg = (cell['made'] + 0.5 * cell['threes']) / attempts cell['efg'] = efg scaled_attempts = min(attempts_frac, max_attempts_frac) size = scaled_attempts * m + b #print size, scaled_attempts, attempts_frac, max_attempts_frac #print size if plot_type == 'hexbin' and not return_cells: cell['patch'] = RegularPolygon((cell['x'], cell['y']), 6, size, orientation=np.pi / 6, color=cm(norm(efg)), alpha=0.75) outline = RegularPolygon((cell['x'], cell['y']), 6, hex_size, orientation=np.pi / 6, fill=False, color='y', linestyle='dotted') ax.add_patch(cell['patch']) ax.add_patch(outline) if 'print_pct' in kwargs and kwargs['print_pct'] == True: ax.text(cell['x'] - 1, cell['y'] - 1, '{0:2.2f}'.format(attempts_frac)) if return_cells: return hexes if plot_type == 'hexbin': cb = ColorbarBase(ax_cb, cmap=cm, norm=norm, orientation='vertical') cb.set_label('Effective Field Goal Percentage') mpl.tight_layout() if plot_type == 'hexbin_contour': efg = [] bin_x = [cell['x'] for cell in hexes] bin_y = [cell['y'] for cell in hexes] efg = [cell['efg'] for cell in hexes] xi = np.linspace(-25, 25, 200) yi = np.linspace(0, 47.5, 200) zi = np.griddata(bin_x, bin_y, efg, xi, yi) mpl.contourf(xi, yi, zi, 5, cmap=mpl.cm.YlOrBr) mpl.colorbar() if 'overplot_shots' in kwargs: if kwargs['overplot_shots'] == True: mpl.plot(made_x, made_y, 'go') mpl.plot(missed_x, missed_y, 'rs') ax.text(0.02, 0.96, 'Total attempts: {}'.format(total_attempts), transform=ax.transAxes) ax.text(0.02, 0.93, 'Total made: {}'.format(total_made), transform=ax.transAxes) ax.text(0.02, 0.90, 'Total threes made: {}'.format(total_threes), transform=ax.transAxes) ax.text(0.02, 0.87, 'Total twos made: {}'.format(total_made - total_threes), transform=ax.transAxes) if total_attempts > 0: efg = 100 * (total_made + 0.5 * total_threes) / total_attempts else: efg = 0 ax.text(0.02, 0.84, 'eFG%: {0:2.2f}'.format(efg), transform=ax.transAxes) ax.set_title(title, fontsize='small') if plot_type == 'xo': mpl.plot(made_x, made_y, 'go') mpl.plot(missed_x, missed_y, 'rd') mpl.title(title) if plot_type == '3d': from mpl_toolkits.mplot3d import Axes3D fig = mpl.figure() ax = fig.gca(projection='3d') surf = ax.plot_surface(X, Y, frac_counts, cmap=mpl.cm.coolwarm) mpl.show() plot_dir = os.path.split(filename) if not os.path.exists(plot_dir[0]): os.makedirs(plot_dir[0]) mpl.savefig(filename)