Spaces:
Running
Running
| import streamlit as st | |
| st.set_page_config(layout="wide") | |
| for name in dir(): | |
| if not name.startswith('_'): | |
| del globals()[name] | |
| import numpy as np | |
| import pandas as pd | |
| import streamlit as st | |
| import os | |
| import requests | |
| NBA_DATA = os.getenv('NBA_DATA') | |
| percentages_format = {'Pts% Boost': '{:.2%}', 'Reb% Boost': '{:.2%}', 'Ast% Boost': '{:.2%}', '3p% Boost': '{:.2%}', | |
| 'Stl Boost%': '{:.2%}', 'Blk Boost%': '{:.2%}', 'TOV Boost%': '{:.2%}', 'FPPM Boost': '{:.2%}', | |
| 'Team FPPM Boost': '{:.2%}'} | |
| team_macro_format = {'FGM%': '{:.2%}', 'FG3M%': '{:.2%}', 'FTM%': '{:.2%}'} | |
| macro_minutes_cols = ['Team', 'Games', 'MIN', 'FGA/m', 'FG3A/m', 'FTA/m', 'PTS/m', 'REB/m', 'AST/m', 'STL/m', 'BLK/m', 'Fantasy/m', 'FD_Fantasy/m'] | |
| remove_minutes_cols = ['MIN', 'FGA/m', 'FG3A/m', 'FTA/m', 'PTS/m', 'REB/m', 'AST/m', 'STL/m', 'BLK/m', 'Fantasy/m', 'FD_Fantasy/m'] | |
| st.markdown(""" | |
| <style> | |
| /* Tab styling */ | |
| .stElementContainer [data-baseweb="button-group"] { | |
| gap: 2.000rem; | |
| padding: 4px; | |
| } | |
| .stElementContainer [kind="segmented_control"] { | |
| height: 2.000rem; | |
| white-space: pre-wrap; | |
| background-color: #DAA520; | |
| color: white; | |
| border-radius: 20px; | |
| gap: 1px; | |
| padding: 10px 20px; | |
| font-weight: bold; | |
| transition: all 0.3s ease; | |
| } | |
| .stElementContainer [kind="segmented_controlActive"] { | |
| height: 3.000rem; | |
| background-color: #DAA520; | |
| border: 3px solid #FFD700; | |
| border-radius: 10px; | |
| color: black; | |
| } | |
| .stElementContainer [kind="segmented_control"]:hover { | |
| background-color: #FFD700; | |
| cursor: pointer; | |
| } | |
| div[data-baseweb="select"] > div { | |
| background-color: #DAA520; | |
| color: white; | |
| } | |
| </style>""", unsafe_allow_html=True) | |
| def init_DEM(): | |
| json_matchups = requests.get(NBA_DATA + '?sheet=DEM%20Matchups').json() | |
| raw_display = pd.DataFrame(json_matchups) | |
| raw_display = raw_display.reset_index(drop=True) | |
| matchups = raw_display[raw_display['Var'] != ""] | |
| matchups_dict = dict(zip(matchups['Team'], matchups['Opp'])) | |
| master_dem_json = requests.get(NBA_DATA + '?sheet=Master_DEM_Calc').json() | |
| master_dem_frame = pd.DataFrame(master_dem_json) | |
| raw_display = master_dem_frame[master_dem_frame['Position'] == 'PG'] | |
| raw_display = raw_display.reset_index(drop=True) | |
| cols_to_check = ['Pts% Boost', 'Reb% Boost', 'Ast% Boost', '3p% Boost', 'Stl Boost%', 'Blk Boost%', 'TOV Boost%', 'FPPM Boost'] | |
| raw_display.loc[:, cols_to_check] = raw_display.loc[:, cols_to_check].replace({'%': ''}, regex=True).astype(float) / 100 | |
| raw_display = raw_display.apply(pd.to_numeric, errors='coerce').fillna(raw_display) | |
| raw_display['position'] = 'Point Guard' | |
| pg_dem = raw_display[raw_display['Acro'] != ""] | |
| raw_display = master_dem_frame[master_dem_frame['Position'] == 'SG'] | |
| raw_display = raw_display.reset_index(drop=True) | |
| cols_to_check = ['Pts% Boost', 'Reb% Boost', 'Ast% Boost', '3p% Boost', 'Stl Boost%', 'Blk Boost%', 'TOV Boost%', 'FPPM Boost'] | |
| raw_display.loc[:, cols_to_check] = raw_display.loc[:, cols_to_check].replace({'%': ''}, regex=True).astype(float) / 100 | |
| raw_display = raw_display.apply(pd.to_numeric, errors='coerce').fillna(raw_display) | |
| raw_display['position'] = 'Shooting Guard' | |
| sg_dem = raw_display[raw_display['Acro'] != ""] | |
| raw_display = master_dem_frame[master_dem_frame['Position'] == 'SF'] | |
| raw_display = raw_display.reset_index(drop=True) | |
| cols_to_check = ['Pts% Boost', 'Reb% Boost', 'Ast% Boost', '3p% Boost', 'Stl Boost%', 'Blk Boost%', 'TOV Boost%', 'FPPM Boost'] | |
| raw_display.loc[:, cols_to_check] = raw_display.loc[:, cols_to_check].replace({'%': ''}, regex=True).astype(float) / 100 | |
| raw_display = raw_display.apply(pd.to_numeric, errors='coerce').fillna(raw_display) | |
| raw_display['position'] = 'Small Forward' | |
| sf_dem = raw_display[raw_display['Acro'] != ""] | |
| raw_display = master_dem_frame[master_dem_frame['Position'] == 'PF'] | |
| raw_display = raw_display.reset_index(drop=True) | |
| cols_to_check = ['Pts% Boost', 'Reb% Boost', 'Ast% Boost', '3p% Boost', 'Stl Boost%', 'Blk Boost%', 'TOV Boost%', 'FPPM Boost'] | |
| raw_display.loc[:, cols_to_check] = raw_display.loc[:, cols_to_check].replace({'%': ''}, regex=True).astype(float) / 100 | |
| raw_display = raw_display.apply(pd.to_numeric, errors='coerce').fillna(raw_display) | |
| raw_display['position'] = 'Power Forward' | |
| pf_dem = raw_display[raw_display['Acro'] != ""] | |
| raw_display = master_dem_frame[master_dem_frame['Position'] == 'C'] | |
| raw_display = raw_display.reset_index(drop=True) | |
| cols_to_check = ['Pts% Boost', 'Reb% Boost', 'Ast% Boost', '3p% Boost', 'Stl Boost%', 'Blk Boost%', 'TOV Boost%', 'FPPM Boost'] | |
| raw_display.loc[:, cols_to_check] = raw_display.loc[:, cols_to_check].replace({'%': ''}, regex=True).astype(float) / 100 | |
| raw_display = raw_display.apply(pd.to_numeric, errors='coerce').fillna(raw_display) | |
| raw_display['position'] = 'Center' | |
| c_dem = raw_display[raw_display['Acro'] != ""] | |
| overall_dem = pd.concat([pg_dem, sg_dem, sf_dem, pf_dem, c_dem]) | |
| overall_dem = overall_dem[['Acro', 'G', 'Pts% Boost', 'Reb% Boost', 'Ast% Boost', '3p% Boost', | |
| 'Stl Boost%', 'Blk Boost%', 'TOV Boost%', 'FPPM', 'FPPM Boost', 'position']] | |
| overall_dem['Team'] = overall_dem['Acro'] + '-' + overall_dem['position'] | |
| overall_dem['Team FPPM Boost'] = overall_dem.groupby('Acro', sort=False)['FPPM Boost'].transform('mean') | |
| overall_dem = overall_dem.reset_index() | |
| export_dem = overall_dem[['Team', 'Acro', 'G', 'Pts% Boost', 'Reb% Boost', 'Ast% Boost', '3p% Boost', | |
| 'Stl Boost%', 'Blk Boost%', 'TOV Boost%', 'FPPM', 'FPPM Boost', 'Team FPPM Boost', 'position']] | |
| return export_dem, matchups, matchups_dict | |
| def init_macro_tables(): | |
| json_matchups = requests.get(NBA_DATA + '?sheet=Site_Info').json() | |
| raw_display = pd.DataFrame(json_matchups) | |
| raw_display = raw_display.reset_index(drop=True) | |
| dk_main_slate = raw_display['DK Main'].values.tolist() | |
| fd_main_slate = raw_display['FD Main'].values.tolist() | |
| team_macro_json = requests.get(NBA_DATA + '?sheet=Team_Macro').json() | |
| team_macro_frame = pd.DataFrame(team_macro_json) | |
| team_macro_frame = team_macro_frame.reset_index(drop=True) | |
| team_macro_frame = team_macro_frame[team_macro_frame['Team'] != ""] | |
| team_off_frame = team_macro_frame[team_macro_frame['Data'] == 'Off'] | |
| team_off_frame = team_off_frame.reset_index(drop=True) | |
| team_off_frame = team_off_frame.drop(columns=['PLUS_MINUS', 'PF', 'Data'], axis=1) | |
| team_off_frame = team_off_frame.apply(pd.to_numeric, errors='coerce').fillna(team_off_frame) | |
| team_off_frame['PTS/m'] = team_off_frame['PTS'] / team_off_frame['MIN'] | |
| team_off_frame['REB/m'] = team_off_frame['REB'] / team_off_frame['MIN'] | |
| team_off_frame['AST/m'] = team_off_frame['AST'] / team_off_frame['MIN'] | |
| team_off_frame['STL/m'] = team_off_frame['STL'] / team_off_frame['MIN'] | |
| team_off_frame['BLK/m'] = team_off_frame['BLK'] / team_off_frame['MIN'] | |
| team_def_frame = team_macro_frame[team_macro_frame['Data'] == 'Def'] | |
| team_def_frame = team_def_frame.reset_index(drop=True) | |
| team_def_frame = team_def_frame.drop(columns=['PLUS_MINUS', 'PF', 'Data'], axis=1) | |
| team_def_frame = team_def_frame.apply(pd.to_numeric, errors='coerce').fillna(team_def_frame) | |
| team_def_frame['PTS/m'] = team_def_frame['PTS'] / team_def_frame['MIN'] | |
| team_def_frame['REB/m'] = team_def_frame['REB'] / team_def_frame['MIN'] | |
| team_def_frame['AST/m'] = team_def_frame['AST'] / team_def_frame['MIN'] | |
| team_def_frame['STL/m'] = team_def_frame['STL'] / team_def_frame['MIN'] | |
| team_def_frame['BLK/m'] = team_def_frame['BLK'] / team_def_frame['MIN'] | |
| team_combo_json = requests.get(NBA_DATA + '?sheet=Team%20Combo%20Data').json() | |
| team_combo_frame = pd.DataFrame(team_combo_json) | |
| team_combo_frame = team_combo_frame.reset_index(drop=True) | |
| team_combo_frame = team_combo_frame.apply(pd.to_numeric, errors='coerce').fillna(team_combo_frame) | |
| try: | |
| team_matchup_json = requests.get(NBA_DATA + '?sheet=Team%20Matchups').json() | |
| team_matchup_frame = pd.DataFrame(team_matchup_json) | |
| team_matchup_frame = team_matchup_frame[team_matchup_frame['t_Pts'] != ""] | |
| team_matchup_frame = team_matchup_frame.reset_index(drop=True) | |
| team_matchup_frame = team_matchup_frame.apply(pd.to_numeric, errors='coerce').fillna(team_matchup_frame) | |
| except: | |
| team_matchup_frame = pd.DataFrame() | |
| return team_off_frame, team_def_frame, team_combo_frame, team_matchup_frame, dk_main_slate, fd_main_slate | |
| def convert_df_to_csv(df): | |
| return df.to_csv().encode('utf-8') | |
| selected_tab = st.segmented_control( | |
| "Select Tab", | |
| options=["DEM Matchups", "Team Macro Tables"], | |
| selection_mode='single', | |
| default='DEM Matchups', | |
| width='stretch', | |
| label_visibility='collapsed', | |
| key='tab_selector' | |
| ) | |
| if selected_tab == 'DEM Matchups': | |
| overall_dem, matchups, matchups_dict = init_DEM() | |
| col1, col2 = st.columns([1, 9]) | |
| with col1: | |
| if st.button("Reset Data", key='reset1'): | |
| st.cache_data.clear() | |
| overall_dem, matchups, matchups_dict = init_DEM() | |
| split_var1 = st.radio("View all teams or just this main slate's matchups?", ('Slate Matchups', 'All'), key='split_var1') | |
| if split_var1 == 'Slate Matchups': | |
| view_var1 = matchups.Opp.values.tolist() | |
| split_var2 = st.radio("Would you like to view all teams or specific ones?", ('All', 'Specific Teams'), key='split_var2') | |
| if split_var2 == 'Specific Teams': | |
| team_var1 = st.multiselect('Which teams would you like to include in the tables?', options = view_var1, key='team_var1') | |
| elif split_var2 == 'All': | |
| team_var1 = view_var1 | |
| split_var3 = st.radio("Would you like to view all positions or specific ones?", ('All', 'Specific Positions'), key='split_var3') | |
| if split_var3 == 'Specific Positions': | |
| pos_var1 = st.multiselect('Which teams would you like to include in the tables?', options = overall_dem['position'].unique(), key='pos_var1') | |
| elif split_var3 == 'All': | |
| pos_var1 = overall_dem.position.values.tolist() | |
| if split_var1 == 'All': | |
| split_var2 = st.radio("Would you like to view all teams or specific ones?", ('All', 'Specific Teams'), key='split_var2') | |
| if split_var2 == 'Specific Teams': | |
| team_var1 = st.multiselect('Which teams would you like to include in the tables?', options = overall_dem['Acro'].unique(), key='team_var1') | |
| elif split_var2 == 'All': | |
| team_var1 = overall_dem.Acro.values.tolist() | |
| split_var3 = st.radio("Would you like to view all positions or specific ones?", ('All', 'Specific Positions'), key='split_var3') | |
| if split_var3 == 'Specific Positions': | |
| pos_var1 = st.multiselect('Which teams would you like to include in the tables?', options = overall_dem['position'].unique(), key='pos_var1') | |
| elif split_var3 == 'All': | |
| pos_var1 = overall_dem.position.values.tolist() | |
| with col2: | |
| if split_var1 == 'Slate Matchups': | |
| dem_display = overall_dem[overall_dem['Acro'].isin(view_var1)] | |
| dem_display['Team (Getting Boost)'] = dem_display['Acro'].map(matchups_dict) | |
| dem_display.rename(columns={"Acro": "Opp (Giving Boost)"}, inplace = True) | |
| dem_display = dem_display[['Team (Getting Boost)', 'Opp (Giving Boost)', 'G', 'Pts% Boost', 'Reb% Boost', 'Ast% Boost', '3p% Boost', | |
| 'Stl Boost%', 'Blk Boost%', 'TOV Boost%', 'FPPM', 'FPPM Boost', 'Team FPPM Boost', 'position']] | |
| dem_display = dem_display[dem_display['Team (Getting Boost)'].isin(team_var1)] | |
| dem_display = dem_display[dem_display['position'].isin(pos_var1)] | |
| dem_display = dem_display.sort_values(by='FPPM Boost', ascending=False) | |
| elif split_var1 == 'All': | |
| dem_display = overall_dem[overall_dem['Acro'].isin(team_var1)] | |
| dem_display = dem_display[dem_display['position'].isin(pos_var1)] | |
| dem_display = dem_display.sort_values(by='FPPM Boost', ascending=False) | |
| dem_display.rename(columns={"Team": "Team (Giving Boost)"}, inplace = True) | |
| dem_display = dem_display.set_index('Team (Giving Boost)') | |
| st.dataframe(dem_display.style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').format(percentages_format, precision=2), use_container_width = True) | |
| st.download_button( | |
| label="Export DEM Numbers", | |
| data=convert_df_to_csv(overall_dem), | |
| file_name='DEM_export.csv', | |
| mime='text/csv', | |
| ) | |
| if selected_tab == 'Team Macro Tables': | |
| team_off_frame, team_def_frame, team_combo_frame, team_matchup_frame, dk_main_slate, fd_main_slate = init_macro_tables() | |
| col1, col2 = st.columns([1, 9]) | |
| with col1: | |
| if st.button("Reset Data", key='reset2'): | |
| st.cache_data.clear() | |
| team_off_frame, team_def_frame, team_combo_frame, team_matchup_frame, dk_main_slate, fd_main_slate = init_macro_tables() | |
| macro_split_var = st.radio("View all teams or just this main slate's matchups?", ('DK Main Slate', 'FD Main Slate', 'All'), key='macro_split_var') | |
| if macro_split_var == 'DK Main Slate': | |
| macro_view_var = dk_main_slate | |
| if macro_split_var == 'FD Main Slate': | |
| macro_view_var = fd_main_slate | |
| if macro_split_var == 'All': | |
| macro_view_var = team_off_frame.Team.values.tolist() | |
| table_var2 = st.selectbox("Select Table", options=['Team Offense', 'Team Defense', 'Team Combo', 'Team Matchups'], key='table_var2') | |
| display_type2 = st.selectbox("Select Display Type", options=['Minutes', 'Total'], key='display_type2') | |
| with col2: | |
| if table_var2 == 'Team Offense': | |
| if display_type2 == 'Minutes': | |
| team_macro_display = team_off_frame.loc[:, team_off_frame.columns.isin(macro_minutes_cols)] | |
| team_macro_display = team_macro_display[team_macro_display['Team'].isin(macro_view_var)] | |
| team_macro_display = team_macro_display[['Team', 'Games', 'MIN', 'FGA/m', 'FG3A/m', 'FTA/m', 'PTS/m', 'REB/m', 'AST/m', 'STL/m', 'BLK/m', 'Fantasy/m', 'FD_Fantasy/m']] | |
| elif display_type2 == 'Total': | |
| team_macro_display = team_off_frame.loc[:, ~team_off_frame.columns.isin(remove_minutes_cols)] | |
| team_macro_display = team_macro_display[team_macro_display['Team'].isin(macro_view_var)] | |
| elif table_var2 == 'Team Defense': | |
| if display_type2 == 'Minutes': | |
| team_macro_display = team_def_frame.loc[:, team_def_frame.columns.isin(macro_minutes_cols)] | |
| team_macro_display = team_macro_display[team_macro_display['Team'].isin(macro_view_var)] | |
| team_macro_display = team_macro_display[['Team', 'Games', 'MIN', 'FGA/m', 'FG3A/m', 'FTA/m', 'PTS/m', 'REB/m', 'AST/m', 'STL/m', 'BLK/m', 'Fantasy/m', 'FD_Fantasy/m']] | |
| elif display_type2 == 'Total': | |
| team_macro_display = team_def_frame.loc[:, ~team_def_frame.columns.isin(remove_minutes_cols)] | |
| team_macro_display = team_macro_display[team_macro_display['Team'].isin(macro_view_var)] | |
| elif table_var2 == 'Team Combo': | |
| team_macro_display = team_combo_frame | |
| team_macro_display = team_macro_display[team_macro_display['Team'].isin(macro_view_var)] | |
| elif table_var2 == 'Team Matchups': | |
| team_macro_display = team_matchup_frame | |
| team_macro_display = team_macro_display[team_macro_display['Team'].isin(macro_view_var)] | |
| st.dataframe(team_macro_display.set_index('Team').style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').format(team_macro_format, precision=2), use_container_width = True) | |
| st.download_button( | |
| label="Export Table Data", | |
| data=convert_df_to_csv(team_macro_display), | |
| file_name='Team_Macro_export.csv', | |
| mime='text/csv', | |
| ) |