James McCool commited on
Commit
36150d4
·
1 Parent(s): e4858f7

added UI updates and second tab

Browse files
Files changed (1) hide show
  1. src/streamlit_app.py +159 -65
src/streamlit_app.py CHANGED
@@ -17,8 +17,45 @@ percentages_format = {'Pts% Boost': '{:.2%}', 'Reb% Boost': '{:.2%}', 'Ast% Boos
17
  'Stl Boost%': '{:.2%}', 'Blk Boost%': '{:.2%}', 'TOV Boost%': '{:.2%}', 'FPPM Boost': '{:.2%}',
18
  'Team FPPM Boost': '{:.2%}'}
19
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
20
  @st.cache_resource(ttl = 600)
21
- def init_baselines():
22
 
23
  json_matchups = requests.get(NBA_DATA + '?sheet=DEM%20Matchups').json()
24
  raw_display = pd.DataFrame(json_matchups)
@@ -26,8 +63,10 @@ def init_baselines():
26
  matchups = raw_display[raw_display['Var'] != ""]
27
  matchups_dict = dict(zip(matchups['Team'], matchups['Opp']))
28
 
29
- json_pg_dem = requests.get(NBA_DATA + '?sheet=PG_DEM_Calc').json()
30
- raw_display = pd.DataFrame(json_pg_dem)
 
 
31
  raw_display = raw_display.reset_index(drop=True)
32
  cols_to_check = ['Pts% Boost', 'Reb% Boost', 'Ast% Boost', '3p% Boost', 'Stl Boost%', 'Blk Boost%', 'TOV Boost%', 'FPPM Boost']
33
  raw_display.loc[:, cols_to_check] = raw_display.loc[:, cols_to_check].replace({'%': ''}, regex=True).astype(float) / 100
@@ -35,8 +74,7 @@ def init_baselines():
35
  raw_display['position'] = 'Point Guard'
36
  pg_dem = raw_display[raw_display['Acro'] != ""]
37
 
38
- json_sg_dem = requests.get(NBA_DATA + '?sheet=SG_DEM_Calc').json()
39
- raw_display = pd.DataFrame(json_sg_dem)
40
  raw_display = raw_display.reset_index(drop=True)
41
  cols_to_check = ['Pts% Boost', 'Reb% Boost', 'Ast% Boost', '3p% Boost', 'Stl Boost%', 'Blk Boost%', 'TOV Boost%', 'FPPM Boost']
42
  raw_display.loc[:, cols_to_check] = raw_display.loc[:, cols_to_check].replace({'%': ''}, regex=True).astype(float) / 100
@@ -44,8 +82,7 @@ def init_baselines():
44
  raw_display['position'] = 'Shooting Guard'
45
  sg_dem = raw_display[raw_display['Acro'] != ""]
46
 
47
- json_sf_dem = requests.get(NBA_DATA + '?sheet=SF_DEM_Calc').json()
48
- raw_display = pd.DataFrame(json_sf_dem)
49
  raw_display = raw_display.reset_index(drop=True)
50
  cols_to_check = ['Pts% Boost', 'Reb% Boost', 'Ast% Boost', '3p% Boost', 'Stl Boost%', 'Blk Boost%', 'TOV Boost%', 'FPPM Boost']
51
  raw_display.loc[:, cols_to_check] = raw_display.loc[:, cols_to_check].replace({'%': ''}, regex=True).astype(float) / 100
@@ -53,8 +90,7 @@ def init_baselines():
53
  raw_display['position'] = 'Small Forward'
54
  sf_dem = raw_display[raw_display['Acro'] != ""]
55
 
56
- json_pf_dem = requests.get(NBA_DATA + '?sheet=PF_DEM_Calc').json()
57
- raw_display = pd.DataFrame(json_pf_dem)
58
  raw_display = raw_display.reset_index(drop=True)
59
  cols_to_check = ['Pts% Boost', 'Reb% Boost', 'Ast% Boost', '3p% Boost', 'Stl Boost%', 'Blk Boost%', 'TOV Boost%', 'FPPM Boost']
60
  raw_display.loc[:, cols_to_check] = raw_display.loc[:, cols_to_check].replace({'%': ''}, regex=True).astype(float) / 100
@@ -62,8 +98,7 @@ def init_baselines():
62
  raw_display['position'] = 'Power Forward'
63
  pf_dem = raw_display[raw_display['Acro'] != ""]
64
 
