import streamlit as st import pandas as pd import matplotlib.pyplot as plt from matplotlib.patches import Circle, Rectangle, Arc import matplotlib.colors def seasons_of_player( playerId ): df = pd.read_html('https://www.basketball-reference.com/players/%s.html' % (playerId) ) try: seasons = df[0]['Season'] games_played = pd.to_numeric(df[0]['G'], errors='coerce') except: seasons = df[1]['Season'] games_played = pd.to_numeric(df[1]['G'], errors='coerce') seasons_played = seasons[ games_played>0 ] seasons_with_shots = [s for s in seasons_played if '-' in s and (int(s.split('-')[0])>=1996)] return seasons_with_shots st.set_page_config(page_title='NBA shots', page_icon=":basketball:") st.sidebar.title('Mapping NBA shots') if False: playerId = { 'Ray Allen':'a/allenra02', 'Kobe Bryant':'b/bryanko01', 'Stephen Curry':'c/curryst01', 'James Harden':'h/hardeja01', 'Allen Iverson':'i/iversal01', 'Michael Jordan':'j/jordami01', 'Damian Lillard':'l/lillada01', 'Karl Malone':'m/malonka01', 'Reggie Miller':'m/millere01', 'Dirk Nowitzki':'n/nowitdi01', "Shaquille O'Neal":'o/onealsh01', 'Trae Young':'y/youngtr01', 'Victor Wembanyama':'w/wembavi01', } else: import json playerId = json.load(open("all_player_names.txt")) selected = st.sidebar.selectbox('Select or type a player name:', ['']+list(playerId.keys()), format_func=lambda x: '...' if x == '' else x) if selected: #st.success('Yay! 🎉') seasons_with_shots = seasons_of_player( playerId[selected] ) season = st.sidebar.selectbox('Season:',seasons_with_shots) if season: seasonYearEnd = str(int(season.split('-')[0]) + 1) urlShots = 'https://www.basketball-reference.com/players/%s/shooting/%s' % (playerId[selected],seasonYearEnd) else: st.warning('No player selected') urlShots = '' # Checkboxes: left, right = st.sidebar.columns(2) # Range slider: valuesRange = st.sidebar.slider( 'Percentage limits for "bad" and "good" shots:', 0.0, 100.0, (10.0, 50.0)) colorBAD = left.color_picker('bad', '#ff0000') colorGOOD = right.color_picker('good', '#97ff33') with left: draw_court_box = st.sidebar.checkbox('Draw court',value=True) with right: draw_title_box = st.sidebar.checkbox('Add title',value=True) 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 def html_to_shot_table( html ): full_table = [] for line in str(html).split('