Spaces:
Runtime error
Runtime error
Update app.py
Browse files
app.py
CHANGED
@@ -4,12 +4,15 @@ st.set_page_config(layout="wide")
|
|
4 |
for name in dir():
|
5 |
if not name.startswith('_'):
|
6 |
del globals()[name]
|
7 |
-
|
8 |
import numpy as np
|
9 |
import pandas as pd
|
10 |
import streamlit as st
|
11 |
import gspread
|
12 |
import gc
|
|
|
|
|
|
|
13 |
|
14 |
@st.cache_resource
|
15 |
def init_conn():
|
@@ -78,6 +81,8 @@ def init_baselines():
|
|
78 |
gamelog_table['spread'] = (gamelog_table['opp_score'] - gamelog_table['team_score']).abs()
|
79 |
gamelog_table['GAME_DATE'] = pd.to_datetime(gamelog_table['GAME_DATE']).dt.date
|
80 |
|
|
|
|
|
81 |
gamelog_table = gamelog_table.set_axis(['Player', 'Pos', 'game_id', 'Team', 'Opp', 'Season', 'Date', 'Matchup', 'Min', 'Touches', 'Pts', 'FGM', 'FGA', 'FG%', 'FG3M',
|
82 |
'FG3A', 'FG3%', 'FTM', 'FTA', 'FT%', 'OREB Chance', 'OREB', 'DREB Chance', 'DREB', 'REB Chance', 'REB',
|
83 |
'Passes', 'Alt Assists', 'FT Assists', 'Assists', 'Stl', 'Blk', 'Tov', 'PF', 'DD', 'TD', 'Fantasy', 'FD_Fantasy',
|
@@ -94,9 +99,20 @@ def init_baselines():
|
|
94 |
rot_table[data_cols] = rot_table[data_cols].apply(pd.to_numeric, errors='coerce')
|
95 |
rot_table = rot_table[rot_table['Player'] != 0]
|
96 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
97 |
timestamp = gamelog_table['Date'].max()
|
98 |
|
99 |
-
return gamelog_table, rot_table, timestamp
|
100 |
|
101 |
@st.cache_data(show_spinner=False)
|
102 |
def seasonlong_build(data_sample):
|
@@ -197,7 +213,7 @@ def split_frame(input_df, rows):
|
|
197 |
def convert_df_to_csv(df):
|
198 |
return df.to_csv().encode('utf-8')
|
199 |
|
200 |
-
gamelog_table, rot_table, timestamp = init_baselines()
|
201 |
t_stamp = f"Updated through: " + str(timestamp) + f" CST"
|
202 |
basic_cols = ['Player', 'Pos', 'Team', 'Opp', 'Season', 'Date', 'Matchup', 'Min']
|
203 |
basic_season_cols = ['Pos', 'Team', 'Min']
|
@@ -217,7 +233,7 @@ indv_players = gamelog_table.drop_duplicates(subset='Player')
|
|
217 |
total_players = indv_players.Player.values.tolist()
|
218 |
total_dates = gamelog_table.Date.values.tolist()
|
219 |
|
220 |
-
tab1, tab2, tab3, tab4 = st.tabs(['Gamelogs', 'Correlation Matrix', 'Position vs. Opp', 'Rotations'])
|
221 |
|
222 |
with tab1:
|
223 |
st.info(t_stamp)
|
@@ -225,7 +241,7 @@ with tab1:
|
|
225 |
with col1:
|
226 |
if st.button("Reset Data", key='reset1'):
|
227 |
st.cache_data.clear()
|
228 |
-
gamelog_table, rot_table = init_baselines()
|
229 |
basic_cols = ['Player', 'Pos', 'Team', 'Opp', 'Season', 'Date', 'Matchup', 'Min']
|
230 |
basic_season_cols = ['Pos', 'Team', 'Min']
|
231 |
data_cols = ['team_score', 'opp_score', 'spread', 'Touches', 'Pts', 'FGM', 'FGA', 'FG%', 'FG3M',
|
@@ -350,7 +366,7 @@ with tab2:
|
|
350 |
with col1:
|
351 |
if st.button("Reset Data", key='reset2'):
|
352 |
st.cache_data.clear()
|
353 |
-
gamelog_table, rot_table = init_baselines()
|
354 |
basic_cols = ['Player', 'Pos', 'Team', 'Opp', 'Season', 'Date', 'Matchup', 'Min']
|
355 |
basic_season_cols = ['Pos', 'Team', 'Min']
|
356 |
data_cols = ['team_score', 'opp_score', 'spread', 'Touches', 'Pts', 'FGM', 'FGA', 'FG%', 'FG3M',
|
@@ -441,7 +457,7 @@ with tab3:
|
|
441 |
with col1:
|
442 |
if st.button("Reset Data", key='reset3'):
|
443 |
st.cache_data.clear()
|
444 |
-
gamelog_table, rot_table = init_baselines()
|
445 |
basic_cols = ['Player', 'Pos', 'Team', 'Opp', 'Season', 'Date', 'Matchup', 'Min']
|
446 |
basic_season_cols = ['Pos', 'Team', 'Min']
|
447 |
data_cols = ['team_score', 'opp_score', 'spread', 'Touches', 'Pts', 'FGM', 'FGA', 'FG%', 'FG3M',
|
@@ -524,7 +540,7 @@ with tab4:
|
|
524 |
with col1:
|
525 |
if st.button("Reset Data", key='reset4'):
|
526 |
st.cache_data.clear()
|
527 |
-
gamelog_table, rot_table = init_baselines()
|
528 |
basic_cols = ['Player', 'Pos', 'Team', 'Opp', 'Season', 'Date', 'Matchup', 'Min']
|
529 |
basic_season_cols = ['Pos', 'Team', 'Min']
|
530 |
data_cols = ['team_score', 'opp_score', 'spread', 'Touches', 'Pts', 'FGM', 'FGA', 'FG%', 'FG3M',
|
@@ -563,4 +579,100 @@ with tab4:
|
|
563 |
data=convert_df_to_csv(rot_display),
|
564 |
file_name='Rotations_NBA_View.csv',
|
565 |
mime='text/csv',
|
566 |
-
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
4 |
for name in dir():
|
5 |
if not name.startswith('_'):
|
6 |
del globals()[name]
|
7 |
+
|
8 |
import numpy as np
|
9 |
import pandas as pd
|
10 |
import streamlit as st
|
11 |
import gspread
|
12 |
import gc
|
13 |
+
import plotly.express as px
|
14 |
+
import plotly.io as pio
|
15 |
+
pio.renderers.default='browser'
|
16 |
|
17 |
@st.cache_resource
|
18 |
def init_conn():
|
|
|
81 |
gamelog_table['spread'] = (gamelog_table['opp_score'] - gamelog_table['team_score']).abs()
|
82 |
gamelog_table['GAME_DATE'] = pd.to_datetime(gamelog_table['GAME_DATE']).dt.date
|
83 |
|
84 |
+
spread_dict = dict(zip(gamelog_table['GAME_ID'], gamelog_table['spread']))
|
85 |
+
|
86 |
gamelog_table = gamelog_table.set_axis(['Player', 'Pos', 'game_id', 'Team', 'Opp', 'Season', 'Date', 'Matchup', 'Min', 'Touches', 'Pts', 'FGM', 'FGA', 'FG%', 'FG3M',
|
87 |
'FG3A', 'FG3%', 'FTM', 'FTA', 'FT%', 'OREB Chance', 'OREB', 'DREB Chance', 'DREB', 'REB Chance', 'REB',
|
88 |
'Passes', 'Alt Assists', 'FT Assists', 'Assists', 'Stl', 'Blk', 'Tov', 'PF', 'DD', 'TD', 'Fantasy', 'FD_Fantasy',
|
|
|
99 |
rot_table[data_cols] = rot_table[data_cols].apply(pd.to_numeric, errors='coerce')
|
100 |
rot_table = rot_table[rot_table['Player'] != 0]
|
101 |
|
102 |
+
worksheet = sh.worksheet('Rotation_stats')
|
103 |
+
raw_display = pd.DataFrame(worksheet.get_values())
|
104 |
+
raw_display.columns = raw_display.iloc[0]
|
105 |
+
raw_display = raw_display[1:]
|
106 |
+
raw_display = raw_display.reset_index(drop=True)
|
107 |
+
game_rot = raw_display[raw_display['PLAYER_NAME'] != ""]
|
108 |
+
data_cols = game_rot.columns.drop(['PLAYER_NAME', 'POS', 'TEAM_ABBREVIATION', 'OPP_ABBREVIATION', 'TEAM_NAME', 'OPP_NAME', 'GAME_DATE',
|
109 |
+
'MATCHUP', 'WL', 'backlog_lookup', 'Task', 'game_players'])
|
110 |
+
game_rot[data_cols] = game_rot[data_cols].apply(pd.to_numeric, errors='coerce')
|
111 |
+
game_rot['spread'] = game_rot['GAME_ID'].map(spread_dict)
|
112 |
+
|
113 |
timestamp = gamelog_table['Date'].max()
|
114 |
|
115 |
+
return gamelog_table, rot_table, game_rot, timestamp
|
116 |
|
117 |
@st.cache_data(show_spinner=False)
|
118 |
def seasonlong_build(data_sample):
|
|
|
213 |
def convert_df_to_csv(df):
|
214 |
return df.to_csv().encode('utf-8')
|
215 |
|
216 |
+
gamelog_table, rot_table, game_rot, timestamp = init_baselines()
|
217 |
t_stamp = f"Updated through: " + str(timestamp) + f" CST"
|
218 |
basic_cols = ['Player', 'Pos', 'Team', 'Opp', 'Season', 'Date', 'Matchup', 'Min']
|
219 |
basic_season_cols = ['Pos', 'Team', 'Min']
|
|
|
233 |
total_players = indv_players.Player.values.tolist()
|
234 |
total_dates = gamelog_table.Date.values.tolist()
|
235 |
|
236 |
+
tab1, tab2, tab3, tab4, tab5 = st.tabs(['Gamelogs', 'Correlation Matrix', 'Position vs. Opp', 'Positional Percentages', 'Game Rotations'])
|
237 |
|
238 |
with tab1:
|
239 |
st.info(t_stamp)
|
|
|
241 |
with col1:
|
242 |
if st.button("Reset Data", key='reset1'):
|
243 |
st.cache_data.clear()
|
244 |
+
gamelog_table, rot_table, game_rot, timestamp = init_baselines()
|
245 |
basic_cols = ['Player', 'Pos', 'Team', 'Opp', 'Season', 'Date', 'Matchup', 'Min']
|
246 |
basic_season_cols = ['Pos', 'Team', 'Min']
|
247 |
data_cols = ['team_score', 'opp_score', 'spread', 'Touches', 'Pts', 'FGM', 'FGA', 'FG%', 'FG3M',
|
|
|
366 |
with col1:
|
367 |
if st.button("Reset Data", key='reset2'):
|
368 |
st.cache_data.clear()
|
369 |
+
gamelog_table, rot_table, game_rot, timestamp = init_baselines()
|
370 |
basic_cols = ['Player', 'Pos', 'Team', 'Opp', 'Season', 'Date', 'Matchup', 'Min']
|
371 |
basic_season_cols = ['Pos', 'Team', 'Min']
|
372 |
data_cols = ['team_score', 'opp_score', 'spread', 'Touches', 'Pts', 'FGM', 'FGA', 'FG%', 'FG3M',
|
|
|
457 |
with col1:
|
458 |
if st.button("Reset Data", key='reset3'):
|
459 |
st.cache_data.clear()
|
460 |
+
gamelog_table, rot_table, game_rot, timestamp = init_baselines()
|
461 |
basic_cols = ['Player', 'Pos', 'Team', 'Opp', 'Season', 'Date', 'Matchup', 'Min']
|
462 |
basic_season_cols = ['Pos', 'Team', 'Min']
|
463 |
data_cols = ['team_score', 'opp_score', 'spread', 'Touches', 'Pts', 'FGM', 'FGA', 'FG%', 'FG3M',
|
|
|
540 |
with col1:
|
541 |
if st.button("Reset Data", key='reset4'):
|
542 |
st.cache_data.clear()
|
543 |
+
gamelog_table, rot_table, game_rot, timestamp = init_baselines()
|
544 |
basic_cols = ['Player', 'Pos', 'Team', 'Opp', 'Season', 'Date', 'Matchup', 'Min']
|
545 |
basic_season_cols = ['Pos', 'Team', 'Min']
|
546 |
data_cols = ['team_score', 'opp_score', 'spread', 'Touches', 'Pts', 'FGM', 'FGA', 'FG%', 'FG3M',
|
|
|
579 |
data=convert_df_to_csv(rot_display),
|
580 |
file_name='Rotations_NBA_View.csv',
|
581 |
mime='text/csv',
|
582 |
+
)
|
583 |
+
|
584 |
+
with tab1:
|
585 |
+
st.info(t_stamp)
|
586 |
+
col1, col2 = st.columns([1, 9])
|
587 |
+
with col1:
|
588 |
+
if st.button("Reset Data", key='reset5'):
|
589 |
+
st.cache_data.clear()
|
590 |
+
gamelog_table, rot_table, game_rot, timestamp = init_baselines()
|
591 |
+
basic_cols = ['Player', 'Pos', 'Team', 'Opp', 'Season', 'Date', 'Matchup', 'Min']
|
592 |
+
basic_season_cols = ['Pos', 'Team', 'Min']
|
593 |
+
data_cols = ['team_score', 'opp_score', 'spread', 'Touches', 'Pts', 'FGM', 'FGA', 'FG%', 'FG3M',
|
594 |
+
'FG3A', 'FG3%', 'FTM', 'FTA', 'FT%', 'OREB Chance', 'OREB', 'DREB Chance', 'DREB', 'REB Chance', 'REB',
|
595 |
+
'Passes', 'Alt Assists', 'FT Assists', 'Assists', 'Stl', 'Blk', 'Tov', 'PF', 'DD', 'TD', 'Fantasy', 'FD_Fantasy',
|
596 |
+
'Rebound%', 'Assists/Pass', 'Touch_per_min', 'Fantasy/Touch', 'FD Fantasy/Touch']
|
597 |
+
season_data_cols = ['Touches', 'Touch/Min', 'Pts', 'FGM', 'FGA', 'FG%', 'FG3M', 'FG3A',
|
598 |
+
'FG3%', 'FTM', 'FTA', 'FT%', 'OREB Chance', 'OREB', 'DREB Chance', 'DREB', 'REB Chance', 'REB',
|
599 |
+
'Passes', 'Alt Assists', 'FT Assists', 'Assists', 'Stl', 'Blk', 'Tov', 'PF', 'DD', 'TD', 'Fantasy', 'FD_Fantasy',
|
600 |
+
'Rebound%', 'Assists/Pass', 'Fantasy/Touch', 'FD Fantasy/Touch']
|
601 |
+
indv_teams = gamelog_table.drop_duplicates(subset='Team')
|
602 |
+
total_teams = indv_teams.Team.values.tolist()
|
603 |
+
indv_rot_teams = rot_table.drop_duplicates(subset='Team')
|
604 |
+
total_rot_teams = indv_rot_teams.Team.values.tolist()
|
605 |
+
indv_players = gamelog_table.drop_duplicates(subset='Player')
|
606 |
+
total_players = indv_players.Player.values.tolist()
|
607 |
+
total_dates = gamelog_table.Date.values.tolist()
|
608 |
+
|
609 |
+
game_rot_view = st.radio("What set would you like to view?", ('Team Rotations', 'Player Rotations'), key='game_rot_view')
|
610 |
+
|
611 |
+
if game_rot_view == 'Team Rotations':
|
612 |
+
game_rot_team = st.selectbox("What team would you like to work with?", options = total_teams, key='game_rot_team')
|
613 |
+
team_backlog = game_rot[game_rot['TEAM_ABBREVIATION'] == game_rot_team]
|
614 |
+
|
615 |
+
game_id_var = st.selectbox("What game would you like to view?", options = team_backlog['backlog_lookup'], key='game_id_var')
|
616 |
+
|
617 |
+
game_rot_spread = st.slider("Is there a certain spread range you want to view?", 0, 100, (0, 100), key='game_rot_spread')
|
618 |
+
|
619 |
+
game_rot_min = st.slider("Is there a certain minutes range you want to view?", 0, 60, (0, 60), key='game_rot_min')
|
620 |
+
|
621 |
+
game_rot_dates = st.radio("Would you like to view all dates or specific ones?", ('All', 'Specific Dates'), key='game_rot_dates')
|
622 |
+
|
623 |
+
if game_rot_dates == 'Specific Dates':
|
624 |
+
game_rot_low_date = st.date_input('Min Date:', value=None, format="YYYY-MM-DD", key='game_rot_low_date')
|
625 |
+
if game_rot_low_date is not None:
|
626 |
+
game_rot_low_date = pd.to_datetime(low_date).date()
|
627 |
+
game_rot_high_date = st.date_input('Max Date:', value=None, format="YYYY-MM-DD", key='game_rot_high_date')
|
628 |
+
if game_rot_high_date is not None:
|
629 |
+
game_rot_high_date = pd.to_datetime(high_date).date()
|
630 |
+
elif game_rot_dates == 'All':
|
631 |
+
game_rot_low_date = gamelog_table['Date'].min()
|
632 |
+
game_rot_high_date = gamelog_table['Date'].max()
|
633 |
+
|
634 |
+
|
635 |
+
|
636 |
+
with col2:
|
637 |
+
working_data = game_rot
|
638 |
+
if game_rot_view == 'Player Rotations':
|
639 |
+
display = st.container()
|
640 |
+
working_data = working_data[working_data['GAME_DATE'] >= game_rot_low_date]
|
641 |
+
working_data = working_data[working_data['GAME_DATE'] <= game_rot_high_date]
|
642 |
+
working_data = working_data[working_data['MIN'] >= game_rot_min[0]]
|
643 |
+
working_data = working_data[working_data['MIN'] <= game_rot_min[1]]
|
644 |
+
working_data = working_data[working_data['spread'] >= game_rot_spread[0]]
|
645 |
+
working_data = working_data[working_data['spread'] <= game_rot_spread[1]]
|
646 |
+
check_rotation = working_data[working_data['backlog_lookup'] == game_id_var]
|
647 |
+
|
648 |
+
fig = px.timeline(check_rotation, x_start="Start", x_end="Finish", y="Task", range_x=[0,check_rotation["Finish"].max()], text='minutes')
|
649 |
+
fig.update_yaxes(autorange="reversed")
|
650 |
+
|
651 |
+
fig.layout.xaxis.type = 'linear'
|
652 |
+
fig.data[0].x = check_rotation.delta.tolist()
|
653 |
+
fig.add_vline(x=12, line_width=3, line_dash="dash", line_color="green")
|
654 |
+
fig.add_vline(x=24, line_width=3, line_dash="dash", line_color="green")
|
655 |
+
fig.add_vline(x=36, line_width=3, line_dash="dash", line_color="green")
|
656 |
+
# pages = pages.set_index('Player')
|
657 |
+
display.plotly_chart(fig, use_container_width=True)
|
658 |
+
|
659 |
+
elif game_rot_view == 'Team Rotations':
|
660 |
+
display = st.container()
|
661 |
+
working_data = working_data[working_data['GAME_DATE'] >= game_rot_low_date]
|
662 |
+
working_data = working_data[working_data['GAME_DATE'] <= game_rot_high_date]
|
663 |
+
working_data = working_data[working_data['MIN'] >= game_rot_min[0]]
|
664 |
+
working_data = working_data[working_data['MIN'] <= game_rot_min[1]]
|
665 |
+
working_data = working_data[working_data['spread'] >= game_rot_spread[0]]
|
666 |
+
working_data = working_data[working_data['spread'] <= game_rot_spread[1]]
|
667 |
+
check_rotation = working_data[working_data['backlog_lookup'] == game_id_var]
|
668 |
+
|
669 |
+
fig = px.timeline(check_rotation, x_start="Start", x_end="Finish", y="Task", range_x=[0,check_rotation["Finish"].max()], text='minutes')
|
670 |
+
fig.update_yaxes(autorange="reversed")
|
671 |
+
|
672 |
+
fig.layout.xaxis.type = 'linear'
|
673 |
+
fig.data[0].x = check_rotation.delta.tolist()
|
674 |
+
fig.add_vline(x=12, line_width=3, line_dash="dash", line_color="green")
|
675 |
+
fig.add_vline(x=24, line_width=3, line_dash="dash", line_color="green")
|
676 |
+
fig.add_vline(x=36, line_width=3, line_dash="dash", line_color="green")
|
677 |
+
# pages = pages.set_index('Player')
|
678 |
+
display.plotly_chart(fig, use_container_width=True)
|