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(""" """, unsafe_allow_html=True) @st.cache_resource(ttl = 600) 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 @st.cache_resource(ttl = 600) 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', )