65
- json_c_dem = requests.get(NBA_DATA + '?sheet=C_DEM_Calc').json()
66
- raw_display = pd.DataFrame(json_c_dem)
67
  raw_display = raw_display.reset_index(drop=True)
68
  cols_to_check = ['Pts% Boost', 'Reb% Boost', 'Ast% Boost', '3p% Boost', 'Stl Boost%', 'Blk Boost%', 'TOV Boost%', 'FPPM Boost']
69
  raw_display.loc[:, cols_to_check] = raw_display.loc[:, cols_to_check].replace({'%': ''}, regex=True).astype(float) / 100
@@ -85,60 +120,119 @@ def init_baselines():
85
 
86
  return export_dem, matchups, matchups_dict
87
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
88
  def convert_df_to_csv(df):
89
  return df.to_csv().encode('utf-8')
90
 
91
- overall_dem, matchups, matchups_dict = init_baselines()
92
-
93
- col1, col2 = st.columns([1, 9])
94
- with col1:
95
- if st.button("Reset Data", key='reset1'):
96
- st.cache_data.clear()
97
- overall_dem, matchups, matchups_dict = init_baselines()
98
- split_var1 = st.radio("View all teams or just this main slate's matchups?", ('Slate Matchups', 'All'), key='split_var1')
99
- if split_var1 == 'Slate Matchups':
100
- view_var1 = matchups.Opp.values.tolist()
101
- split_var2 = st.radio("Would you like to view all teams or specific ones?", ('All', 'Specific Teams'), key='split_var2')
102
- if split_var2 == 'Specific Teams':
103
- team_var1 = st.multiselect('Which teams would you like to include in the tables?', options = view_var1, key='team_var1')
104
- elif split_var2 == 'All':
105
- team_var1 = view_var1
106
- split_var3 = st.radio("Would you like to view all positions or specific ones?", ('All', 'Specific Positions'), key='split_var3')
107
- if split_var3 == 'Specific Positions':
108
- pos_var1 = st.multiselect('Which teams would you like to include in the tables?', options = overall_dem['position'].unique(), key='pos_var1')
109
- elif split_var3 == 'All':
110
- pos_var1 = overall_dem.position.values.tolist()
111
- if split_var1 == 'All':
112
- split_var2 = st.radio("Would you like to view all teams or specific ones?", ('All', 'Specific Teams'), key='split_var2')
113
- if split_var2 == 'Specific Teams':
114
- team_var1 = st.multiselect('Which teams would you like to include in the tables?', options = overall_dem['Acro'].unique(), key='team_var1')
115
- elif split_var2 == 'All':
116
- team_var1 = overall_dem.Acro.values.tolist()
117
- split_var3 = st.radio("Would you like to view all positions or specific ones?", ('All', 'Specific Positions'), key='split_var3')
118
- if split_var3 == 'Specific Positions':
119
- pos_var1 = st.multiselect('Which teams would you like to include in the tables?', options = overall_dem['position'].unique(), key='pos_var1')
120
- elif split_var3 == 'All':
121
- pos_var1 = overall_dem.position.values.tolist()
122
- with col2:
123
- if split_var1 == 'Slate Matchups':
124
- dem_display = overall_dem[overall_dem['Acro'].isin(view_var1)]
125
- dem_display['Team (Getting Boost)'] = dem_display['Acro'].map(matchups_dict)
126
- dem_display.rename(columns={"Acro": "Opp (Giving Boost)"}, inplace = True)
127
- dem_display = dem_display[['Team (Getting Boost)', 'Opp (Giving Boost)', 'G', 'Pts% Boost', 'Reb% Boost', 'Ast% Boost', '3p% Boost',
128
- 'Stl Boost%', 'Blk Boost%', 'TOV Boost%', 'FPPM', 'FPPM Boost', 'Team FPPM Boost', 'position']]
129
- dem_display = dem_display[dem_display['Team (Getting Boost)'].isin(team_var1)]
130
- dem_display = dem_display[dem_display['position'].isin(pos_var1)]
131
- dem_display = dem_display.sort_values(by='FPPM Boost', ascending=False)
132
- elif split_var1 == 'All':
133
- dem_display = overall_dem[overall_dem['Acro'].isin(team_var1)]
134
- dem_display = dem_display[dem_display['position'].isin(pos_var1)]
135
- dem_display = dem_display.sort_values(by='FPPM Boost', ascending=False)
136
- dem_display.rename(columns={"Team": "Team (Giving Boost)"}, inplace = True)
137
- dem_display = dem_display.set_index('Team (Giving Boost)')
138
- st.dataframe(dem_display.style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').format(percentages_format, precision=2), use_container_width = True)
139
- st.download_button(
140
- label="Export DEM Numbers",
141
- data=convert_df_to_csv(overall_dem),
142
- file_name='DEM_export.csv',
143
- mime='text/csv',
144
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
17
  'Stl Boost%': '{:.2%}', 'Blk Boost%': '{:.2%}', 'TOV Boost%': '{:.2%}', 'FPPM Boost': '{:.2%}',
18
  'Team FPPM Boost': '{:.2%}'}
19
 
20
+ st.markdown("""
21
+ <style>
22
+ /* Tab styling */
23
+ .stElementContainer [data-baseweb="button-group"] {
24
+ gap: 2.000rem;
25
+ padding: 4px;
26
+ }
27
+ .stElementContainer [kind="segmented_control"] {
28
+ height: 2.000rem;
29
+ white-space: pre-wrap;
30
+ background-color: #DAA520;
31
+ color: white;
32
+ border-radius: 20px;
33
+ gap: 1px;
34
+ padding: 10px 20px;
35
+ font-weight: bold;
36
+ transition: all 0.3s ease;
37
+ }
38
+ .stElementContainer [kind="segmented_controlActive"] {
39
+ height: 3.000rem;
40
+ background-color: #DAA520;
41
+ border: 3px solid #FFD700;
42
+ border-radius: 10px;
43
+ color: black;
44
+ }
45
+ .stElementContainer [kind="segmented_control"]:hover {
46
+ background-color: #FFD700;
47
+ cursor: pointer;
48
+ }
49
+
50
+ div[data-baseweb="select"] > div {
51
+ background-color: #DAA520;
52
+ color: white;
53
+ }
54
+
55
+ </style>""", unsafe_allow_html=True)
56
+
57
  @st.cache_resource(ttl = 600)
58
+ def init_DEM():
59
 
60
  json_matchups = requests.get(NBA_DATA + '?sheet=DEM%20Matchups').json()
61
  raw_display = pd.DataFrame(json_matchups)
 
63
  matchups = raw_display[raw_display['Var'] != ""]
64
  matchups_dict = dict(zip(matchups['Team'], matchups['Opp']))
65
 
66
+ master_dem_json = requests.get(NBA_DATA + '?sheet=Master_DEM_Calc').json()
67
+ master_dem_frame = pd.DataFrame(master_dem_json)
68
+
69
+ raw_display = master_dem_frame[master_dem_frame['Position'] == 'PG']
70
  raw_display = raw_display.reset_index(drop=True)
71
  cols_to_check = ['Pts% Boost', 'Reb% Boost', 'Ast% Boost', '3p% Boost', 'Stl Boost%', 'Blk Boost%', 'TOV Boost%', 'FPPM Boost']
72
  raw_display.loc[:, cols_to_check] = raw_display.loc[:, cols_to_check].replace({'%': ''}, regex=True).astype(float) / 100
 
74
  raw_display['position'] = 'Point Guard'
75
  pg_dem = raw_display[raw_display['Acro'] != ""]
76
 
77
+ raw_display = master_dem_frame[master_dem_frame['Position'] == 'SG']
 
78
  raw_display = raw_display.reset_index(drop=True)
79
  cols_to_check = ['Pts% Boost', 'Reb% Boost', 'Ast% Boost', '3p% Boost', 'Stl Boost%', 'Blk Boost%', 'TOV Boost%', 'FPPM Boost']
80
  raw_display.loc[:, cols_to_check] = raw_display.loc[:, cols_to_check].replace({'%': ''}, regex=True).astype(float) / 100
 
82
  raw_display['position'] = 'Shooting Guard'
83
  sg_dem = raw_display[raw_display['Acro'] != ""]
84
 
85
+ raw_display = master_dem_frame[master_dem_frame['Position'] == 'SF']
 
86
  raw_display = raw_display.reset_index(drop=True)
87
  cols_to_check = ['Pts% Boost', 'Reb% Boost', 'Ast% Boost', '3p% Boost', 'Stl Boost%', 'Blk Boost%', 'TOV Boost%', 'FPPM Boost']
88
  raw_display.loc[:, cols_to_check] = raw_display.loc[:, cols_to_check].replace({'%': ''}, regex=True).astype(float) / 100
 
90
  raw_display['position'] = 'Small Forward'
91
  sf_dem = raw_display[raw_display['Acro'] != ""]
92
 
93
+ raw_display = master_dem_frame[master_dem_frame['Position'] == 'PF']
 
94
  raw_display = raw_display.reset_index(drop=True)
95
  cols_to_check = ['Pts% Boost', 'Reb% Boost', 'Ast% Boost', '3p% Boost', 'Stl Boost%', 'Blk Boost%', 'TOV Boost%', 'FPPM Boost']
96
  raw_display.loc[:, cols_to_check] = raw_display.loc[:, cols_to_check].replace({'%': ''}, regex=True).astype(float) / 100
 
98
  raw_display['position'] = 'Power Forward'
99
  pf_dem = raw_display[raw_display['Acro'] != ""]
100
 
101
+ raw_display = master_dem_frame[master_dem_frame['Position'] == 'C']
 
102
  raw_display = raw_display.reset_index(drop=True)
103
  cols_to_check = ['Pts% Boost', 'Reb% Boost', 'Ast% Boost', '3p% Boost', 'Stl Boost%', 'Blk Boost%', 'TOV Boost%', 'FPPM Boost']
104
  raw_display.loc[:, cols_to_check] = raw_display.loc[:, cols_to_check].replace({'%': ''}, regex=True).astype(float) / 100
 
120
 
121
  return export_dem, matchups, matchups_dict
122
 
123
+ @st.cache_resource(ttl = 600)
124
+ def init_macro_tables():
125
+ team_macro_json = requests.get(NBA_DATA + '?sheet=Team_Macro').json()
126
+ team_macro_frame = pd.DataFrame(team_macro_json)
127
+ team_macro_frame = team_macro_frame.reset_index(drop=True)
128
+
129
+ team_off_frame = team_macro_frame[team_macro_frame['Data'] == 'Off']
130
+ team_off_frame = team_off_frame.reset_index(drop=True)
131
+
132
+ team_def_frame = team_macro_frame[team_macro_frame['Data'] == 'Def']
133
+ team_def_frame = team_def_frame.reset_index(drop=True)
134
+
135
+ team_combo_json = requests.get(NBA_DATA + '?sheet=Team%20Combo%20Data').json()
136
+ team_combo_frame = pd.DataFrame(team_combo_json)
137
+ team_combo_frame = team_combo_frame.reset_index(drop=True)
138
+
139
+ team_matchup_json = requests.get(NBA_DATA + '?sheet=Team%20Matchups').json()
140
+ team_matchup_frame = pd.DataFrame(team_matchup_json)
141
+ team_matchup_frame = team_matchup_frame.reset_index(drop=True)
142
+
143
+ return team_off_frame, team_def_frame, team_combo_frame, team_matchup_frame
144
+
145
  def convert_df_to_csv(df):
146
  return df.to_csv().encode('utf-8')
147
 
148
+ selected_tab = st.segmented_control(
149
+ "Select Tab",
150
+ options=["DEM Matchups", "Team Macro Tables"],
151
+ selection_mode='single',
152
+ default='DEM Matchups',
153
+ width='stretch',
154
+ label_visibility='collapsed',
155
+ key='tab_selector'
156
+ )
157
+
158
+ if selected_tab == 'DEM Matchups':
159
+
160
+ overall_dem, matchups, matchups_dict = init_DEM()
161
+
162
+ col1, col2 = st.columns([1, 9])
163
+ with col1:
164
+ if st.button("Reset Data", key='reset1'):
165
+ st.cache_data.clear()
166
+ overall_dem, matchups, matchups_dict = init_DEM()
167
+ split_var1 = st.radio("View all teams or just this main slate's matchups?", ('Slate Matchups', 'All'), key='split_var1')
168
+ if split_var1 == 'Slate Matchups':
169
+ view_var1 = matchups.Opp.values.tolist()
170
+ split_var2 = st.radio("Would you like to view all teams or specific ones?", ('All', 'Specific Teams'), key='split_var2')
171
+ if split_var2 == 'Specific Teams':
172
+ team_var1 = st.multiselect('Which teams would you like to include in the tables?', options = view_var1, key='team_var1')
173
+ elif split_var2 == 'All':
174
+ team_var1 = view_var1
175
+ split_var3 = st.radio("Would you like to view all positions or specific ones?", ('All', 'Specific Positions'), key='split_var3')
176
+ if split_var3 == 'Specific Positions':
177
+ pos_var1 = st.multiselect('Which teams would you like to include in the tables?', options = overall_dem['position'].unique(), key='pos_var1')
178
+ elif split_var3 == 'All':
179
+ pos_var1 = overall_dem.position.values.tolist()
180
+ if split_var1 == 'All':
181
+ split_var2 = st.radio("Would you like to view all teams or specific ones?", ('All', 'Specific Teams'), key='split_var2')
182
+ if split_var2 == 'Specific Teams':
183
+ team_var1 = st.multiselect('Which teams would you like to include in the tables?', options = overall_dem['Acro'].unique(), key='team_var1')
184
+ elif split_var2 == 'All':
185
+ team_var1 = overall_dem.Acro.values.tolist()
186
+ split_var3 = st.radio("Would you like to view all positions or specific ones?", ('All', 'Specific Positions'), key='split_var3')
187
+ if split_var3 == 'Specific Positions':
188
+ pos_var1 = st.multiselect('Which teams would you like to include in the tables?', options = overall_dem['position'].unique(), key='pos_var1')
189
+ elif split_var3 == 'All':
190
+ pos_var1 = overall_dem.position.values.tolist()
191
+ with col2:
192
+ if split_var1 == 'Slate Matchups':
193
+ dem_display = overall_dem[overall_dem['Acro'].isin(view_var1)]
194
+ dem_display['Team (Getting Boost)'] = dem_display['Acro'].map(matchups_dict)
195
+ dem_display.rename(columns={"Acro": "Opp (Giving Boost)"}, inplace = True)
196
+ dem_display = dem_display[['Team (Getting Boost)', 'Opp (Giving Boost)', 'G', 'Pts% Boost', 'Reb% Boost', 'Ast% Boost', '3p% Boost',
197
+ 'Stl Boost%', 'Blk Boost%', 'TOV Boost%', 'FPPM', 'FPPM Boost', 'Team FPPM Boost', 'position']]
198
+ dem_display = dem_display[dem_display['Team (Getting Boost)'].isin(team_var1)]
199
+ dem_display = dem_display[dem_display['position'].isin(pos_var1)]
200
+ dem_display = dem_display.sort_values(by='FPPM Boost', ascending=False)
201
+ elif split_var1 == 'All':
202
+ dem_display = overall_dem[overall_dem['Acro'].isin(team_var1)]
203
+ dem_display = dem_display[dem_display['position'].isin(pos_var1)]
204
+ dem_display = dem_display.sort_values(by='FPPM Boost', ascending=False)
205
+ dem_display.rename(columns={"Team": "Team (Giving Boost)"}, inplace = True)
206
+ dem_display = dem_display.set_index('Team (Giving Boost)')
207
+ st.dataframe(dem_display.style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').format(percentages_format, precision=2), use_container_width = True)
208
+ st.download_button(
209
+ label="Export DEM Numbers",
210
+ data=convert_df_to_csv(overall_dem),
211
+ file_name='DEM_export.csv',
212
+ mime='text/csv',
213
+ )
214
+
215
+ if selected_tab == 'Team Macro Tables':
216
+ team_off_frame, team_def_frame, team_combo_frame, team_matchup_frame = init_macro_tables()
217
+ col1, col2 = st.columns([1, 9])
218
+ with col1:
219
+ if st.button("Reset Data", key='reset2'):
220
+ st.cache_data.clear()
221
+ team_off_frame, team_def_frame, team_combo_frame, team_matchup_frame = init_macro_tables()
222
+ table_var2 = st.selectbox("Select Table", options=['Team Offense', 'Team Defense', 'Team Combo', 'Team Matchups'], key='table_var2')
223
+ with col2:
224
+ if table_var2 == 'Team Offense':
225
+ team_macro_display = team_off_frame
226
+ elif table_var2 == 'Team Defense':
227
+ team_macro_display = team_def_frame
228
+ elif table_var2 == 'Team Combo':
229
+ team_macro_display = team_combo_frame
230
+ elif table_var2 == 'Team Matchups':
231
+ team_macro_display = team_matchup_frame
232
+ st.dataframe(team_macro_display.set_index('Team').style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').format(precision=2), use_container_width = True)
233
+ st.download_button(
234
+ label="Export Table Data",
235
+ data=convert_df_to_csv(team_macro_display),
236
+ file_name='Team_Macro_export.csv',
237
+ mime='text/csv',
238
+ )