def get_2d_data(wl_per_rosters, player_matrix): data = [] games = [] for game in wl_per_rosters[1:]: # home roster row = [] limit = min(len(game[1]), 13) for player in game[1][:limit]: if player not in player_matrix: if players.find_player_by_id(player) is not None: print("ERROR has occured!!") sys.exit(1) else: # Subtract from game id in order to get previous game stats stats = np.array( player_matrix[player][f"00{int(game[0]) - 1}"], dtype="float32") row.append(stats) while len(row) < 13: row.append(np.zeros(23, dtype="float32")) limit = min(len(game[1]), 13) for player in game[2][:limit]: if player not in player_matrix: if players.find_player_by_id(player) is not None: print("ERROR has occured!!") sys.exit(1) else: print("Player id not in data. skipping...") else: # Subtract from game id in order to get previous game stats stats = np.array( player_matrix[player][f"00{int(game[0]) - 1}"], dtype="float32") row.append(stats) while len(row) < 26: row.append(np.zeros(23, dtype="float32")) row = np.array(row, dtype="float32").flatten() if row.shape != (598, ): print("RED ALERT!") print(game) print(stats) sys.exit(1) data.append(row) games.append(int(game[0])) return np.array(data), np.array(games)
def getPlayerHeadshotURL(player_id: int) -> Optional[str]: static_info = players.find_player_by_id(player_id) if static_info is None or len(static_info) < 1: return None return f"https://ak-static.cms.nba.com/wp-content/uploads/headshots/nba/latest/260x190/{str(player_id)}.png"
def get_filtered_player_df(file_name, is_legends=False): csv.field_size_limit(sys.maxsize) res = pd.read_csv(file_name, header=None) all_games = [] keep_indices = [0, 1, -1, 16, 15, 17, 18, 19] for player_id, career in zip(res[0], res[1]): player = players.find_player_by_id(player_id)['full_name'] print(f'{player} selected.') career_arc = ast.literal_eval(career) for game in career_arc: # in this case, temp = [game[i] for i in keep_indices] temp.insert(0, player_id) temp.insert(0, player) all_games.append(temp) # each python list of each game filtered_player_df = pd.DataFrame(all_games, columns=[ 'Name', 'ID', 'Date', 'Team', 'PTS', 'AST', 'REB', 'STL', 'BLK', 'TOV' ]) filtered_player_df.to_csv( 'filtered_legends.csv') if is_legends else filtered_player_df.to_csv( 'filtered_players.csv')
def find_players(player_name): found_players = {} if player_name.isdigit(): found_players = [players.find_player_by_id(player_name)] else: found_players = players.find_players_by_full_name(player_name) return found_players
def by_season(year, debug=False, games_thresh=0, headers=None): ''' given a year, gets all players in a dataframe args: `year`: str: year, like `2019-20` `debug`: bool: if we want to print out dataframe `games_thresh`: int: take out players who player <= `games_thresh` games ''' # given the year, gets all of the players in 1 call p = leaguedashplayerstats.LeagueDashPlayerStats( per_mode_detailed='PerGame', season='2019-20', headers=headers) data = p.league_dash_player_stats.data['data'] # all the columns we want for clustering columns = np.array([ 'PlayerID', 'GP', 'PTS', 'AST', 'REB', 'STL', 'BLK', 'TOV', 'FT_PCT', 'FG_PCT', 'FG3_PCT', 'FTA', 'FGA', 'FG3A', 'MIN', 'PLUS_MINUS' ]) r = len(data) c = len(columns) # store players into matrix with r players (rows) and c columns players_arr = np.zeros((r, c)) # non-empty data if data != []: # these are the indices that are used for the columns, this is what stats.nba.com decided num = np.array( [0, 5, 29, 22, 21, 24, 25, 23, 18, 12, 15, 17, 11, 14, 9, 30]) for i, player in enumerate(data): try: # print if player's name name = players.find_player_by_id(player[0])['full_name'] print(f'{name} found.') except: # name not found print('Player name not found') for j, n in enumerate(num): # populate matrix with data players_arr[i, j] = player[n] # convert matrix and cols to df to store in csv on disk df = pd.DataFrame(players_arr, columns=columns) to_int = ['PlayerID', 'GP'] # only columns that need to be int df[to_int] = df[to_int].astype(int) df_filtered = df[df['GP'] > games_thresh] if debug: print(df_filtered) # also export to csv, so you only have to run it once. df_filtered.to_csv(f'data/{year}_nba_players.csv') return df_filtered
def get_season(self, player_id, dictionary): # get the seasons that player_id played career = playercareerstats.PlayerCareerStats(player_id=player_id) # get all of the seasons a player played in arr = list(career.get_data_frames()[0]['SEASON_ID'].values) name = players.find_player_by_id(player_id)['full_name'] # print the name for a measure of the speed of this program. print(f'{name} processed.') player_dict = {player_id: arr} # update the dictionary in shared memory dictionary.update(player_dict)
def build_basic_shotchart(the_player, season, season_type): player_name = players.find_player_by_id(the_player).get('full_name') response = shotchartdetail.ShotChartDetail( team_id=0, player_id=the_player, season_nullable=season, season_type_all_star=season_type, context_measure_simple='FGA') df = response.get_data_frames()[0] made_shots = df[df['SHOT_MADE_FLAG'] == 1] missed_shots = df[df['SHOT_MADE_FLAG'] == 0] fig = go.Figure() fig.add_trace( go.Scatter( # made shots x=made_shots['LOC_X'], y=made_shots['LOC_Y'], mode='markers', name='Made Shot', hoverinfo='skip', marker=dict( size=5, cmax=40, cmin=-40, color="#008000", ), )) fig.add_trace( go.Scatter( # missed shots x=missed_shots['LOC_X'], y=missed_shots['LOC_Y'], mode='markers', name='Missed Shot', hoverinfo='skip', marker=dict( size=5, cmax=40, cmin=-40, color="#FF0000", ), )) draw_court(fig) fig.update_layout(title={ 'text': player_name + " , " + str(season), 'y': 1, 'x': 0.42, 'xanchor': 'center', 'yanchor': 'top' }, xaxis_title='Basic Shot Chart', font=dict(family="Rockwell", size=15, color="#000000"), dragmode=False) return fig
def text_display_cluster(self): ''' displays all of the groups that every player is in after `fit()` is run, as well their corresponding centroid. ''' for i, p in enumerate(self.x): name_obj = players.find_player_by_id(self.names[i]) if name_obj != None: name = name_obj['full_name'] print( f'{name}: Group {self.labels[i]} with centroid {self.centroids[self.labels[i]]}' )
def display_shot_charts(player, season, season_type): shots_df, league_avg = get_player_shotchartdetail(player, season, season_type) name = players.find_player_by_id(player)['full_name'] shot_fig = go.Figure() heat_fig = go.Figure() hex_fig = go.Figure() if int(season[:4]) >= 1996: make_shot_chart(shot_fig, shots_df, name, season) draw_plotly_court(shot_fig) make_heatmap(heat_fig, shots_df, name, season) draw_plotly_court(heat_fig, layer='above') make_hexbin(hex_fig, shots_df, league_avg, 'p', name, season) draw_plotly_court(hex_fig) else: draw_plotly_court(shot_fig) shot_fig.update_layout( title={ 'text': 'No Shot Chart Data', 'y': 0.98, 'x': 0.5, 'xanchor': 'center', 'yanchor': 'top' }) draw_plotly_court(heat_fig) heat_fig.update_layout( title={ 'text': 'No Shot Chart Data', 'y': 0.98, 'x': 0.5, 'xanchor': 'center', 'yanchor': 'top' }) draw_plotly_court(hex_fig) hex_fig.update_layout( title={ 'text': 'No Shot Chart Data', 'y': 0.98, 'x': 0.5, 'xanchor': 'center', 'yanchor': 'top' }) return shot_fig, heat_fig, hex_fig
def get_common_teammates(p1name, p2name): ''' Get all common teammates of the players listed ''' print 'Getting players ...' p1name, p1id = get_player_id(p1name) p2name, p2id = get_player_id(p2name) print 'Getting careers ...' p1career = playercareerstats.PlayerCareerStats(p1id) sleep(0.2) p2career = playercareerstats.PlayerCareerStats(p2id) sleep(0.2) p1teamsszns = [ (d['TEAM_ID'], d['SEASON_ID']) for d in p1career.get_normalized_dict()['SeasonTotalsRegularSeason'] if d['TEAM_ID'] != 0 ] p2teamsszns = [ (d['TEAM_ID'], d['SEASON_ID']) for d in p2career.get_normalized_dict()['SeasonTotalsRegularSeason'] if d['TEAM_ID'] != 0 ] print 'Getting teammates ...' p1teammates = set() for tid, szn in tqdm(p1teamsszns, desc=p1name): p1teammates.update(get_szn_teammates(tid, szn)) sleep(0.2) p1teammates.remove(p1id) p2teammates = set() for tid, szn in tqdm(p2teamsszns, desc=p2name): p2teammates.update(get_szn_teammates(tid, szn)) sleep(0.2) p2teammates.remove(p2id) common = p1teammates.intersection(p2teammates) commoninfo = [players.find_player_by_id(i) for i in common] for p in commoninfo: print p['full_name'] # get_common_teammates('rajon rondo', 'chris paul')
async def getPlayerCareerStatsByID(player_id: int, use_proxy: Optional[bool] = None ) -> Optional[dict]: static_info = players.find_player_by_id(player_id) if static_info is None or len(static_info) < 1: return None stats_dict = {} common_info_response = await ProxiedEndpoint( CommonPlayerInfo, player_id=static_info.get('id'), use_proxy=use_proxy) await asyncio.sleep(0) career_stats_response = await ProxiedEndpoint( PlayerCareerStats, player_id=static_info.get('id'), use_proxy=use_proxy) common_info = common_info_response.get_normalized_dict().get( 'CommonPlayerInfo')[0] career_stats = career_stats_response.get_normalized_dict().get( 'CareerTotalsRegularSeason')[0] stats_dict['FROM_YEAR'] = common_info.get('FROM_YEAR') stats_dict['TO_YEAR'] = common_info.get('TO_YEAR') stats_dict['TEAM_COLOR'] = getTeamColor(common_info.get('TEAM_ID')) stats_dict['TEAM_CITY'] = common_info.get('TEAM_CITY') stats_dict['TEAM_NAME'] = common_info.get('TEAM_NAME') stats_dict['JERSEY'] = common_info.get('JERSEY') stats_dict['POSITION'] = common_info.get('POSITION') stats_dict['HEIGHT'] = common_info.get('HEIGHT') stats_dict['WEIGHT'] = common_info.get('WEIGHT') stats_dict['PTS'] = career_stats.get('PTS') stats_dict['AST'] = career_stats.get('AST') stats_dict['BLK'] = career_stats.get('BLK') stats_dict['STL'] = career_stats.get('STL') stats_dict['REB'] = career_stats.get('REB') stats_dict['OREB'] = career_stats.get('OREB') stats_dict['DREB'] = career_stats.get('DREB') stats_dict['DRAFT_YEAR'] = common_info.get('DRAFT_YEAR') stats_dict['DRAFT_ROUND'] = common_info.get('DRAFT_ROUND') stats_dict['DRAFT_NUMBER'] = common_info.get('DRAFT_NUMBER') return stats_dict
def get_random_player(file_name): def need_s(num): return 's' if num != 1 else '' csv.field_size_limit(sys.maxsize) # the rows are really long! res = pd.read_csv(file_name, header=None) r = np.random.randint(0, len(res.values)) arr = ast.literal_eval(res.values[r][1]) player = players.find_player_by_id(res.values[r][0])['full_name'] print(f'{player} selected.') r_idx = np.random.randint(0, len(arr)) game = arr[r_idx] x = f'On {game[0]}, {player} scored {game[-1]} point{need_s(game[-1])}, dished out '\ f'{game[16]} assist{need_s(game[16])}, grabbed {game[15]} rebound{need_s(game[15])}, '\ f'had {game[17]} steal{need_s(game[17])}, and had {game[18]} block{need_s(game[18])}.' print(x) return player, arr
async def getPlayerCareerString(player_id: int) -> Optional[str]: static_info = players.find_player_by_id(player_id) #If that id doesn't return a player, return None if static_info is None or len(static_info) < 1: return None ret_str = f"**Player {str(static_info.get('id'))}: {static_info.get('full_name')}**" ret_str += "\n\tStatus: " if static_info.get('is_active'): ret_str += "Active" else: ret_str += "Inactive" # get the rest of the data from the NBA api endpoint # might want to change this to DataFrame if we need it for graphing later all_info = await getPlayerCareerStatsByID(player_id) ret_str += f" ({all_info.get('FROM_YEAR')}-{all_info.get('TO_YEAR')})" ret_str += f"\n\t{all_info.get('TEAM_CITY')} {all_info.get('TEAM_NAME')} #{all_info.get('JERSEY')}: {all_info.get('POSITION')}" #split the height into separate feet and inches for formatting height = all_info.get('HEIGHT').split('-') ret_str += f"\n\tHeight: {height[0]}\'{height[1]}\", Weight: {all_info.get('WEIGHT')} lbs" #career stats ret_str += "\n\n\t*Career Stats (Regular Season):*" ret_str += f"\n\tPoints: {all_info.get('PTS')}" ret_str += f"\n\tAssists: {all_info.get('AST')}" ret_str += f"\n\tBlocks: {all_info.get('BLK')}" ret_str += f"\n\tSteals: {all_info.get('STL')}" ret_str += f"\n\tRebounds: {all_info.get('REB')}" ret_str += f"\n\t Offensive: {all_info.get('OREB')}" ret_str += f"\n\t Defensive: {all_info.get('DREB')}" return ret_str
def get_every_game_season(self, player_id, season_dict, season_games_dict): # go through every season for a player, get all of the games name = players.find_player_by_id(player_id)['full_name'] res = [] for year in season_dict[player_id]: # http request is made here player_season = playergamelog.PlayerGameLog(player_id, season=year) print(f'{name} - {year}') # ignore empty data if player_season.player_game_log.data['data'] != []: # played some time # all games in a season for game in player_season.player_game_log.data['data']: temp = [] for i in range(3, 25): # indices 3 to 25 give the important stats temp.append(game[i]) res.append(temp) player_dict = {player_id: res} season_games_dict.update(player_dict) # update shared dictionary print(f'{name} processed.')
def __init__(self, id, per_mode): self.dict = players.find_player_by_id(id) self.name = self.dict['full_name'] self.playerstats = playercareerstats.PlayerCareerStats( id, per_mode36=per_mode).get_data_frames()[0]
for row in reader: #First check if field has an ID instead of a name player_id = None try: player_id = int(row[CORRECT_INDEX]) except ValueError: pass # If it's not an ID, get the player by their name if player_id is None: players_dict = players.find_players_by_full_name( row[CORRECT_INDEX]) else: players_dict = [players.find_player_by_id(player_id)] # Don't run the test if we don't know what the solution should be if not len(players_dict) == 1: print(f"Couldn't find player matching {row[CORRECT_INDEX]}") else: print(f"\"{row[MISSPELLED_INDEX]}\" ", end='') # Figure out which mode the fuzzy code is going to run in player_names = row[MISSPELLED_INDEX].split() if len(player_names) == 1: stats_dict = one_stats_dict print('(First or last name mode)') elif len(player_names) == 2: stats_dict = two_stats_dict print('(First and last name mode)')
def plot(self, disp_names=False, thresh=0.8, single_name='', interactive=False): ''' plots the cluster points. `disp_names`: `bool`: selects whether to display some players' names or not. `thresh`: `float`, between `0` and `1`: given each dimensions max value, take `thresh * 100%` of that to show names. `single_name`: `str`: If the user wants to see where a specific player is classified, they can do so here. `interactive`: `bool`: If the user wants to be able to interact with the plot after each clustering `fit` is run. ''' self.priority_name_index = -1 player = players.find_players_by_full_name(single_name) if len(player) == 1: # there is a valid player with the name self.p_id = player[0]['id'] index = np.where(np.array(self.names) == self.p_id) if len(index) == 1: # player does in fact exist self.priority_name_index = index[0][0] # groups self.color_labels = [f'Group {i+1}' for i in range(self.num_clusters)] groups = [[] for i in range(self.num_clusters)] group_labels = [[] for i in range(self.num_clusters)] for i, p in enumerate(self.x): groups[self.labels[i]].append(p) group_labels[self.labels[i]].append(self.labels[i]) groups = np.array(groups) if len(self.dim_vals) == 1: pass elif len(self.dim_vals) == 2: # 2-d visualization fig, ax = plt.subplots() # for i,group in enumerate(groups): # g = np.array(group) # plt.scatter(g[::,0], g[::,1], c=self.labels, label=self.color_labels) ax.scatter(self.x[::, 0], self.x[::, 1], c=self.labels) # plt.xlabel('f') ax.set_xlabel(self.ordered_dims[0]) ax.set_ylabel(self.ordered_dims[1]) dim1_thresh = np.max(self.x[::, 0]) * thresh dim2_thresh = np.max(self.x[::, 1]) * thresh # if we want to display themes, find players with high values, and show the name on the plot if disp_names: for i, p in enumerate(self.x): if p[0] > dim1_thresh or p[1] > dim2_thresh: name_obj = players.find_player_by_id(self.names[i]) if name_obj != None: name = name_obj['full_name'] ax.text(p[0], p[1], name) # look for player with priority name index, which is when a user wants a player's name to be # shown in the graph itself for i, p in enumerate(self.x): if i == self.priority_name_index: name_obj = players.find_player_by_id(self.names[i]) if name_obj != None: name = name_obj['full_name'] ax.text(p[0], p[1], name) elif len(self.dim_vals) == 3: # 3d visualization # kudos to matplotlib with good example of showing how this works fig = plt.figure() ax = Axes3D(fig) ax.scatter(xs=self.x[::, 0], ys=self.x[::, 1], zs=self.x[::, 2], c=self.labels) ax.set_xlabel(self.ordered_dims[0]) ax.set_ylabel(self.ordered_dims[1]) ax.set_zlabel(self.ordered_dims[2]) dim1_thresh = np.max(self.x[::, 0]) * thresh dim2_thresh = np.max(self.x[::, 1]) * thresh dim3_thresh = np.max(self.x[::, 2]) * thresh # similar to 2d plot, display names that are high on one or more axes if disp_names: for i, p in enumerate(self.x): if p[0] > dim1_thresh or p[1] > dim2_thresh or p[ 2] > dim3_thresh: name_obj = players.find_player_by_id(self.names[i]) if name_obj != None: name = name_obj['full_name'] ax.text(p[0], p[1], p[2], name) # display name if important for i, p in enumerate(self.x): if i == self.priority_name_index: name_obj = players.find_player_by_id(self.names[i]) if name_obj != None: name = name_obj['full_name'] ax.text(p[0], p[1], p[2], name) # save all of the graphs to a png file # if pca was performed # method type # year # k value # along with fields/dimensions clustering was performed. is_dr = '' if not self.reduced else '-with-PCA' rounded_ssd = np.round(self.ssd, 4) title = f'{self.method}-k={self.num_clusters}-{self.cols}-{self.year}{is_dr}' plt.title(f'{title}-ssd={rounded_ssd}') plt.savefig(f'img/{title}') # also can be toggled in 3-d, fun stuff if interactive: plt.show() # close plot. plt.close()
from nba_api.stats.static import teams team_list = teams.get_teams() for team in team_list: print(team['full_name']) from nba_api.stats.static import players stephen_curry = players.find_player_by_id(201939) print(stephen_curry['full_name']) from nba_api.stats.endpoints import commonplayerinfo # Basic Request player_info = commonplayerinfo.CommonPlayerInfo(player_id=2544) lebron_stats = player_info.player_headline_stats.get_dict() print(lebron_stats['data']) from nba_api.stats.endpoints import commonteamroster import json roster_info = commonteamroster.CommonTeamRoster(season=2017, team_id=1610612739) roster_cavs = roster_info.get_dict() with open('nba.json', 'w') as fp: json.dump(roster_cavs, fp, indent=3)
async def getPlayerSeasonStatsByID(player_id: int, season_id: str = Season.current_season, use_proxy=None) -> Optional[dict]: static_info = players.find_player_by_id(player_id) if static_info is None or len(static_info) < 1: return None all_seasons_response = await ProxiedEndpoint( PlayerCareerStats, player_id=static_info.get('id'), use_proxy=use_proxy) await asyncio.sleep(0) all_seasons = all_seasons_response.get_normalized_dict().get( 'SeasonTotalsRegularSeason') target_season = None for season in all_seasons: if season.get('SEASON_ID') == season_id: target_season = season break if target_season is None: return None else: common_info_response = await ProxiedEndpoint( CommonPlayerInfo, player_id=static_info.get('id'), use_proxy=use_proxy) common_info = common_info_response.get_normalized_dict().get( 'CommonPlayerInfo')[0] stats_dict = {} stats_dict['FROM_YEAR'] = common_info.get('FROM_YEAR') stats_dict['TO_YEAR'] = common_info.get('TO_YEAR') stats_dict['TEAM_COLOR'] = getTeamColor(common_info.get('TEAM_ID')) stats_dict['TEAM_CITY'] = common_info.get('TEAM_CITY') stats_dict['TEAM_NAME'] = common_info.get('TEAM_NAME') stats_dict['JERSEY'] = common_info.get('JERSEY') stats_dict['POSITION'] = common_info.get('POSITION') stats_dict['HEIGHT'] = common_info.get('HEIGHT') stats_dict['WEIGHT'] = common_info.get('WEIGHT') stats_dict['SEASON_ID'] = target_season.get('SEASON_ID') stats_dict['GP'] = target_season.get('GP') stats_dict['GS'] = target_season.get('GS') stats_dict['MIN'] = target_season.get('MIN') stats_dict['PTS'] = target_season.get('PTS') stats_dict['AST'] = target_season.get('AST') stats_dict['BLK'] = target_season.get('BLK') stats_dict['STL'] = target_season.get('STL') stats_dict['REB'] = target_season.get('REB') stats_dict['OREB'] = target_season.get('OREB') stats_dict['DREB'] = target_season.get('DREB') stats_dict['PPG'] = round( target_season.get('PTS') / target_season.get('GP'), 1) stats_dict['RPG'] = round( target_season.get('REB') / target_season.get('GP'), 1) stats_dict['APG'] = round( target_season.get('AST') / target_season.get('GP'), 1) stats_dict['BPG'] = round( target_season.get('BLK') / target_season.get('GP'), 1) stats_dict['SPG'] = round( target_season.get('STL') / target_season.get('GP'), 1) return stats_dict