James McCool commited on
Commit
545350e
·
1 Parent(s): dee7fea

Initial commit from old app

Browse files
Files changed (5) hide show
  1. .streamlit/secrets.toml +1 -0
  2. Dockerfile +13 -0
  3. requirements.txt +11 -3
  4. src/database.py +30 -0
  5. src/streamlit_app.py +782 -36
.streamlit/secrets.toml ADDED
@@ -0,0 +1 @@
 
 
1
+ mongo_uri = "mongodb+srv://multichem:Xr1q5wZdXPbxdUmJ@testcluster.lgwtp5i.mongodb.net/?retryWrites=true&w=majority&appName=TestCluster"
Dockerfile CHANGED
@@ -5,11 +5,24 @@ WORKDIR /app
5
  RUN apt-get update && apt-get install -y \
6
  build-essential \
7
  curl \
 
8
  git \
9
  && rm -rf /var/lib/apt/lists/*
10
 
11
  COPY requirements.txt ./
12
  COPY src/ ./src/
 
 
 
 
 
 
 
 
 
 
 
 
13
 
14
  RUN pip3 install -r requirements.txt
15
 
 
5
  RUN apt-get update && apt-get install -y \
6
  build-essential \
7
  curl \
8
+ software-properties-common \
9
  git \
10
  && rm -rf /var/lib/apt/lists/*
11
 
12
  COPY requirements.txt ./
13
  COPY src/ ./src/
14
+ COPY .streamlit/ ./.streamlit/
15
+
16
+
17
+
18
+ ENV MONGO_URI="mongodb+srv://multichem:Xr1q5wZdXPbxdUmJ@testcluster.lgwtp5i.mongodb.net/?retryWrites=true&w=majority&appName=TestCluster"
19
+ RUN useradd -m -u 1000 user
20
+ USER user
21
+ ENV HOME=/home/user\
22
+ PATH=/home/user/.local/bin:$PATH
23
+ WORKDIR $HOME/app
24
+ RUN pip install --no-cache-dir --upgrade pip
25
+ COPY --chown=user . $HOME/app
26
 
27
  RUN pip3 install -r requirements.txt
28
 
requirements.txt CHANGED
@@ -1,3 +1,11 @@
1
- altair
2
- pandas
3
- streamlit
 
 
 
 
 
 
 
 
 
1
+ streamlit
2
+ gspread
3
+ openpyxl
4
+ matplotlib
5
+ streamlit-aggrid
6
+ pulp
7
+ docker
8
+ plotly
9
+ scipy
10
+ pymongo
11
+ gspread
src/database.py ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import pymongo
3
+ import gspread
4
+ import os
5
+
6
+ @st.cache_resource
7
+ def init_conn():
8
+ scope = ['https://spreadsheets.google.com/feeds', 'https://www.googleapis.com/auth/drive']
9
+
10
+ credentials = {
11
+ "type": "service_account",
12
+ "project_id": "model-sheets-connect",
13
+ "private_key_id": "0e0bc2fdef04e771172fe5807392b9d6639d945e",
14
+ "private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDiu1v/e6KBKOcK\ncx0KQ23nZK3ZVvADYy8u/RUn/EDI82QKxTd/DizRLIV81JiNQxDJXSzgkbwKYEDm\n48E8zGvupU8+Nk76xNPakrQKy2Y8+VJlq5psBtGchJTuUSHcXU5Mg2JhQsB376PJ\nsCw552K6Pw8fpeMDJDZuxpKSkaJR6k9G5Dhf5q8HDXnC5Rh/PRFuKJ2GGRpX7n+2\nhT/sCax0J8jfdTy/MDGiDfJqfQrOPrMKELtsGHR9Iv6F4vKiDqXpKfqH+02E9ptz\nBk+MNcbZ3m90M8ShfRu28ebebsASfarNMzc3dk7tb3utHOGXKCf4tF8yYKo7x8BZ\noO9X4gSfAgMBAAECggEAU8ByyMpSKlTCF32TJhXnVJi/kS+IhC/Qn5JUDMuk4LXr\naAEWsWO6kV/ZRVXArjmuSzuUVrXumISapM9Ps5Ytbl95CJmGDiLDwRL815nvv6k3\nUyAS8EGKjz74RpoIoH6E7EWCAzxlnUgTn+5oP9Flije97epYk3H+e2f1f5e1Nn1d\nYNe8U+1HqJgILcxA1TAUsARBfoD7+K3z/8DVPHI8IpzAh6kTHqhqC23Rram4XoQ6\nzj/ZdVBjvnKuazETfsD+Vl3jGLQA8cKQVV70xdz3xwLcNeHsbPbpGBpZUoF73c65\nkAXOrjYl0JD5yAk+hmYhXr6H9c6z5AieuZGDrhmlFQKBgQDzV6LRXmjn4854DP/J\nI82oX2GcI4eioDZPRukhiQLzYerMQBmyqZIRC+/LTCAhYQSjNgMa+ZKyvLqv48M0\n/x398op/+n3xTs+8L49SPI48/iV+mnH7k0WI/ycd4OOKh8rrmhl/0EWb9iitwJYe\nMjTV/QxNEpPBEXfR1/mvrN/lVQKBgQDuhomOxUhWVRVH6x03slmyRBn0Oiw4MW+r\nrt1hlNgtVmTc5Mu+4G0USMZwYuOB7F8xG4Foc7rIlwS7Ic83jMJxemtqAelwOLdV\nXRLrLWJfX8+O1z/UE15l2q3SUEnQ4esPHbQnZowHLm0mdL14qSVMl1mu1XfsoZ3z\nJZTQb48CIwKBgEWbzQRtKD8lKDupJEYqSrseRbK/ax43DDITS77/DWwHl33D3FYC\nMblUm8ygwxQpR4VUfwDpYXBlklWcJovzamXpSnsfcYVkkQH47NuOXPXPkXQsw+w+\nDYcJzeu7F/vZqk9I7oBkWHUrrik9zPNoUzrfPvSRGtkAoTDSwibhoc5dAoGBAMHE\nK0T/ANeZQLNuzQps6S7G4eqjwz5W8qeeYxsdZkvWThOgDd/ewt3ijMnJm5X05hOn\ni4XF1euTuvUl7wbqYx76Wv3/1ZojiNNgy7ie4rYlyB/6vlBS97F4ZxJdxMlabbCW\n6b3EMWa4EVVXKoA1sCY7IVDE+yoQ1JYsZmq45YzPAoGBANWWHuVueFGZRDZlkNlK\nh5OmySmA0NdNug3G1upaTthyaTZ+CxGliwBqMHAwpkIRPwxUJpUwBTSEGztGTAxs\nWsUOVWlD2/1JaKSmHE8JbNg6sxLilcG6WEDzxjC5dLL1OrGOXj9WhC9KX3sq6qb6\nF/j9eUXfXjAlb042MphoF3ZC\n-----END PRIVATE KEY-----\n",
15
+ "client_email": "gspread-connection@model-sheets-connect.iam.gserviceaccount.com",
16
+ "client_id": "100369174533302798535",
17
+ "auth_uri": "https://accounts.google.com/o/oauth2/auth",
18
+ "token_uri": "https://oauth2.googleapis.com/token",
19
+ "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
20
+ "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/gspread-connection%40model-sheets-connect.iam.gserviceaccount.com"
21
+ }
22
+ uri = "mongodb+srv://multichem:Xr1q5wZdXPbxdUmJ@testcluster.lgwtp5i.mongodb.net/?retryWrites=true&w=majority&appName=TestCluster"
23
+ client = pymongo.MongoClient(uri, retryWrites=True, serverSelectionTimeoutMS=100000)
24
+ db = client["testing_db"]
25
+
26
+ gc_con = gspread.service_account_from_dict(credentials, scope)
27
+
28
+ return gc_con, db
29
+
30
+ gcservice_account, db = init_conn()
src/streamlit_app.py CHANGED
@@ -1,40 +1,786 @@
1
- import altair as alt
 
 
 
 
 
 
2
  import numpy as np
3
  import pandas as pd
4
  import streamlit as st
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5
 
6
- """
7
- # Welcome to Streamlit!
8
-
9
- Edit `/streamlit_app.py` to customize this app to your heart's desire :heart:.
10
- If you have any questions, checkout our [documentation](https://docs.streamlit.io) and [community
11
- forums](https://discuss.streamlit.io).
12
-
13
- In the meantime, below is an example of what you can do with just a few lines of code:
14
- """
15
-
16
- num_points = st.slider("Number of points in spiral", 1, 10000, 1100)
17
- num_turns = st.slider("Number of turns in spiral", 1, 300, 31)
18
-
19
- indices = np.linspace(0, 1, num_points)
20
- theta = 2 * np.pi * num_turns * indices
21
- radius = indices
22
-
23
- x = radius * np.cos(theta)
24
- y = radius * np.sin(theta)
25
-
26
- df = pd.DataFrame({
27
- "x": x,
28
- "y": y,
29
- "idx": indices,
30
- "rand": np.random.randn(num_points),
31
- })
32
-
33
- st.altair_chart(alt.Chart(df, height=700, width=700)
34
- .mark_point(filled=True)
35
- .encode(
36
- x=alt.X("x", axis=None),
37
- y=alt.Y("y", axis=None),
38
- color=alt.Color("idx", legend=None, scale=alt.Scale()),
39
- size=alt.Size("rand", legend=None, scale=alt.Scale(range=[1, 150])),
40
- ))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ st.set_page_config(layout="wide")
3
+
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 plotly.express as px
12
+ import plotly.graph_objects as go
13
+ import plotly.io as pio
14
+ import certifi
15
+ ca = certifi.where()
16
+ from database import gcservice_account, db
17
+
18
+ NBA_Data = 'https://docs.google.com/spreadsheets/d/1Yq0vGriWK-bS79e-bD6_u9pqrYE6Yrlbb_wEkmH-ot0/edit#gid=1808117109'
19
+
20
+ percentages_format = {'PG': '{:.2%}', 'SG': '{:.2%}', 'SF': '{:.2%}', 'PF': '{:.2%}', 'C': '{:.2%}'}
21
+
22
+ @st.cache_resource(ttl = 599)
23
+ def init_baselines():
24
+ sh = gcservice_account.open_by_url(NBA_Data)
25
+ collection = db["gamelog"]
26
+ cursor = collection.find() # Finds all documents in the collection
27
+
28
+ raw_display = pd.DataFrame(list(cursor))
29
+ gamelog_table = raw_display[raw_display['PLAYER_NAME'] != ""]
30
+ gamelog_table = gamelog_table[['PLAYER_NAME', 'POS', 'GAME_ID', 'TEAM_NAME', 'OPP_NAME', 'SEASON_ID', 'GAME_DATE', 'MATCHUP', 'MIN', 'touches', 'PTS', 'FGM', 'FGA', 'FG_PCT', 'FG3M', 'FG3A',
31
+ 'FG3_PCT', 'FTM', 'FTA', 'FT_PCT', 'reboundChancesOffensive', 'OREB', 'reboundChancesDefensive', 'DREB', 'reboundChancesTotal', 'REB',
32
+ 'passes', 'secondaryAssists', 'freeThrowAssists', 'assists', 'STL', 'BLK', 'TOV', 'PF', 'DD', 'TD', 'Fantasy', 'FD_Fantasy', 'FPPM']]
33
+ gamelog_table['assists'].replace("", 0, inplace=True)
34
+ gamelog_table['reboundChancesTotal'].replace("", 0, inplace=True)
35
+ gamelog_table['passes'].replace("", 0, inplace=True)
36
+ gamelog_table['touches'].replace("", 0, inplace=True)
37
+ gamelog_table['MIN'].replace("", 0, inplace=True)
38
+ gamelog_table['Fantasy'].replace("", 0, inplace=True)
39
+ gamelog_table['FD_Fantasy'].replace("", 0, inplace=True)
40
+ gamelog_table['FPPM'].replace("", 0, inplace=True)
41
+ gamelog_table['REB'] = gamelog_table['REB'].astype(int)
42
+ gamelog_table['assists'] = gamelog_table['assists'].astype(int)
43
+ gamelog_table['reboundChancesTotal'] = gamelog_table['reboundChancesTotal'].astype(int)
44
+ gamelog_table['passes'] = gamelog_table['passes'].astype(int)
45
+ gamelog_table['touches'] = gamelog_table['touches'].astype(int)
46
+ gamelog_table['MIN'] = gamelog_table['MIN'].astype(int)
47
+ gamelog_table['Fantasy'] = gamelog_table['Fantasy'].astype(float)
48
+ gamelog_table['FD_Fantasy'] = gamelog_table['FD_Fantasy'].astype(float)
49
+ gamelog_table['FPPM'] = gamelog_table['FPPM'].astype(float)
50
+ gamelog_table['rebound%'] = gamelog_table['REB'] / gamelog_table['reboundChancesTotal']
51
+ gamelog_table['assists_per_pass'] = gamelog_table['assists'] / gamelog_table['passes']
52
+ gamelog_table['Touch_per_min'] = gamelog_table['touches'] / gamelog_table['MIN']
53
+ gamelog_table['Fantasy_per_touch'] = gamelog_table['Fantasy'] / gamelog_table['touches']
54
+ gamelog_table['FD_Fantasy_per_touch'] = gamelog_table['FD_Fantasy'] / gamelog_table['touches']
55
+ data_cols = gamelog_table.columns.drop(['PLAYER_NAME', 'POS', 'TEAM_NAME', 'OPP_NAME', 'SEASON_ID', 'GAME_DATE', 'MATCHUP'])
56
+ gamelog_table[data_cols] = gamelog_table[data_cols].apply(pd.to_numeric, errors='coerce')
57
+ gamelog_table['team_score'] = gamelog_table.groupby(['TEAM_NAME', 'GAME_ID'], sort=False)['PTS'].transform('sum')
58
+ gamelog_table['opp_score'] = gamelog_table.groupby(['GAME_ID'], sort=False)['PTS'].transform('sum') - gamelog_table['team_score']
59
+ gamelog_table['spread'] = (gamelog_table['opp_score'] - gamelog_table['team_score']).abs()
60
+ gamelog_table['GAME_DATE'] = pd.to_datetime(gamelog_table['GAME_DATE']).dt.date
61
+
62
+ spread_dict = dict(zip(gamelog_table['GAME_ID'], gamelog_table['spread']))
63
+
64
+ gamelog_table = gamelog_table.set_axis(['Player', 'Pos', 'game_id', 'Team', 'Opp', 'Season', 'Date', 'Matchup', 'Min', 'Touches', 'Pts', 'FGM', 'FGA', 'FG%', 'FG3M',
65
+ 'FG3A', 'FG3%', 'FTM', 'FTA', 'FT%', 'OREB Chance', 'OREB', 'DREB Chance', 'DREB', 'REB Chance', 'REB',
66
+ 'Passes', 'Alt Assists', 'FT Assists', 'Assists', 'Stl', 'Blk', 'Tov', 'PF', 'DD', 'TD', 'Fantasy', 'FD_Fantasy', 'FPPM',
67
+ 'Rebound%', 'Assists/Pass', 'Touch_per_min', 'Fantasy/Touch', 'FD Fantasy/Touch', 'team_score', 'opp_score', 'spread'], axis=1)
68
+
69
+ worksheet = sh.worksheet('Rotations')
70
+ raw_display = pd.DataFrame(worksheet.get_values())
71
+ raw_display.columns = raw_display.iloc[0]
72
+ raw_display = raw_display[1:]
73
+ raw_display = raw_display.reset_index(drop=True)
74
+ rot_table = raw_display[raw_display['Player'] != ""]
75
+ rot_table = rot_table[['Player', 'Team', 'PG', 'SG', 'SF', 'PF', 'C', 'Given_Pos']]
76
+ data_cols = ['PG', 'SG', 'SF', 'PF', 'C']
77
+ rot_table[data_cols] = rot_table[data_cols].apply(pd.to_numeric, errors='coerce')
78
+ rot_table = rot_table[rot_table['Player'] != 0]
79
+
80
+ collection = db["rotations"]
81
+ cursor = collection.find() # Finds all documents in the collection
82
+
83
+ raw_display = pd.DataFrame(list(cursor))
84
+ game_rot = raw_display[raw_display['PLAYER_NAME'] != ""]
85
+ data_cols = game_rot.columns.drop(['PLAYER_NAME', 'POS', 'TEAM_ABBREVIATION', 'OPP_ABBREVIATION', 'TEAM_NAME', 'OPP_NAME', 'GAME_DATE',
86
+ 'MATCHUP', 'WL', 'backlog_lookup', 'Task', 'game_players'])
87
+ game_rot[data_cols] = game_rot[data_cols].apply(pd.to_numeric, errors='coerce')
88
+ game_rot['spread'] = game_rot['GAME_ID'].map(spread_dict)
89
+ game_rot['GAME_DATE'] = pd.to_datetime(game_rot['GAME_DATE']).dt.date
90
+
91
+ timestamp = gamelog_table['Date'].max()
92
+
93
+ return gamelog_table, rot_table, game_rot, timestamp
94
+
95
+ @st.cache_data(show_spinner=False)
96
+ def seasonlong_build(data_sample):
97
+ season_long_table = data_sample[['Player', 'Pos', 'Team']]
98
+ season_long_table['Min'] = data_sample.groupby(['Player', 'Season'], sort=False)['Min'].transform('mean').astype(float)
99
+ season_long_table['Touches'] = data_sample.groupby(['Player', 'Season'], sort=False)['Touches'].transform('mean').astype(float)
100
+ season_long_table['Touch/Min'] = (data_sample.groupby(['Player', 'Season'], sort=False)['Touches'].transform('sum').astype(int) /
101
+ data_sample.groupby(['Player', 'Season'], sort=False)['Min'].transform('sum').astype(int))
102
+ season_long_table['Pts'] = data_sample.groupby(['Player', 'Season'], sort=False)['Pts'].transform('mean').astype(float)
103
+ season_long_table['FGM'] = data_sample.groupby(['Player', 'Season'], sort=False)['FGM'].transform('mean').astype(float)
104
+ season_long_table['FGA'] = data_sample.groupby(['Player', 'Season'], sort=False)['FGA'].transform('mean').astype(float)
105
+ season_long_table['FG%'] = (data_sample.groupby(['Player', 'Season'], sort=False)['FGM'].transform('sum').astype(int) /
106
+ data_sample.groupby(['Player', 'Season'], sort=False)['FGA'].transform('sum').astype(int))
107
+ season_long_table['FG3M'] = data_sample.groupby(['Player', 'Season'], sort=False)['FG3M'].transform('mean').astype(float)
108
+ season_long_table['FG3A'] = data_sample.groupby(['Player', 'Season'], sort=False)['FG3A'].transform('mean').astype(float)
109
+ season_long_table['FG3%'] = (data_sample.groupby(['Player', 'Season'], sort=False)['FG3M'].transform('sum').astype(int) /
110
+ data_sample.groupby(['Player', 'Season'], sort=False)['FG3A'].transform('sum').astype(int))
111
+ season_long_table['FTM'] = data_sample.groupby(['Player', 'Season'], sort=False)['FTM'].transform('mean').astype(float)
112
+ season_long_table['FTA'] = data_sample.groupby(['Player', 'Season'], sort=False)['FTA'].transform('mean').astype(float)
113
+ season_long_table['FT%'] = (data_sample.groupby(['Player', 'Season'], sort=False)['FTM'].transform('sum').astype(int) /
114
+ data_sample.groupby(['Player', 'Season'], sort=False)['FTA'].transform('sum').astype(int))
115
+ season_long_table['OREB Chance'] = data_sample.groupby(['Player', 'Season'], sort=False)['OREB Chance'].transform('mean').astype(float)
116
+ season_long_table['OREB'] = data_sample.groupby(['Player', 'Season'], sort=False)['OREB'].transform('mean').astype(float)
117
+ season_long_table['DREB Chance'] = data_sample.groupby(['Player', 'Season'], sort=False)['DREB Chance'].transform('mean').astype(float)
118
+ season_long_table['DREB'] = data_sample.groupby(['Player', 'Season'], sort=False)['DREB'].transform('mean').astype(float)
119
+ season_long_table['REB Chance'] = data_sample.groupby(['Player', 'Season'], sort=False)['REB Chance'].transform('mean').astype(float)
120
+ season_long_table['REB'] = data_sample.groupby(['Player', 'Season'], sort=False)['REB'].transform('mean').astype(float)
121
+ season_long_table['Passes'] = data_sample.groupby(['Player', 'Season'], sort=False)['Passes'].transform('mean').astype(float)
122
+ season_long_table['Alt Assists'] = data_sample.groupby(['Player', 'Season'], sort=False)['Alt Assists'].transform('mean').astype(float)
123
+ season_long_table['FT Assists'] = data_sample.groupby(['Player', 'Season'], sort=False)['FT Assists'].transform('mean').astype(float)
124
+ season_long_table['Assists'] = data_sample.groupby(['Player', 'Season'], sort=False)['Assists'].transform('mean').astype(float)
125
+ season_long_table['Stl'] = data_sample.groupby(['Player', 'Season'], sort=False)['Stl'].transform('mean').astype(float)
126
+ season_long_table['Blk'] = data_sample.groupby(['Player', 'Season'], sort=False)['Blk'].transform('mean').astype(float)
127
+ season_long_table['Tov'] = data_sample.groupby(['Player', 'Season'], sort=False)['Tov'].transform('mean').astype(float)
128
+ season_long_table['PF'] = data_sample.groupby(['Player', 'Season'], sort=False)['PF'].transform('mean').astype(float)
129
+ season_long_table['DD'] = data_sample.groupby(['Player', 'Season'], sort=False)['DD'].transform('mean').astype(float)
130
+ season_long_table['TD'] = data_sample.groupby(['Player', 'Season'], sort=False)['TD'].transform('mean').astype(float)
131
+ season_long_table['Fantasy'] = data_sample.groupby(['Player', 'Season'], sort=False)['Fantasy'].transform('mean').astype(float)
132
+ season_long_table['FD_Fantasy'] = data_sample.groupby(['Player', 'Season'], sort=False)['FD_Fantasy'].transform('mean').astype(float)
133
+ season_long_table['FPPM'] = data_sample.groupby(['Player', 'Season'], sort=False)['FPPM'].transform('mean').astype(float)
134
+ season_long_table['Rebound%'] = (data_sample.groupby(['Player', 'Season'], sort=False)['REB'].transform('sum').astype(int) /
135
+ data_sample.groupby(['Player', 'Season'], sort=False)['REB Chance'].transform('sum').astype(int))
136
+ season_long_table['Assists/Pass'] = (data_sample.groupby(['Player', 'Season'], sort=False)['Assists'].transform('sum').astype(int) /
137
+ data_sample.groupby(['Player', 'Season'], sort=False)['Passes'].transform('sum').astype(int))
138
+ season_long_table['Fantasy/Touch'] = (data_sample.groupby(['Player', 'Season'], sort=False)['Fantasy'].transform('sum').astype(int) /
139
+ data_sample.groupby(['Player', 'Season'], sort=False)['Touches'].transform('sum').astype(int))
140
+ season_long_table['FD Fantasy/Touch'] = (data_sample.groupby(['Player', 'Season'], sort=False)['FD_Fantasy'].transform('sum').astype(int) /
141
+ data_sample.groupby(['Player', 'Season'], sort=False)['Touches'].transform('sum').astype(int))
142
+ season_long_table = season_long_table.drop_duplicates(subset='Player')
143
+
144
+ season_long_table = season_long_table.sort_values(by='Fantasy', ascending=False)
145
+
146
+ season_long_table = season_long_table.set_axis(['Player', 'Pos', 'Team', 'Min', 'Touches', 'Touch/Min', 'Pts', 'FGM', 'FGA', 'FG%', 'FG3M', 'FG3A',
147
+ 'FG3%', 'FTM', 'FTA', 'FT%', 'OREB Chance', 'OREB', 'DREB Chance', 'DREB', 'REB Chance', 'REB',
148
+ 'Passes', 'Alt Assists', 'FT Assists', 'Assists', 'Stl', 'Blk', 'Tov', 'PF', 'DD', 'TD', 'Fantasy', 'FD_Fantasy',
149
+ 'FPPM', 'Rebound%', 'Assists/Pass', 'Fantasy/Touch', 'FD Fantasy/Touch'], axis=1)
150
+
151
+ return season_long_table
152
+
153
+ @st.cache_data(show_spinner=False)
154
+ def run_fantasy_corr(data_sample):
155
+ cor_testing = data_sample
156
+ cor_testing = cor_testing[cor_testing['Season'] == '22024']
157
+ date_list = cor_testing['Date'].unique().tolist()
158
+ player_list = cor_testing['Player'].unique().tolist()
159
+ corr_frame = pd.DataFrame()
160
+ corr_frame['DATE'] = date_list
161
+ for player in player_list:
162
+ player_testing = cor_testing[cor_testing['Player'] == player]
163
+ fantasy_map = dict(zip(player_testing['Date'], player_testing['Fantasy']))
164
+ corr_frame[player] = corr_frame['DATE'].map(fantasy_map)
165
+ players_fantasy = corr_frame.drop('DATE', axis=1)
166
+ corrM = players_fantasy.corr()
167
+
168
+ return corrM
169
+
170
+ @st.cache_data(show_spinner=False)
171
+ def run_min_corr(data_sample):
172
+ cor_testing = data_sample
173
+ cor_testing = cor_testing[cor_testing['Season'] == '22024']
174
+ date_list = cor_testing['Date'].unique().tolist()
175
+ player_list = cor_testing['Player'].unique().tolist()
176
+ corr_frame = pd.DataFrame()
177
+ corr_frame['DATE'] = date_list
178
+ for player in player_list:
179
+ player_testing = cor_testing[cor_testing['Player'] == player]
180
+ fantasy_map = dict(zip(player_testing['Date'], player_testing['Min']))
181
+ corr_frame[player] = corr_frame['DATE'].map(fantasy_map)
182
+ players_fantasy = corr_frame.drop('DATE', axis=1)
183
+ corrM = players_fantasy.corr()
184
+
185
+ return corrM
186
+
187
+ @st.cache_data(show_spinner=False)
188
+ def split_frame(input_df, rows):
189
+ df = [input_df.loc[i : i + rows - 1, :] for i in range(0, len(input_df), rows)]
190
+ return df
191
+
192
+ def convert_df_to_csv(df):
193
+ return df.to_csv().encode('utf-8')
194
+
195
+ gamelog_table, rot_table, game_rot, timestamp = init_baselines()
196
+ t_stamp = f"Updated through: " + str(timestamp) + f" CST"
197
+ basic_cols = ['Player', 'Pos', 'Team', 'Opp', 'Season', 'Date', 'Matchup', 'Min']
198
+ basic_season_cols = ['Pos', 'Team', 'Min']
199
+ data_cols = ['team_score', 'opp_score', 'spread', 'Touches', 'Pts', 'FGM', 'FGA', 'FG%', 'FG3M',
200
+ 'FG3A', 'FG3%', 'FTM', 'FTA', 'FT%', 'OREB Chance', 'OREB', 'DREB Chance', 'DREB', 'REB Chance', 'REB',
201
+ 'Passes', 'Alt Assists', 'FT Assists', 'Assists', 'Stl', 'Blk', 'Tov', 'PF', 'DD', 'TD', 'Fantasy', 'FD_Fantasy',
202
+ 'FPPM', 'Rebound%', 'Assists/Pass', 'Touch_per_min', 'Fantasy/Touch', 'FD Fantasy/Touch']
203
+ season_data_cols = ['Touches', 'Touch/Min', 'Pts', 'FGM', 'FGA', 'FG%', 'FG3M', 'FG3A',
204
+ 'FG3%', 'FTM', 'FTA', 'FT%', 'OREB Chance', 'OREB', 'DREB Chance', 'DREB', 'REB Chance', 'REB',
205
+ 'Passes', 'Alt Assists', 'FT Assists', 'Assists', 'Stl', 'Blk', 'Tov', 'PF', 'DD', 'TD', 'Fantasy', 'FD_Fantasy',
206
+ 'FPPM', 'Rebound%', 'Assists/Pass', 'Fantasy/Touch', 'FD Fantasy/Touch']
207
+ game_rot_cols = ['PLAYER_NAME', 'backlog_lookup', 'spread', 'MIN', 'PTS', 'FGM', 'FGA', 'FG3M', 'FG3A', 'FTM', 'FTA', 'REB', 'AST', 'STL', 'BLK', 'TOV', 'PF',
208
+ 'Fantasy', 'FD_Fantasy']
209
+ indv_teams = gamelog_table.drop_duplicates(subset='Team')
210
+ total_teams = indv_teams.Team.values.tolist()
211
+ indv_rot_teams = rot_table.drop_duplicates(subset='Team')
212
+ total_rot_teams = indv_rot_teams.Team.values.tolist()
213
+ indv_game_rot_teams = game_rot.drop_duplicates(subset='TEAM_ABBREVIATION')
214
+ total_game_rot_teams = indv_game_rot_teams.TEAM_ABBREVIATION.values.tolist()
215
+ indv_players = gamelog_table.drop_duplicates(subset='Player')
216
+ total_players = indv_players.Player.values.tolist()
217
+ total_dates = gamelog_table.Date.values.tolist()
218
+
219
+ tab1, tab2, tab3, tab4, tab5 = st.tabs(['Gamelogs', 'Correlation Matrix', 'Position vs. Opp', 'Positional Percentages', 'Game Rotations'])
220
+
221
+ with tab1:
222
+ st.info(t_stamp)
223
+ col1, col2 = st.columns([1, 9])
224
+ with col1:
225
+ if st.button("Reset Data", key='reset1'):
226
+ st.cache_data.clear()
227
+ gamelog_table, rot_table, game_rot, timestamp = init_baselines()
228
+ basic_cols = ['Player', 'Pos', 'Team', 'Opp', 'Season', 'Date', 'Matchup', 'Min']
229
+ basic_season_cols = ['Pos', 'Team', 'Min']
230
+ data_cols = ['team_score', 'opp_score', 'spread', 'Touches', 'Pts', 'FGM', 'FGA', 'FG%', 'FG3M',
231
+ 'FG3A', 'FG3%', 'FTM', 'FTA', 'FT%', 'OREB Chance', 'OREB', 'DREB Chance', 'DREB', 'REB Chance', 'REB',
232
+ 'Passes', 'Alt Assists', 'FT Assists', 'Assists', 'Stl', 'Blk', 'Tov', 'PF', 'DD', 'TD', 'Fantasy', 'FD_Fantasy',
233
+ 'FPPM', 'Rebound%', 'Assists/Pass', 'Touch_per_min', 'Fantasy/Touch', 'FD Fantasy/Touch']
234
+ season_data_cols = ['Touches', 'Touch/Min', 'Pts', 'FGM', 'FGA', 'FG%', 'FG3M', 'FG3A',
235
+ 'FG3%', 'FTM', 'FTA', 'FT%', 'OREB Chance', 'OREB', 'DREB Chance', 'DREB', 'REB Chance', 'REB',
236
+ 'Passes', 'Alt Assists', 'FT Assists', 'Assists', 'Stl', 'Blk', 'Tov', 'PF', 'DD', 'TD', 'Fantasy', 'FD_Fantasy',
237
+ 'FPPM', 'Rebound%', 'Assists/Pass', 'Fantasy/Touch', 'FD Fantasy/Touch']
238
+ game_rot_cols = ['PLAYER_NAME', 'backlog_lookup', 'spread', 'MIN', 'PTS', 'FGM', 'FGA', 'FG3M', 'FG3A', 'FTM', 'FTA', 'REB', 'AST', 'STL', 'BLK', 'TOV', 'PF',
239
+ 'Fantasy', 'FD_Fantasy']
240
+ indv_teams = gamelog_table.drop_duplicates(subset='Team')
241
+ total_teams = indv_teams.Team.values.tolist()
242
+ indv_rot_teams = rot_table.drop_duplicates(subset='Team')
243
+ total_rot_teams = indv_rot_teams.Team.values.tolist()
244
+ indv_game_rot_teams = game_rot.drop_duplicates(subset='TEAM_ABBREVIATION')
245
+ total_game_rot_teams = indv_game_rot_teams.TEAM_ABBREVIATION.values.tolist()
246
+ indv_players = gamelog_table.drop_duplicates(subset='Player')
247
+ total_players = indv_players.Player.values.tolist()
248
+ total_dates = gamelog_table.Date.values.tolist()
249
+
250
+ split_var1 = st.radio("What table would you like to view?", ('Season Logs', 'Gamelogs'), key='split_var1')
251
+ split_var2 = st.radio("Would you like to view all teams or specific ones?", ('All', 'Specific Teams'), key='split_var2')
252
+
253
+ if split_var2 == 'Specific Teams':
254
+ team_var1 = st.multiselect('Which teams would you like to include in the tables?', options = total_teams, key='team_var1')
255
+ elif split_var2 == 'All':
256
+ team_var1 = total_teams
257
+
258
+ split_var3 = st.radio("Would you like to view all dates or specific ones?", ('All', 'Specific Dates'), key='split_var3')
259
+
260
+ if split_var3 == 'Specific Dates':
261
+ low_date = st.date_input('Min Date:', value=None, format="YYYY-MM-DD", key='low_date')
262
+ if low_date is not None:
263
+ low_date = pd.to_datetime(low_date).date()
264
+ high_date = st.date_input('Max Date:', value=None, format="YYYY-MM-DD", key='high_date')
265
+ if high_date is not None:
266
+ high_date = pd.to_datetime(high_date).date()
267
+ elif split_var3 == 'All':
268
+ low_date = gamelog_table['Date'].min()
269
+ high_date = gamelog_table['Date'].max()
270
+
271
+ split_var4 = st.radio("Would you like to view all players or specific ones?", ('All', 'Specific Players'), key='split_var4')
272
+
273
+ if split_var4 == 'Specific Players':
274
+ player_var1 = st.multiselect('Which players would you like to include in the tables?', options = total_players, key='player_var1')
275
+ elif split_var4 == 'All':
276
+ player_var1 = total_players
277
+
278
+ spread_var1 = st.slider("Is there a certain spread range you want to view?", 0, 100, (0, 100), key='spread_var1')
279
+
280
+ min_var1 = st.slider("Is there a certain minutes range you want to view?", 0, 60, (0, 60), key='min_var1')
281
+
282
+ with col2:
283
+ working_data = gamelog_table
284
+ if split_var1 == 'Season Logs':
285
+ choose_cols = st.container()
286
+ with choose_cols:
287
+ choose_disp = st.multiselect('Which stats would you like to view?', options = season_data_cols, default = season_data_cols, key='col_display')
288
+ disp_stats = basic_season_cols + choose_disp
289
+ display = st.container()
290
+ working_data = working_data[working_data['Date'] >= low_date]
291
+ working_data = working_data[working_data['Date'] <= high_date]
292
+ working_data = working_data[working_data['Min'] >= min_var1[0]]
293
+ working_data = working_data[working_data['Min'] <= min_var1[1]]
294
+ working_data = working_data[working_data['spread'] >= spread_var1[0]]
295
+ working_data = working_data[working_data['spread'] <= spread_var1[1]]
296
+ working_data = working_data[working_data['Team'].isin(team_var1)]
297
+ working_data = working_data[working_data['Player'].isin(player_var1)]
298
+ season_long_table = seasonlong_build(working_data)
299
+ season_long_table = season_long_table.set_index('Player')
300
+ season_long_table_disp = season_long_table.reindex(disp_stats,axis="columns")
301
+ display.dataframe(season_long_table_disp.style.format(precision=2), height=750, use_container_width = True)
302
+ st.download_button(
303
+ label="Export seasonlogs Model",
304
+ data=convert_df_to_csv(season_long_table),
305
+ file_name='Seasonlogs_NBA_View.csv',
306
+ mime='text/csv',
307
+ )
308
+
309
+ elif split_var1 == 'Gamelogs':
310
+ choose_cols = st.container()
311
+ with choose_cols:
312
+ choose_disp_gamelog = st.multiselect('Which stats would you like to view?', options = data_cols, default = data_cols, key='choose_disp_gamelog')
313
+ gamelog_disp_stats = basic_cols + choose_disp_gamelog
314
+ working_data = working_data[working_data['Date'] >= low_date]
315
+ working_data = working_data[working_data['Date'] <= high_date]
316
+ working_data = working_data[working_data['Min'] >= min_var1[0]]
317
+ working_data = working_data[working_data['Min'] <= min_var1[1]]
318
+ working_data = working_data[working_data['spread'] >= spread_var1[0]]
319
+ working_data = working_data[working_data['spread'] <= spread_var1[1]]
320
+ working_data = working_data[working_data['Team'].isin(team_var1)]
321
+ working_data = working_data[working_data['Player'].isin(player_var1)]
322
+ working_data = working_data.reset_index(drop=True)
323
+ gamelog_data = working_data.reindex(gamelog_disp_stats,axis="columns")
324
+ display = st.container()
325
+
326
+ bottom_menu = st.columns((4, 1, 1))
327
+ with bottom_menu[2]:
328
+ batch_size = st.selectbox("Page Size", options=[25, 50, 100])
329
+ with bottom_menu[1]:
330
+ total_pages = (
331
+ int(len(gamelog_data) / batch_size) if int(len(gamelog_data) / batch_size) > 0 else 1
332
+ )
333
+ current_page = st.number_input(
334
+ "Page", min_value=1, max_value=total_pages, step=1
335
+ )
336
+ with bottom_menu[0]:
337
+ st.markdown(f"Page **{current_page}** of **{total_pages}** ")
338
+
339
+
340
+ pages = split_frame(gamelog_data, batch_size)
341
+ # pages = pages.set_index('Player')
342
+ display.dataframe(data=pages[current_page - 1].style.format(precision=2), height=500, use_container_width=True)
343
+ st.download_button(
344
+ label="Export gamelogs Model",
345
+ data=convert_df_to_csv(gamelog_data),
346
+ file_name='Gamelogs_NBA_View.csv',
347
+ mime='text/csv',
348
+ )
349
+
350
+ with tab2:
351
+ st.info(t_stamp)
352
+ col1, col2 = st.columns([1, 9])
353
+ with col1:
354
+ if st.button("Reset Data", key='reset2'):
355
+ st.cache_data.clear()
356
+ gamelog_table, rot_table, game_rot, timestamp = init_baselines()
357
+ basic_cols = ['Player', 'Pos', 'Team', 'Opp', 'Season', 'Date', 'Matchup', 'Min']
358
+ basic_season_cols = ['Pos', 'Team', 'Min']
359
+ data_cols = ['team_score', 'opp_score', 'spread', 'Touches', 'Pts', 'FGM', 'FGA', 'FG%', 'FG3M',
360
+ 'FG3A', 'FG3%', 'FTM', 'FTA', 'FT%', 'OREB Chance', 'OREB', 'DREB Chance', 'DREB', 'REB Chance', 'REB',
361
+ 'Passes', 'Alt Assists', 'FT Assists', 'Assists', 'Stl', 'Blk', 'Tov', 'PF', 'DD', 'TD', 'Fantasy', 'FD_Fantasy',
362
+ 'FPPM', 'Rebound%', 'Assists/Pass', 'Touch_per_min', 'Fantasy/Touch', 'FD Fantasy/Touch']
363
+ season_data_cols = ['Touches', 'Touch/Min', 'Pts', 'FGM', 'FGA', 'FG%', 'FG3M', 'FG3A',
364
+ 'FG3%', 'FTM', 'FTA', 'FT%', 'OREB Chance', 'OREB', 'DREB Chance', 'DREB', 'REB Chance', 'REB',
365
+ 'Passes', 'Alt Assists', 'FT Assists', 'Assists', 'Stl', 'Blk', 'Tov', 'PF', 'DD', 'TD', 'Fantasy', 'FD_Fantasy',
366
+ 'FPPM', 'Rebound%', 'Assists/Pass', 'Fantasy/Touch', 'FD Fantasy/Touch']
367
+ game_rot_cols = ['PLAYER_NAME', 'backlog_lookup', 'spread', 'MIN', 'PTS', 'FGM', 'FGA', 'FG3M', 'FG3A', 'FTM', 'FTA', 'REB', 'AST', 'STL', 'BLK', 'TOV', 'PF',
368
+ 'Fantasy', 'FD_Fantasy']
369
+ indv_teams = gamelog_table.drop_duplicates(subset='Team')
370
+ total_teams = indv_teams.Team.values.tolist()
371
+ indv_rot_teams = rot_table.drop_duplicates(subset='Team')
372
+ total_rot_teams = indv_rot_teams.Team.values.tolist()
373
+ indv_game_rot_teams = game_rot.drop_duplicates(subset='TEAM_ABBREVIATION')
374
+ total_game_rot_teams = indv_game_rot_teams.TEAM_ABBREVIATION.values.tolist()
375
+ indv_players = gamelog_table.drop_duplicates(subset='Player')
376
+ total_players = indv_players.Player.values.tolist()
377
+ total_dates = gamelog_table.Date.values.tolist()
378
+
379
+ corr_var = st.radio("Are you correlating fantasy or minutes?", ('Fantasy', 'Minutes'), key='corr_var')
380
+
381
+ split_var1_t2 = st.radio("Would you like to view specific teams or specific players?", ('Specific Teams', 'Specific Players'), key='split_var1_t2')
382
+
383
+ if split_var1_t2 == 'Specific Teams':
384
+ corr_var1_t2 = st.multiselect('Which teams would you like to include in the correlation?', options = total_teams, key='corr_var1_t2')
385
+ elif split_var1_t2 == 'Specific Players':
386
+ corr_var1_t2 = st.multiselect('Which players would you like to include in the correlation?', options = total_players, key='corr_var1_t2')
387
+
388
+ split_var2_t2 = st.radio("Would you like to view all dates or specific ones?", ('All', 'Specific Dates'), key='split_var3_t2')
389
+
390
+ if split_var2_t2 == 'Specific Dates':
391
+ low_date_t2 = st.date_input('Min Date:', value=None, format="YYYY-MM-DD", key='low_date_t2')
392
+ if low_date_t2 is not None:
393
+ low_date_t2 = pd.to_datetime(low_date_t2).date()
394
+ high_date_t2 = st.date_input('Max Date:', value=None, format="YYYY-MM-DD", key='high_date_t2')
395
+ if high_date_t2 is not None:
396
+ high_date_t2 = pd.to_datetime(high_date_t2).date()
397
+ elif split_var2_t2 == 'All':
398
+ low_date_t2 = gamelog_table['Date'].min()
399
+ high_date_t2 = gamelog_table['Date'].max()
400
+
401
+ spread_var1_t2 = st.slider("Is there a certain spread range you want to view?", 0, 100, (0, 100), key='spread_var1_t2')
402
+
403
+ min_var1_t2 = st.slider("Is there a certain minutes range you want to view?", 0, 60, (0, 60), key='min_var1_t2')
404
+
405
+ with col2:
406
+ working_data = gamelog_table
407
+ if split_var1_t2 == 'Specific Teams':
408
+ display = st.container()
409
+ working_data = working_data.sort_values(by='Fantasy', ascending=False)
410
+ working_data = working_data[working_data['Date'] >= low_date_t2]
411
+ working_data = working_data[working_data['Date'] <= high_date_t2]
412
+ working_data = working_data[working_data['Min'] >= min_var1_t2[0]]
413
+ working_data = working_data[working_data['Min'] <= min_var1_t2[1]]
414
+ working_data = working_data[working_data['spread'] >= spread_var1_t2[0]]
415
+ working_data = working_data[working_data['spread'] <= spread_var1_t2[1]]
416
+ working_data = working_data[working_data['Team'].isin(corr_var1_t2)]
417
+ if corr_var == 'Fantasy':
418
+ corr_display = run_fantasy_corr(working_data)
419
+ elif corr_var == 'Minutes':
420
+ corr_display = run_min_corr(working_data)
421
+ display.dataframe(corr_display.style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').format(precision=2), height=1000, use_container_width = True)
422
+
423
+ elif split_var1_t2 == 'Specific Players':
424
+ display = st.container()
425
+ working_data = working_data.sort_values(by='Fantasy', ascending=False)
426
+ working_data = working_data[working_data['Date'] >= low_date_t2]
427
+ working_data = working_data[working_data['Date'] <= high_date_t2]
428
+ working_data = working_data[working_data['Min'] >= min_var1_t2[0]]
429
+ working_data = working_data[working_data['Min'] <= min_var1_t2[1]]
430
+ working_data = working_data[working_data['spread'] >= spread_var1_t2[0]]
431
+ working_data = working_data[working_data['spread'] <= spread_var1_t2[1]]
432
+ working_data = working_data[working_data['Player'].isin(corr_var1_t2)]
433
+ if corr_var == 'Fantasy':
434
+ corr_display = run_fantasy_corr(working_data)
435
+ elif corr_var == 'Minutes':
436
+ corr_display = run_min_corr(working_data)
437
+ display.dataframe(corr_display.style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').format(precision=2), use_container_width = True)
438
+ st.download_button(
439
+ label="Export Correlations Model",
440
+ data=convert_df_to_csv(corr_display),
441
+ file_name='Correlations_NBA_View.csv',
442
+ mime='text/csv',
443
+ )
444
+
445
+ with tab3:
446
+ st.info(t_stamp)
447
+ col1, col2 = st.columns([1, 9])
448
+ with col1:
449
+ if st.button("Reset Data", key='reset3'):
450
+ st.cache_data.clear()
451
+ gamelog_table, rot_table, game_rot, timestamp = init_baselines()
452
+ basic_cols = ['Player', 'Pos', 'Team', 'Opp', 'Season', 'Date', 'Matchup', 'Min']
453
+ basic_season_cols = ['Pos', 'Team', 'Min']
454
+ data_cols = ['team_score', 'opp_score', 'spread', 'Touches', 'Pts', 'FGM', 'FGA', 'FG%', 'FG3M',
455
+ 'FG3A', 'FG3%', 'FTM', 'FTA', 'FT%', 'OREB Chance', 'OREB', 'DREB Chance', 'DREB', 'REB Chance', 'REB',
456
+ 'Passes', 'Alt Assists', 'FT Assists', 'Assists', 'Stl', 'Blk', 'Tov', 'PF', 'DD', 'TD', 'Fantasy', 'FD_Fantasy',
457
+ 'FPPM', 'Rebound%', 'Assists/Pass', 'Touch_per_min', 'Fantasy/Touch', 'FD Fantasy/Touch']
458
+ season_data_cols = ['Touches', 'Touch/Min', 'Pts', 'FGM', 'FGA', 'FG%', 'FG3M', 'FG3A',
459
+ 'FG3%', 'FTM', 'FTA', 'FT%', 'OREB Chance', 'OREB', 'DREB Chance', 'DREB', 'REB Chance', 'REB',
460
+ 'Passes', 'Alt Assists', 'FT Assists', 'Assists', 'Stl', 'Blk', 'Tov', 'PF', 'DD', 'TD', 'Fantasy', 'FD_Fantasy',
461
+ 'FPPM', 'Rebound%', 'Assists/Pass', 'Fantasy/Touch', 'FD Fantasy/Touch']
462
+ game_rot_cols = ['PLAYER_NAME', 'backlog_lookup', 'spread', 'MIN', 'PTS', 'FGM', 'FGA', 'FG3M', 'FG3A', 'FTM', 'FTA', 'REB', 'AST', 'STL', 'BLK', 'TOV', 'PF',
463
+ 'Fantasy', 'FD_Fantasy']
464
+ indv_teams = gamelog_table.drop_duplicates(subset='Team')
465
+ total_teams = indv_teams.Team.values.tolist()
466
+ indv_rot_teams = rot_table.drop_duplicates(subset='Team')
467
+ total_rot_teams = indv_rot_teams.Team.values.tolist()
468
+ indv_game_rot_teams = game_rot.drop_duplicates(subset='TEAM_ABBREVIATION')
469
+ total_game_rot_teams = indv_game_rot_teams.TEAM_ABBREVIATION.values.tolist()
470
+ indv_players = gamelog_table.drop_duplicates(subset='Player')
471
+ total_players = indv_players.Player.values.tolist()
472
+ total_dates = gamelog_table.Date.values.tolist()
473
+
474
+ team_var3 = st.selectbox('Which opponent would you like to view?', options = total_teams, key='team_var3')
475
+ pos_var3 = st.selectbox('Which position would you like to view?', options = ['PG', 'SG', 'SF', 'PF', 'C'], key='pos_var3')
476
+ disp_var3 = st.radio('Which view would you like to see?', options = ['Fantasy', 'Stats'], key='disp_var3')
477
+ date_var3 = st.radio("Would you like to view all dates or specific ones?", ('All', 'Specific Dates'), key='date_var3')
478
+
479
+ if date_var3 == 'Specific Dates':
480
+ low_date3 = st.date_input('Min Date:', value=None, format="YYYY-MM-DD", key='low_date3')
481
+ if low_date3 is not None:
482
+ low_date3 = pd.to_datetime(low_date3).date()
483
+ high_date3 = st.date_input('Max Date:', value=None, format="YYYY-MM-DD", key='high_date3')
484
+ if high_date3 is not None:
485
+ high_date3 = pd.to_datetime(high_date3).date()
486
+ elif date_var3 == 'All':
487
+ low_date3 = gamelog_table['Date'].min()
488
+ high_date3 = gamelog_table['Date'].max()
489
+
490
+ spread_var3 = st.slider("Is there a certain spread range you want to view?", 0, 100, (0, 100), key='spread_var3')
491
+
492
+ min_var3 = st.slider("Is there a certain minutes range you want to view?", 0, 60, (0, 60), key='min_var3')
493
+
494
+ with col2:
495
+ if disp_var3 == 'Stats':
496
+ choose_cols = st.container()
497
+ with choose_cols:
498
+ choose_disp_matchup = st.multiselect('Which stats would you like to view?', options = data_cols, default = data_cols, key='choose_disp_matchup')
499
+ matchup_disp_stats = basic_cols + choose_disp_matchup
500
+ working_data = gamelog_table
501
+ working_data = working_data[gamelog_table['Date'] >= low_date3]
502
+ working_data = working_data[gamelog_table['Date'] <= high_date3]
503
+ season_long_table = seasonlong_build(working_data)
504
+ fantasy_dict = dict(zip(season_long_table['Player'], season_long_table['Fantasy']))
505
+ fd_fantasy_dict = dict(zip(season_long_table['Player'], season_long_table['FD_Fantasy']))
506
+
507
+ working_data = working_data[working_data['Pos'] == pos_var3]
508
+ working_data = working_data[working_data['Min'] >= min_var3[0]]
509
+ working_data = working_data[working_data['Min'] <= min_var3[1]]
510
+ working_data = working_data[working_data['spread'] >= spread_var3[0]]
511
+ working_data = working_data[working_data['spread'] <= spread_var3[1]]
512
+ working_data = working_data[working_data['Opp'] == team_var3]
513
+ working_data = working_data.reset_index(drop=True)
514
+ if disp_var3 == 'Fantasy':
515
+ gamelog_display = working_data[['Player', 'Pos', 'Team', 'Opp', 'Date', 'Min', 'Fantasy', 'FD_Fantasy']]
516
+ elif disp_var3 == 'Stats':
517
+ gamelog_data = working_data.reindex(matchup_disp_stats,axis="columns")
518
+ gamelog_display = gamelog_data
519
+ gamelog_display['Avg_Fantasy'] = gamelog_display['Player'].map(fantasy_dict)
520
+ gamelog_display['Avg_FD_Fantasy'] = gamelog_display['Player'].map(fd_fantasy_dict)
521
+ display = st.container()
522
+
523
+ # pages = pages.set_index('Player')
524
+ display.dataframe(gamelog_display.style.format(precision=2), height=500, use_container_width=True)
525
+ st.download_button(
526
+ label="Export Matchups Model",
527
+ data=convert_df_to_csv(gamelog_display),
528
+ file_name='Matchups_NBA_View.csv',
529
+ mime='text/csv',
530
+ )
531
+
532
+ with tab4:
533
+ st.info(t_stamp)
534
+ col1, col2 = st.columns([1, 9])
535
+ with col1:
536
+ if st.button("Reset Data", key='reset4'):
537
+ st.cache_data.clear()
538
+ gamelog_table, rot_table, game_rot, timestamp = init_baselines()
539
+ basic_cols = ['Player', 'Pos', 'Team', 'Opp', 'Season', 'Date', 'Matchup', 'Min']
540
+ basic_season_cols = ['Pos', 'Team', 'Min']
541
+ data_cols = ['team_score', 'opp_score', 'spread', 'Touches', 'Pts', 'FGM', 'FGA', 'FG%', 'FG3M',
542
+ 'FG3A', 'FG3%', 'FTM', 'FTA', 'FT%', 'OREB Chance', 'OREB', 'DREB Chance', 'DREB', 'REB Chance', 'REB',
543
+ 'Passes', 'Alt Assists', 'FT Assists', 'Assists', 'Stl', 'Blk', 'Tov', 'PF', 'DD', 'TD', 'Fantasy', 'FD_Fantasy',
544
+ 'FPPM', 'Rebound%', 'Assists/Pass', 'Touch_per_min', 'Fantasy/Touch', 'FD Fantasy/Touch']
545
+ season_data_cols = ['Touches', 'Touch/Min', 'Pts', 'FGM', 'FGA', 'FG%', 'FG3M', 'FG3A',
546
+ 'FG3%', 'FTM', 'FTA', 'FT%', 'OREB Chance', 'OREB', 'DREB Chance', 'DREB', 'REB Chance', 'REB',
547
+ 'Passes', 'Alt Assists', 'FT Assists', 'Assists', 'Stl', 'Blk', 'Tov', 'PF', 'DD', 'TD', 'Fantasy', 'FD_Fantasy',
548
+ 'FPPM', 'Rebound%', 'Assists/Pass', 'Fantasy/Touch', 'FD Fantasy/Touch']
549
+ game_rot_cols = ['PLAYER_NAME', 'backlog_lookup', 'spread', 'MIN', 'PTS', 'FGM', 'FGA', 'FG3M', 'FG3A', 'FTM', 'FTA', 'REB', 'AST', 'STL', 'BLK', 'TOV', 'PF',
550
+ 'Fantasy', 'FD_Fantasy']
551
+ indv_teams = gamelog_table.drop_duplicates(subset='Team')
552
+ total_teams = indv_teams.Team.values.tolist()
553
+ indv_rot_teams = rot_table.drop_duplicates(subset='Team')
554
+ total_rot_teams = indv_rot_teams.Team.values.tolist()
555
+ indv_game_rot_teams = game_rot.drop_duplicates(subset='TEAM_ABBREVIATION')
556
+ total_game_rot_teams = indv_game_rot_teams.TEAM_ABBREVIATION.values.tolist()
557
+ indv_players = gamelog_table.drop_duplicates(subset='Player')
558
+ total_players = indv_players.Player.values.tolist()
559
+ total_dates = gamelog_table.Date.values.tolist()
560
+
561
+ split_var5 = st.radio("Would you like to view all teams or specific ones?", ('All', 'Specific Teams'), key='split_var5')
562
+
563
+ if split_var5 == 'Specific Teams':
564
+ team_var4 = st.multiselect('Which teams would you like to view?', options = total_rot_teams, key='team_var4')
565
+ elif split_var5 == 'All':
566
+ team_var4 = total_rot_teams
567
+
568
+
569
+ with col2:
570
+ working_data = rot_table
571
+ rot_display = working_data[working_data['Team'].isin(team_var4)]
572
+ display = st.container()
573
+
574
+ # rot_display = rot_display.set_index('Player')
575
+ display.dataframe(rot_display.style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').format(percentages_format, precision=2), height=500, use_container_width=True)
576
+ st.download_button(
577
+ label="Export Rotations Model",
578
+ data=convert_df_to_csv(rot_display),
579
+ file_name='Rotations_NBA_View.csv',
580
+ mime='text/csv',
581
+ )
582
+
583
+ with tab5:
584
+ st.info(t_stamp)
585
+ col1, col2 = st.columns([1, 9])
586
+ with col1:
587
+ if st.button("Reset Data", key='reset5'):
588
+ st.cache_data.clear()
589
+ gamelog_table, rot_table, game_rot, timestamp = init_baselines()
590
+ basic_cols = ['Player', 'Pos', 'Team', 'Opp', 'Season', 'Date', 'Matchup', 'Min']
591
+ basic_season_cols = ['Pos', 'Team', 'Min']
592
+ data_cols = ['team_score', 'opp_score', 'spread', 'Touches', 'Pts', 'FGM', 'FGA', 'FG%', 'FG3M',
593
+ 'FG3A', 'FG3%', 'FTM', 'FTA', 'FT%', 'OREB Chance', 'OREB', 'DREB Chance', 'DREB', 'REB Chance', 'REB',
594
+ 'Passes', 'Alt Assists', 'FT Assists', 'Assists', 'Stl', 'Blk', 'Tov', 'PF', 'DD', 'TD', 'Fantasy', 'FD_Fantasy',
595
+ 'FPPM', 'Rebound%', 'Assists/Pass', 'Touch_per_min', 'Fantasy/Touch', 'FD Fantasy/Touch']
596
+ season_data_cols = ['Touches', 'Touch/Min', 'Pts', 'FGM', 'FGA', 'FG%', 'FG3M', 'FG3A',
597
+ 'FG3%', 'FTM', 'FTA', 'FT%', 'OREB Chance', 'OREB', 'DREB Chance', 'DREB', 'REB Chance', 'REB',
598
+ 'Passes', 'Alt Assists', 'FT Assists', 'Assists', 'Stl', 'Blk', 'Tov', 'PF', 'DD', 'TD', 'Fantasy', 'FD_Fantasy',
599
+ 'FPPM', 'Rebound%', 'Assists/Pass', 'Fantasy/Touch', 'FD Fantasy/Touch']
600
+ game_rot_cols = ['PLAYER_NAME', 'backlog_lookup', 'spread', 'MIN', 'PTS', 'FGM', 'FGA', 'FG3M', 'FG3A', 'FTM', 'FTA', 'REB', 'AST', 'STL', 'BLK', 'TOV', 'PF',
601
+ 'Fantasy', 'FD_Fantasy']
602
+ indv_teams = gamelog_table.drop_duplicates(subset='Team')
603
+ total_teams = indv_teams.Team.values.tolist()
604
+ indv_rot_teams = rot_table.drop_duplicates(subset='Team')
605
+ total_rot_teams = indv_rot_teams.Team.values.tolist()
606
+ indv_game_rot_teams = game_rot.drop_duplicates(subset='TEAM_ABBREVIATION')
607
+ total_game_rot_teams = indv_game_rot_teams.TEAM_ABBREVIATION.values.tolist()
608
+ indv_players = gamelog_table.drop_duplicates(subset='Player')
609
+ total_players = indv_players.Player.values.tolist()
610
+ total_dates = gamelog_table.Date.values.tolist()
611
+
612
+ game_rot_view = st.radio("What set would you like to view?", ('Team Rotations', 'Player Rotations'), key='game_rot_view')
613
+
614
+ if game_rot_view == 'Team Rotations':
615
+ game_rot_team = st.selectbox("What team would you like to work with?", options = total_game_rot_teams, key='game_rot_team')
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
+ elif game_rot_view == 'Player Rotations':
634
+ game_rot_team = st.multiselect("What players would you like to work with?", options = total_players, key='game_rot_team')
635
+
636
+ game_rot_spread = st.slider("Is there a certain spread range you want to view?", 0, 100, (0, 100), key='game_rot_spread')
637
+
638
+ game_rot_min = st.slider("Is there a certain minutes range you want to view?", 0, 60, (0, 60), key='game_rot_min')
639
+
640
+ game_rot_dates = st.radio("Would you like to view all dates or specific ones?", ('All', 'Specific Dates'), key='game_rot_dates')
641
+
642
+ if game_rot_dates == 'Specific Dates':
643
+ game_rot_low_date = st.date_input('Min Date:', value=None, format="YYYY-MM-DD", key='game_rot_low_date')
644
+ if game_rot_low_date is not None:
645
+ game_rot_low_date = pd.to_datetime(game_rot_low_date).date()
646
+ game_rot_high_date = st.date_input('Max Date:', value=None, format="YYYY-MM-DD", key='game_rot_high_date')
647
+ if game_rot_high_date is not None:
648
+ game_rot_high_date = pd.to_datetime(game_rot_high_date).date()
649
+ elif game_rot_dates == 'All':
650
+ game_rot_low_date = gamelog_table['Date'].min()
651
+ game_rot_high_date = gamelog_table['Date'].max()
652
+
653
+
654
+ with col2:
655
+ if game_rot_view == 'Player Rotations':
656
+ team_backlog = game_rot[game_rot['PLAYER_NAME'].isin(game_rot_team)]
657
+ team_backlog = team_backlog[pd.to_datetime(team_backlog['GAME_DATE']).dt.date >= game_rot_low_date]
658
+ team_backlog = team_backlog[pd.to_datetime(team_backlog['GAME_DATE']).dt.date <= game_rot_high_date]
659
+ team_backlog = team_backlog[team_backlog['MIN'] >= game_rot_min[0]]
660
+ team_backlog = team_backlog[team_backlog['MIN'] <= game_rot_min[1]]
661
+ team_backlog = team_backlog[team_backlog['spread'] >= game_rot_spread[0]]
662
+ team_backlog = team_backlog[team_backlog['spread'] <= game_rot_spread[1]]
663
+ working_data = game_rot
664
+ display = st.container()
665
+ stats_disp = st.container()
666
+ check_rotation = team_backlog.sort_values(by=['GAME_DATE', 'Finish'], ascending=[False, True])
667
+
668
+ # Ensure Start and Finish are numeric and Task is properly set
669
+ check_rotation['Start'] = pd.to_numeric(check_rotation['Start'], errors='coerce')
670
+ check_rotation['Finish'] = pd.to_numeric(check_rotation['Finish'], errors='coerce')
671
+ check_rotation['delta'] = pd.to_numeric(check_rotation['delta'], errors='coerce')
672
+
673
+ # Create figure
674
+ fig = go.Figure()
675
+
676
+ # Add bars for each shift
677
+ for idx, row in check_rotation.iterrows():
678
+ fig.add_trace(go.Bar(
679
+ x=[row['delta']], # Width of bar
680
+ y=[row['Task']],
681
+ base=row['Start'], # Start position of bar
682
+ orientation='h',
683
+ text=f"{row['delta']:.1f} Minutes",
684
+ textposition='inside',
685
+ showlegend=False,
686
+ marker_color=px.colors.qualitative.Plotly[hash(row['PLAYER_NAME']) % len(px.colors.qualitative.Plotly)]
687
+ ))
688
+
689
+ # Update layout
690
+ fig.update_layout(
691
+ barmode='overlay',
692
+ xaxis=dict(
693
+ range=[0, 48],
694
+ title='Game Time (minutes)'
695
+ ),
696
+ yaxis=dict(
697
+ autorange='reversed'
698
+ )
699
+ )
700
+
701
+ # Add quarter lines
702
+ fig.add_vline(x=12, line_width=3, line_dash="dash", line_color="green")
703
+ fig.add_vline(x=24, line_width=3, line_dash="dash", line_color="green")
704
+ fig.add_vline(x=36, line_width=3, line_dash="dash", line_color="green")
705
+
706
+ game_rot_stats = check_rotation.reindex(game_rot_cols,axis="columns")
707
+ game_rot_stats = game_rot_stats.drop_duplicates(subset='backlog_lookup')
708
+
709
+ # pages = pages.set_index('Player')
710
+ display.plotly_chart(fig, use_container_width=True)
711
+ stats_disp.dataframe(game_rot_stats.style.format(precision=2), hide_index=True, use_container_width = True)
712
+
713
+ elif game_rot_view == 'Team Rotations':
714
+ team_backlog = game_rot[game_rot['TEAM_ABBREVIATION'] == game_rot_team]
715
+ team_backlog = team_backlog[pd.to_datetime(team_backlog['GAME_DATE']).dt.date >= game_rot_low_date]
716
+ team_backlog = team_backlog[pd.to_datetime(team_backlog['GAME_DATE']).dt.date <= game_rot_high_date]
717
+ team_backlog = team_backlog[team_backlog['MIN'] >= game_rot_min[0]]
718
+ team_backlog = team_backlog[team_backlog['MIN'] <= game_rot_min[1]]
719
+ team_backlog = team_backlog[team_backlog['spread'] >= game_rot_spread[0]]
720
+ team_backlog = team_backlog[team_backlog['spread'] <= game_rot_spread[1]]
721
+ game_id_var = st.selectbox("What game would you like to view?", options = team_backlog['backlog_lookup'].unique(), key='game_id_var')
722
+ working_data = game_rot
723
+ display = st.container()
724
+ stats_disp = st.container()
725
+ check_rotation = working_data[working_data['backlog_lookup'] == game_id_var]
726
+ check_rotation = check_rotation.sort_values(by='Start', ascending=True)
727
+ game_rot_stats = check_rotation.reindex(game_rot_cols,axis="columns")
728
+ game_rot_stats = game_rot_stats.drop_duplicates(subset='PLAYER_NAME')
729
+
730
+ # Create figure
731
+ fig = go.Figure()
732
 
733
+ distinct_colors = [
734
+ '#1f77b4', # blue
735
+ '#ff7f0e', # orange
736
+ '#2ca02c', # green
737
+ '#d62728', # red
738
+ '#9467bd', # purple
739
+ '#8c564b', # brown
740
+ '#e377c2', # pink
741
+ '#7f7f7f', # gray
742
+ '#bcbd22', # yellow-green
743
+ '#17becf', # cyan
744
+ '#aec7e8', # light blue
745
+ '#ffbb78', # light orange
746
+ '#98df8a', # light green
747
+ '#ff9896', # light red
748
+ '#c5b0d5' # light purple
749
+ ]
750
+
751
+ # Create a mapping of unique tasks to colors
752
+ unique_tasks = check_rotation['Task'].unique()
753
+ color_map = dict(zip(unique_tasks, distinct_colors[:len(unique_tasks)]))
754
+
755
+ # Add bars for each rotation shift
756
+ for idx, row in check_rotation.iterrows():
757
+ fig.add_trace(go.Bar(
758
+ x=[row['Finish'] - row['Start']], # Width of bar
759
+ y=[row['Task']],
760
+ base=row['Start'], # Start position of bar
761
+ orientation='h',
762
+ text=f"{row['minutes']:.1f} Minutes",
763
+ textposition='inside',
764
+ showlegend=False,
765
+ marker_color=color_map[row['Task']] # Use mapped color for task
766
+ ))
767
+
768
+ # Update layout
769
+ fig.update_layout(
770
+ barmode='overlay',
771
+ xaxis=dict(
772
+ range=[0, 48],
773
+ title='Game Time (minutes)'
774
+ ),
775
+ yaxis=dict(
776
+ autorange='reversed'
777
+ )
778
+ )
779
+
780
+ # Add quarter lines
781
+ fig.add_vline(x=12, line_width=3, line_dash="dash", line_color="green")
782
+ fig.add_vline(x=24, line_width=3, line_dash="dash", line_color="green")
783
+ fig.add_vline(x=36, line_width=3, line_dash="dash", line_color="green")
784
+ # pages = pages.set_index('Player')
785
+ display.plotly_chart(fig, use_container_width=True)
786
+ stats_disp.dataframe(game_rot_stats.style.format(precision=2), hide_index=True, use_container_width = True)