nesticot commited on
Commit
03a3648
·
verified ·
1 Parent(s): 84b1b7d

Delete app.py

Browse files
Files changed (1) hide show
  1. app.py +0 -708
app.py DELETED
@@ -1,708 +0,0 @@
1
- import pandas as pd
2
- import numpy as np
3
- import requests
4
- import math
5
- import matplotlib.pyplot as plt
6
- import seaborn as sns
7
- import matplotlib.patches as patches
8
- import matplotlib.colors as mcolors
9
- import matplotlib
10
- import inflect
11
- infl = inflect.engine()
12
- from matplotlib.offsetbox import (OffsetImage, AnnotationBbox)
13
- from matplotlib.colors import Normalize
14
- from matplotlib.ticker import FuncFormatter
15
- import matplotlib.ticker as mtick
16
- from matplotlib.colors import Normalize
17
- import urllib
18
- import urllib.request
19
- import urllib.error
20
- from urllib.error import HTTPError
21
- import time
22
- from shinywidgets import output_widget, render_widget
23
- import shinyswatch
24
- from shiny import App, Inputs, Outputs, Session, reactive, render, req, ui
25
-
26
- column_list = ['woba_percent',
27
- 'xwoba_percent',
28
- 'barrel_percent',
29
- 'sweet_spot_percent',
30
- 'hard_hit_percent',
31
- 'launch_speed',
32
- 'launch_speed_90',
33
- 'max_launch_speed',
34
- 'k_percent',
35
- 'bb_percent',
36
- 'swing_percent',
37
- 'whiff_rate',
38
- 'zone_swing_percent',
39
- 'zone_contact_percent',
40
- 'chase_percent',
41
- 'chase_contact']
42
- column_list_pitch = ['pitches','bip','xwoba_percent','whiff_rate','chase_percent']
43
-
44
- import joblib
45
-
46
-
47
- loaded_model = joblib.load('joblib_model/barrel_model.joblib')
48
- in_zone_model = joblib.load('joblib_model/in_zone_model_knn_20240410.joblib')
49
-
50
- stat_plot_dict = {'woba_percent':{'name':'wOBA','format':'.3f','flip':False},
51
- 'xwoba_percent':{'name':'xwOBA','format':'.3f','flip':False},
52
- 'woba_percent_contact':{'name':'wOBACON','format':'.3f','flip':False},
53
- 'barrel_percent':{'name':'Barrel%','format':'.1%','flip':False},
54
- 'max_launch_speed':{'name':'Max EV','format':'.1f','flip':False},
55
- 'launch_speed_90':{'name':'90th% EV','format':'.1f','flip':False},
56
- 'launch_speed':{'name':'Avg EV','format':'.1f','flip':False},
57
- 'sweet_spot_percent':{'name':'SwSpot%','format':'.1%','flip':False},
58
- 'hard_hit_percent':{'name':'HardHit%','format':'.1%','flip':False},
59
- 'k_percent':{'name':'K%','format':'.1%','flip':True},
60
- 'bb_percent':{'name':'BB%','format':'.1%','flip':False},
61
- 'zone_contact_percent':{'name':'Z-Contact%','format':'.1%','flip':False},
62
- 'zone_swing_percent':{'name':'Z-Swing%','format':'.1%','flip':False},
63
- 'zone_percent':{'name':'Zone%','format':'.1%','flip':False},
64
- 'chase_percent':{'name':'O-Swing%','format':'.1%','flip':True},
65
- 'chase_contact':{'name':'O-Contact%','format':'.1%','flip':False},
66
- 'swing_percent':{'name':'Swing%','format':'.1%','flip':False},
67
- 'whiff_rate':{'name':'Whiff%','format':'.1%','flip':True},
68
- 'bip':{'name':'Balls in Play','format':'.0f','flip':False},
69
- 'pitches':{'name':'Pitches','format':'.0f','flip':False},}
70
-
71
- stat_plot_dict_rolling = {'woba_percent':{'name':'wOBA','format':'.3f','flip':False,'y':'woba','div':'woba_codes','y_min':0.2,'y_max':0.6,'x_label':'wOBA PA','form':'3f'},
72
- 'xwoba_percent':{'name':'xwOBA','format':'.3f','flip':False,'y':'xwoba','div':'woba_codes','y_min':0.2,'y_max':0.6,'x_label':'xwOBA PA','form':'3f'},
73
- 'k_percent':{'name':'K%','format':'.1%','flip':True,'y':'k','div':'pa','y_min':0.0,'y_max':0.4,'x_label':'PA','form':'1%'},
74
- 'bb_percent':{'name':'BB%','format':'.1%','flip':False,'y':'bb','div':'pa','y_min':0.0,'y_max':0.3,'x_label':'PA','form':'1%'},
75
- 'zone_contact_percent':{'name':'Z-Contact%','format':'.1%','flip':False,'y':'zone_contact','div':'zone_swing','y_min':0.6,'y_max':1.0,'x_label':'In-Zone Swings','form':'1%'},
76
- 'zone_swing_percent':{'name':'Z-Swing%','format':'.1%','flip':False,'y':'zone_swing','div':'in_zone','y_min':0.5,'y_max':1.0,'x_label':'In-Zone Pitches','form':'1%'},
77
- 'zone_percent':{'name':'Zone%','format':'.1%','flip':False,'y':'in_zone','div':'pitches','y_min':0.3,'y_max':0.7,'x_label':'Pitches','form':'1%'},
78
- 'chase_percent':{'name':'O-Swing%','format':'.1%','flip':True,'y':'ozone_swing','div':'out_zone','y_min':0.1,'y_max':0.4,'x_label':'Out-of-Zone Pitches','form':'1%'},
79
- 'chase_contact':{'name':'O-Contact%','format':'.1%','flip':False,'y':'ozone_contact','div':'ozone_swing','y_min':0.4,'y_max':0.8,'x_label':'Out-of-Zone Swings','form':'1%'},
80
- 'swing_percent':{'name':'Swing%','format':'.1%','flip':False,'y':'swings','div':'pitches','y_min':0.3,'y_max':0.7,'x_label':'Pitches','form':'1%'},
81
- 'whiff_rate':{'name':'Whiff%','format':'.1%','flip':True,'y':'whiffs','div':'swings','y_min':0.0,'y_max':0.5,'x_label':'Swings','form':'1%'},}
82
-
83
- cmap_sum = matplotlib.colors.LinearSegmentedColormap.from_list("", ["#0C7BDC","#FFFFFF","#FFB000"])
84
- cmap_sum_r = matplotlib.colors.LinearSegmentedColormap.from_list("", ["#FFB000","#FFFFFF","#0C7BDC",])
85
- cmap_sum.set_bad(color='#C7C7C7', alpha=1.0)
86
- cmap_sum_r.set_bad(color='#C7C7C7', alpha=1.0)
87
-
88
- from batting_update import df_update,df_update_summ_avg,df_update_summ,df_summ_batter_pitch_up,df_summ_changes,df_summ_filter_out
89
-
90
- def percentile(n):
91
- def percentile_(x):
92
- return np.nanpercentile(x, n)
93
- percentile_.__name__ = 'percentile_%s' % n
94
- return percentile_
95
-
96
- print('Reading A')
97
- ### Import Datasets
98
- from datasets import load_dataset
99
- dataset = load_dataset('nesticot/mlb_data', data_files=['mlb_pitch_data_2024.csv' ])
100
- dataset_train = dataset['train']
101
- df_a = dataset_train.to_pandas().set_index(list(dataset_train.features.keys())[0]).reset_index(drop=True)
102
-
103
-
104
- sport_id_input = 1
105
-
106
-
107
- print('Reading A')
108
- df_a_update = df_update(df_a)
109
-
110
-
111
- #df_a_update['batter_id'] = df_a_update['batter_id'].astype(int)
112
- df_a_update['batter_name'] = df_a_update['batter_name'].str.strip(' ')
113
-
114
- df_a_update['bip'] = df_a_update['bip'].replace({'0':False,'False':False,'True':True})
115
-
116
-
117
- choices_woba = [0.696,
118
- 0.726,
119
- 0.883,
120
- 1.244,
121
- 1.569,
122
- 2.004]
123
-
124
- woba_codes = ['strikeout', 'field_out', 'single', 'walk', 'hit_by_pitch',
125
- 'double', 'sac_fly', 'force_out', 'home_run',
126
- 'grounded_into_double_play', 'fielders_choice', 'field_error',
127
- 'triple', 'sac_bunt', 'double_play',
128
- 'fielders_choice_out', 'strikeout_double_play',
129
- 'sac_fly_double_play', 'other_out']
130
-
131
-
132
-
133
- df_a_update['bip_div'] = ~df_a_update.launch_speed.isna()
134
-
135
- # df_dom_update['bip_div'] = ~df_dom_update.launch_speed.isna()
136
- df_a_update['average'] = 'average'
137
- #df_dom_update['average'] = 'average'
138
-
139
- #df_u['is_pitch']
140
-
141
- df_summ_a_update = df_summ_changes(df_update_summ(df_a_update)).set_index(['batter_id','batter_name'])
142
- # df_summ_dom_update = df_summ_changes(df_update_summ(df_dom_update)).set_index(['batter_id','batter_name'])
143
-
144
- df_summ_avg_a_update = df_summ_changes(df_update_summ_avg(df_a_update)).set_index(['average'])
145
- # df_summ_avg_dom_update = df_summ_changes(df_update_summ_avg(df_dom_update)).set_index(['average'])
146
-
147
- stat_roll_dict = dict(zip(stat_plot_dict_rolling.keys(),
148
- [stat_plot_dict_rolling[x]['name'] for x in stat_plot_dict_rolling]))
149
-
150
- df_a_update['batter_id'] = df_a_update['batter_id'].astype(float).astype(int)
151
-
152
- a_player_dict = df_a_update.drop_duplicates(
153
- 'batter_id')[['batter_id','batter_name']].sort_values(by='batter_name').set_index('batter_id').to_dict()['batter_name']
154
- # dom_player_dict = df_summ_dom_update.reset_index().drop_duplicates(
155
- # 'batter_id')[['batter_id','batter_name']].sort_values(by='batter_name').set_index('batter_id').to_dict()['batter_name']
156
-
157
-
158
- import api_scraper
159
- mlb_stats = api_scraper.MLB_Scrape()
160
-
161
- def get_color(value, vmin, vmax, cmap_name=cmap_sum):
162
- # Normalize the value within the range [0, 1]
163
- normalized_value = (value - vmin) / (vmax - vmin)
164
-
165
- # Get the colormap
166
- cmap = plt.get_cmap(cmap_name)
167
-
168
- # Map the normalized value to a color in the colormap
169
- color = cmap(normalized_value)
170
-
171
- # Convert the color from RGBA to hexadecimal format
172
- hex_color = mcolors.rgb2hex(color)
173
-
174
- return hex_color
175
-
176
- def server(input, output, session):
177
- @render.ui
178
- def test():
179
- # @reactive.Effect
180
-
181
-
182
- return ui.input_select("player_id", "Select Batter",a_player_dict,selectize=True)
183
- # if input.my_tabs() == 'LIDOM':
184
- # return ui.input_select("player_id", "Select Batter",dom_player_dict,selectize=True)
185
-
186
-
187
- @output
188
- @render.plot(alt="A Plot")
189
- @reactive.event(input.go, ignore_none=False)
190
- def a_plot():
191
- ### Iniput data for the level
192
- #time.sleep(2)
193
- df_update = df_a_update.copy()
194
- df_summ_update = df_summ_a_update.copy()
195
- df_summ_avg_update = df_summ_avg_a_update.copy()
196
- if len(input.player_id()) < 1:
197
- fig, ax = plt.subplots(1,1,figsize=(10,10))
198
- ax.text(s='Please Select a Batter',x=0.5,y=0.5, ha='center')
199
- ax.axis('off')
200
- return fig
201
-
202
-
203
- batter_select = int(input.player_id())
204
-
205
- df_roll = df_update[df_update['batter_id']==batter_select]
206
- if len(df_roll) == 0:
207
- fig, ax = plt.subplots(1,1,figsize=(10,10))
208
- ax.text(s='Card is Generating',x=0.5,y=0.5, ha='center')
209
- ax.axis('off')
210
- return fig
211
-
212
- df_summ_filter = df_summ_filter_out(df_summ=df_summ_update,batter_select = batter_select)[0]
213
- df_summ_filter_pct = df_summ_filter_out(df_summ=df_summ_update,batter_select = batter_select)[1]
214
- df_summ_player = df_summ_filter_out(df_summ=df_summ_update,batter_select = batter_select)[2]
215
- df_summ_player_pct = df_summ_filter_out(df_summ=df_summ_update,batter_select = batter_select)[3]
216
-
217
- df_summ_batter_pitch = df_summ_batter_pitch_up(df= df_update).set_index(['batter_id','batter_name','pitch_category'])
218
-
219
-
220
- df_summ_batter_pitch_pct = df_summ_batter_pitch.loc[df_summ_filter.index.get_level_values(0)]
221
- df_summ_batter_pitch_pct = df_summ_batter_pitch_pct[df_summ_batter_pitch_pct['pitches']>0]
222
- df_summ_batter_pitch_pct_rank = df_summ_batter_pitch_pct.groupby(level='pitch_category').apply(lambda x: x.rank(pct=True)).xs(batter_select,level=0)
223
-
224
- df_summ_batter_pitch_pct_rank['pitch_count'] = df_summ_batter_pitch_pct_rank.index.get_level_values(1).map(df_summ_batter_pitch.xs(batter_select,level=0).reset_index().set_index('pitch_category')['pitches'].to_dict())
225
- df_summ_batter_pitch_pct_rank = df_summ_batter_pitch_pct_rank.sort_values('pitch_count',ascending=False)
226
- #df_summ_batter_pitch_pct_rank = df_summ_batter_pitch_pct_rank.dropna()
227
-
228
-
229
-
230
- def rolling_plot(stat='k_percent',window_width=100,ax=0,df_r=df_roll,df_r_summ_avg=pd.DataFrame(),stat_plot_dict_rolling=stat_plot_dict_rolling):
231
- plot = sns.lineplot(x=range(window_width,len(df_r[df_r[stat_plot_dict_rolling[stat]['div']]>0])+1),
232
- y=df_r[df_r[stat_plot_dict_rolling[stat]['div']]==1].fillna(0).rolling(window=window_width)[stat_plot_dict_rolling[stat]['y']].sum().dropna()/window_width,
233
- ax=ax,
234
- color="#FFB000",
235
- zorder=10)
236
-
237
-
238
-
239
- # ["#0C7BDC","#FFFFFF","#FFB000"])
240
- ax.set_xlim(window_width,len(df_r[df_r[stat_plot_dict_rolling[stat]['div']]==1]))
241
- ax.set_xlabel(stat_plot_dict_rolling[stat]['x_label'],fontsize=8)
242
- ax.set_ylabel(stat_plot_dict_rolling[stat]['name'],fontsize=8)
243
-
244
- ax.hlines(df_r_summ_avg[stat_plot_dict_rolling[stat]['y']]/df_r_summ_avg[stat_plot_dict_rolling[stat]['div']],
245
- xmin=window_width,
246
- xmax=len(df_r[df_r[stat_plot_dict_rolling[stat]['div']]==1]),
247
- color="#0C7BDC",linestyles='-.')
248
- ax.hlines(sum(df_r[stat_plot_dict_rolling[stat]['y']].dropna())/sum(df_r[stat_plot_dict_rolling[stat]['div']].dropna()),
249
- xmin=window_width,
250
- xmax=len(df_r[df_r[stat_plot_dict_rolling[stat]['div']]==1]),
251
- color="#FFB000",linestyles='--')
252
- #print(sum(df_r[stat_plot_dict_rolling[stat]['y']].dropna())/sum(df_r[stat_plot_dict_rolling[stat]['div']].dropna()))
253
- ax.tick_params(axis='x', labelsize=8) # Set x-axis ticks size
254
- ax.tick_params(axis='y', labelsize=8) # Set y-axis ticks size
255
- ax.set_title(f"{window_width} {stat_plot_dict_rolling[stat]['x_label']} Rolling {stat_plot_dict_rolling[stat]['name']}",fontsize=8)
256
- ax.set_ylim(stat_plot_dict_rolling[stat]['y_min'],stat_plot_dict_rolling[stat]['y_max'])
257
- ax.grid(True,alpha=0.2)
258
-
259
-
260
- if stat_plot_dict_rolling[stat]['form'] == '3f':
261
- ax.yaxis.set_major_formatter(mtick.StrMethodFormatter('{x:.3f}'))
262
-
263
- elif stat_plot_dict_rolling[stat]['form'] == '1f':
264
- ax.yaxis.set_major_formatter(mtick.StrMethodFormatter('{x:.1f}'))
265
-
266
- elif stat_plot_dict_rolling[stat]['form'] == '1%':
267
- ax.yaxis.set_major_formatter(mtick.PercentFormatter(1))
268
-
269
- return plot
270
-
271
- dict_level = {1:'MLB',
272
- 11:'MiLB AAA',
273
- 12:'MiLB AA',
274
- 13:'MiLB High-A',
275
- 14:'MiLB A'}
276
-
277
- def plot_card(sport_id_input=sport_id_input,
278
- batter_select=batter_select,
279
- df_roll=df_roll,
280
- df_summ_player=df_summ_player,
281
- df_summ_update = df_summ_update,
282
- df_summ_batter_pitch_pct=df_summ_batter_pitch_pct,
283
- ):
284
-
285
- #player_df = get_players(sport_id=sport_id_input)
286
- mlb_teams = mlb_stats.get_teams()
287
- team_logos = pd.read_csv('team_logos.csv')
288
- if sport_id_input == 1:
289
- player_bio = requests.get(f'https://statsapi.mlb.com/api/v1/people?personIds={batter_select}&appContext=majorLeague&hydrate=currentTeam').json()
290
- else:
291
- player_bio = requests.get(f'https://statsapi.mlb.com/api/v1/people?personIds={batter_select}&appContext=minorLeague&hydrate=currentTeam').json()
292
-
293
- fig = plt.figure(figsize=(10, 10))#,dpi=600)
294
- plt.rcParams.update({'figure.autolayout': True})
295
- fig.set_facecolor('white')
296
- sns.set_theme(style="whitegrid", palette="pastel")
297
- from matplotlib.gridspec import GridSpec
298
- gs = GridSpec(5, 5, width_ratios=[0.2,1,1,1,0.2], height_ratios=[0.6,0.05,0.15,.30,0.025])
299
- gs.update(hspace=0.4, wspace=0.5)
300
-
301
- # gs.update(left=0.1,right=0.9,top=0.97,bottom=0.03,wspace=0.3,hspace=0.09)
302
-
303
- # ax1 = plt.subplot(4,1,1)
304
- # ax2 = plt.subplot(2,2,2)
305
- # ax3 = plt.subplot(2,2,3)
306
- # ax4 = plt.subplot(4,1,4)
307
- #ax2 = plt.subplot(3,3,2)
308
-
309
- # Add subplots to the grid
310
- ax = fig.add_subplot(gs[0, :])
311
- #ax1 = fig.add_subplot(gs[2, 0])
312
- # ax2 = fig.add_subplot(gs[2, :]) # Subplot at the top-right position
313
- # fig, ax = plt.subplots(1,1,figsize=(10,12))
314
- ax.axis('off')
315
-
316
- width = 0.08
317
- height = width*2.45
318
- if df_summ_player['launch_speed'].isna().values[0]:
319
- df_summ_player['sweet_spot_percent'] = np.nan
320
- df_summ_player['barrel_percent'] = np.nan
321
- df_summ_player['hard_hit_percent'] = np.nan
322
- df_summ_player['xwoba_percent'] = np.nan
323
- if df_summ_player['launch_speed'].isna().values[0]:
324
- df_summ_player_pct['sweet_spot_percent'] = np.nan
325
- df_summ_player_pct['barrel_percent'] = np.nan
326
- df_summ_player_pct['hard_hit_percent'] = np.nan
327
- df_summ_player_pct['xwoba_percent'] = np.nan
328
- # x = 0.1
329
- # y = 0.9
330
- for cat in range(len(column_list)):
331
-
332
- # if cat < len(column_list)/2:
333
- x_adjust, y_adjust =(0.85/7*8)*cat/8+0.075 - (0.85/7*8)*math.floor((cat)/8), 0.45-math.floor((cat)/8)/3.2
334
-
335
- # else:
336
- # x_adjust, y_adjust = (cat-len(column_list)/2)*(1.7/(math.ceil((len(column_list)-1))))+0.1, 0.5
337
- #print( x_adjust, y_adjust)
338
- if sum(df_summ_player[column_list[cat]].isna()) < 1:
339
- print(f'{df_summ_player[column_list[cat]].values[0]:{stat_plot_dict[column_list[cat]]["format"]}}')
340
- ax.text(s = f'{df_summ_player[column_list[cat]].values[0]:{stat_plot_dict[column_list[cat]]["format"]}}'.format().strip(),
341
-
342
- x = x_adjust,
343
- y = y_adjust,
344
- color='black',
345
- #bbox=dict(facecolor='none', edgecolor='black', pad=10.0),
346
- fontsize = 16,
347
- ha='center',
348
- va='center')
349
-
350
- if stat_plot_dict[column_list[cat]]['flip']:
351
-
352
- bbox = patches.Rectangle((x_adjust- width/2,y_adjust- height/2), width, height, linewidth=1,edgecolor='black',
353
- facecolor = get_color(df_summ_player_pct[column_list[cat]].values[0],0,1,cmap_name=cmap_sum_r))
354
- ax.add_patch(bbox)
355
-
356
-
357
- else:
358
- bbox = patches.Rectangle((x_adjust- width/2,y_adjust- height/2), width, height, linewidth=1,edgecolor='black',
359
- facecolor = get_color(df_summ_player_pct[column_list[cat]].values[0],0,1,cmap_name=cmap_sum))
360
- ax.add_patch(bbox)
361
- else:
362
- print(f'{df_summ_player[column_list[cat]].values[0]:{stat_plot_dict[column_list[cat]]["format"]}}')
363
- ax.text(s = f'{df_summ_player[column_list[cat]].fillna("N/A").values[0]}',
364
-
365
- x = x_adjust,
366
- y = y_adjust,
367
- color='black',
368
- #bbox=dict(facecolor='none', edgecolor='black', pad=10.0),
369
- fontsize = 14,
370
- ha='center',
371
- va='center')
372
-
373
- if stat_plot_dict[column_list[cat]]['flip']:
374
-
375
- bbox = patches.Rectangle((x_adjust- width/2,y_adjust- height/2), width, height, linewidth=1,edgecolor='black',
376
- facecolor = get_color(df_summ_player_pct[column_list[cat]].values[0],0,1,cmap_name=cmap_sum_r))
377
- ax.add_patch(bbox)
378
-
379
-
380
- else:
381
- bbox = patches.Rectangle((x_adjust- width/2,y_adjust- height/2), width, height, linewidth=1,edgecolor='black',
382
- facecolor = get_color(df_summ_player_pct[column_list[cat]].values[0],0,1,cmap_name=cmap_sum))
383
- ax.add_patch(bbox)
384
-
385
- ax.text(s = stat_plot_dict[column_list[cat]]['name'],
386
-
387
- x = x_adjust,
388
- y = y_adjust-0.14,
389
- color='black',
390
- #bbox=dict(facecolor='none', edgecolor='black', pad=10.0),
391
- fontsize = 12,
392
- ha='center',
393
- va='center')
394
-
395
- ax.text(s = f"{player_bio['people'][0]['fullName']}",
396
-
397
- x = 0.5,
398
- y = 0.95,
399
- color='black',
400
- #bbox=dict(facecolor='none', edgecolor='black', pad=10.0),
401
- fontsize = 28,
402
- ha='center',
403
- va='center')
404
- if 'parentOrgId' in player_bio['people'][0]['currentTeam']:
405
-
406
- ax.text(s = f"{player_bio['people'][0]['primaryPosition']['abbreviation']}, {mlb_teams[mlb_teams['team_id'] == player_bio['people'][0]['currentTeam']['parentOrgId']]['franchise'].values[0]}",
407
-
408
- x = 0.5,
409
- y = 0.85,
410
- color='black',
411
- #bbox=dict(facecolor='none', edgecolor='black', pad=10.0),
412
- fontsize = 14,
413
- ha='center',
414
- va='center')
415
-
416
- else: ax.text(s = f"{player_bio['people'][0]['primaryPosition']['abbreviation']}, {player_bio['people'][0]['currentTeam']['name']}",
417
-
418
- x = 0.5,
419
- y = 0.85,
420
- color='black',
421
- #bbox=dict(facecolor='none', edgecolor='black', pad=10.0),
422
- fontsize = 14,
423
- ha='center',
424
- va='center')
425
-
426
- ax.text(s =
427
- f"B/T: {player_bio['people'][0]['batSide']['code']}/"
428
- f"{player_bio['people'][0]['pitchHand']['code']} "
429
- f"{player_bio['people'][0]['height']}/"
430
- f"{player_bio['people'][0]['weight']}",
431
-
432
- x = 0.5,
433
- y = 0.785,
434
- color='black',
435
- #bbox=dict(facecolor='none', edgecolor='black', pad=10.0),
436
- fontsize = 14,
437
- ha='center',
438
- va='center')
439
-
440
- ax.text(s =
441
-
442
- f"DOB: {player_bio['people'][0]['birthDate']} "
443
- f"Age: {player_bio['people'][0]['currentAge']}",
444
- x = 0.5,
445
- y = 0.72,
446
- color='black',
447
- #bbox=dict(facecolor='none', edgecolor='black', pad=10.0),
448
- fontsize = 14,
449
- ha='center',
450
- va='center')
451
- if sport_id_input == 1:
452
- try:
453
- url = f'https://img.mlbstatic.com/mlb-photos/image/upload/d_people:generic:headshot:67:current.png/w_213,q_auto:best/v1/people/{batter_select}/headshot/67/current.png'
454
- test_mage = plt.imread(url)
455
- except urllib.error.HTTPError as err:
456
- url = f'https://img.mlbstatic.com/mlb-photos/image/upload/d_people:generic:headshot:67:current.png/w_213,q_auto:best/v1/people/1/headshot/67/current.png'
457
-
458
- else:
459
- try:
460
- url = f'https://img.mlbstatic.com/mlb-photos/image/upload/c_fill,g_auto/w_180/v1/people/{batter_select}/headshot/milb/current.png'
461
- test_mage = plt.imread(url)
462
- except urllib.error.HTTPError as err:
463
- url = f'https://img.mlbstatic.com/mlb-photos/image/upload/d_people:generic:headshot:67:current.png/w_213,q_auto:best/v1/people/1/headshot/67/current.png'
464
- im = plt.imread(url)
465
- # response = requests.get(url)
466
- # im = Image.open(BytesIO(response.content), cmap='viridis')
467
- # im = plt.imread(np.array(PIL.Image.open(urllib.request.urlopen(url))))
468
-
469
- # ax = fig.add_axes([0,0,1,0.85], anchor='C', zorder=1)
470
- imagebox = OffsetImage(im, zoom = 0.3)
471
- ab = AnnotationBbox(imagebox, (0.125, 0.8), frameon = False)
472
- ax.add_artist(ab)
473
-
474
- if 'parentOrgId' in player_bio['people'][0]['currentTeam']:
475
- url = team_logos[team_logos['id'] == player_bio['people'][0]['currentTeam']['parentOrgId']]['imageLink'].values[0]
476
-
477
- im = plt.imread(url)
478
- # response = requests.get(url)
479
- # im = Image.open(BytesIO(response.content))
480
- # im = plt.imread(team_logos[team_logos['id'] == player_bio['people'][0]['currentTeam']['parentOrgId']]['imageLink'].values[0])
481
- # ax = fig.add_axes([0,0,1,0.85], anchor='C', zorder=1)
482
- imagebox = OffsetImage(im, zoom = 0.225)
483
- ab = AnnotationBbox(imagebox, (0.875, 0.8), frameon = False)
484
- ax.add_artist(ab)
485
-
486
- else:
487
- url = team_logos[team_logos['id'] == player_bio['people'][0]['currentTeam']['id']]['imageLink'].values[0]
488
- im = plt.imread(team_logos[team_logos['id'] == player_bio['people'][0]['currentTeam']['id']]['imageLink'].values[0])
489
-
490
- # im = plt.imread(url)
491
- # response = requests.get(url)
492
- # im = Image.open(BytesIO(response.content))
493
- #im = plt.imread(team_logos[team_logos['id'] == player_bio['people'][0]['currentTeam']['parentOrgId']]['imageLink'].values[0])
494
-
495
- # ax = fig.add_axes([0,0,1,0.85], anchor='C', zorder=1)
496
- imagebox = OffsetImage(im, zoom = 0.225)
497
- ab = AnnotationBbox(imagebox, (0.875, 0.8), frameon = False)
498
- ax.add_artist(ab)
499
-
500
- ax.text(s = f'2024 {dict_level[sport_id_input]} Metrics',
501
-
502
- x = 0.5,
503
- y = 0.62,
504
- color='black',
505
- #bbox=dict(facecolor='none', edgecolor='black', pad=10.0),
506
- fontsize = 20,
507
- ha='center',
508
- va='center')
509
-
510
- df_plot = df_summ_batter_pitch[column_list_pitch].xs([batter_select,df_summ_update.xs(batter_select,level=0).index[0]]).sort_values('pitches',ascending=False)#.dropna()
511
- df_plot = df_plot[df_plot['pitches'] > 0]
512
-
513
- df_plot_pct = df_summ_batter_pitch_pct[column_list_pitch].xs([batter_select,df_summ_update.xs(batter_select,level=0).index[0]]).sort_values('pitches',ascending=False)#.dropna()
514
-
515
- value = 1
516
- # Normalize the value
517
- colormap = plt.get_cmap(cmap_sum)
518
- colormap_r = plt.get_cmap(cmap_sum_r)
519
- norm = Normalize(vmin=0, vmax=1)
520
-
521
-
522
-
523
- col_5_colour = [colormap_r(norm(x)) for x in list((df_summ_batter_pitch_pct_rank['chase_percent']))]
524
- col_4_colour = [colormap_r(norm(x)) for x in list((df_summ_batter_pitch_pct_rank['whiff_rate']))]
525
- col_3_colour = [colormap(norm(x)) for x in list((df_summ_batter_pitch_pct_rank['woba_percent_contact']))]
526
- col_2_colour = ['white']*len(df_summ_batter_pitch_pct_rank)
527
- col_1_colour = ['white']*len(df_summ_batter_pitch_pct_rank)
528
- colour_df = pd.DataFrame(data=[col_1_colour,col_2_colour,col_3_colour,col_4_colour,col_5_colour]).T.values
529
-
530
- ax_table = fig.add_subplot(gs[2, 1:-1])
531
- ax_table.axis('off')
532
- print(colour_df)
533
- print(df_plot)
534
- table = ax_table.table(cellText=df_plot.values, colLabels=[stat_plot_dict[x]['name'] for x in df_plot.columns],rowLabels=df_plot.index, cellLoc='center',
535
- bbox=[0.13, 0.0, 0.79, 1],colWidths=[0.1]*len(df_plot.columns),
536
- loc='center',cellColours=colour_df)
537
- ax_table.text(x=0.5,y=1.1,s='Metrics By Pitch Type',ha='center',fontdict={ 'size': 12},fontname='arial')
538
-
539
- w, h = table[0,1].get_width(), table[0,1].get_height()
540
- cell_i = table.add_cell(0, -1, w,h, text='Pitch Type')
541
- cell_i.get_text().set_horizontalalignment('left')
542
- min_font_size = 12
543
- # Set table properties
544
-
545
- table.auto_set_font_size(False)
546
- table.set_fontsize(min_font_size)
547
- #table.set_fontname('arial')
548
- table.scale(1, len(df_plot)*0.3)
549
-
550
-
551
- int_list = ['pitches','bip']
552
- for fl in int_list:
553
- # Subset of column names
554
- subset_columns = [fl]
555
-
556
- # Get the list of column indices
557
- column_indices = [df_plot.columns.get_loc(col) for col in subset_columns]
558
-
559
- # # print(column_indices)
560
- for row_l in range(1,len(df_plot)+1):
561
- # print(row_l)
562
- if table.get_celld()[(row_l,column_indices[0])].get_text().get_text() != '—':
563
- # print()
564
- # print(fl)
565
- table.get_celld()[(row_l,column_indices[0])].get_text().set_text('{:,.0f}'.format(float(table.get_celld()[(row_l,column_indices[0])].get_text().get_text().strip('%'))))
566
-
567
-
568
-
569
- float_3_list = ['xwoba_percent']
570
- for fl in float_3_list:
571
- # Subset of column names
572
- subset_columns = [fl]
573
-
574
- # Get the list of column indices
575
- column_indices = [df_plot.columns.get_loc(col) for col in subset_columns]
576
-
577
- # # print(column_indices)
578
- for row_l in range(1,len(df_plot)+1):
579
- # print(row_l)
580
- if table.get_celld()[(row_l,column_indices[0])].get_text().get_text() != '—':
581
- # print()
582
- # print(fl)
583
- table.get_celld()[(row_l,column_indices[0])].get_text().set_text('{:,.3f}'.format(float(table.get_celld()[(row_l,column_indices[0])].get_text().get_text().strip('%'))))
584
-
585
-
586
-
587
- percent_list = ['whiff_rate','chase_percent']
588
-
589
-
590
- for fl in percent_list:
591
- # Subset of column names
592
- subset_columns = [fl]
593
-
594
- # Get the list of column indices
595
- column_indices = [df_plot.columns.get_loc(col) for col in subset_columns]
596
-
597
- # # print(column_indices)
598
- for row_l in range(1,len(df_plot)+1):
599
- # print(row_l)
600
- if table.get_celld()[(row_l,column_indices[0])].get_text().get_text() != '—':
601
-
602
- # print(fl)
603
- table.get_celld()[(row_l,column_indices[0])].get_text().set_text('{:,.1%}'.format(float(table.get_celld()[(row_l,column_indices[0])].get_text().get_text().strip('%'))))
604
-
605
-
606
-
607
- stat_1 = input.stat_1()
608
- window_width_1 = input.window_1()
609
- stat_2 = input.stat_2()
610
- window_width_2 = input.window_2()
611
- stat_3 = input.stat_3()
612
- window_width_3 = input.window_3()
613
-
614
-
615
- inset_ax = ax = fig.add_subplot(gs[3, 1])
616
- rolling_plot(stat=stat_1,window_width=window_width_1,ax=inset_ax,df_r=df_roll,df_r_summ_avg=df_summ_avg_update)
617
-
618
- inset_ax = ax = fig.add_subplot(gs[3, 2])
619
- rolling_plot(stat=stat_2,window_width=window_width_2,ax=inset_ax,df_r=df_roll,df_r_summ_avg=df_summ_avg_update)
620
-
621
- inset_ax = ax = fig.add_subplot(gs[3, 3])
622
- rolling_plot(stat=stat_3,window_width=window_width_3,ax=inset_ax,df_r=df_roll,df_r_summ_avg=df_summ_avg_update)
623
-
624
- ax_bot = ax = fig.add_subplot(gs[4, :])
625
-
626
- ax_bot.text(x=0.05,y=-0.5,s='By: @TJStats',ha='left',fontdict={ 'size': 14},fontname='arial')
627
- ax_bot.text(x=1-0.05,y=-0.5,s='Data: MLB',ha='right',fontdict={ 'size': 14},fontname='arial')
628
- ax_bot.axis('off')
629
-
630
-
631
- ax_cbar = fig.add_subplot(gs[1,1:-1])
632
-
633
- cb = matplotlib.colorbar.ColorbarBase(ax_cbar, orientation='horizontal',
634
- cmap=cmap_sum)
635
- #ax_cbar.axis('off')
636
- ax_cbar.text(x=0.5,y=1.2,s='Colour Scale - Percentiles',ha='center',fontdict={ 'size': 12},fontname='arial')
637
- ax_cbar.text(s='0%',x=0.01,y=0.5,va='center',ha='left')
638
- ax_cbar.text(s='100%',x=0.99,y=0.5,va='center',ha='right')
639
- # ax_cbar.text(s='50%',x=0.5,y=0.5,va='center',ha='center')
640
- # ax_cbar.text(s='50%',x=0.5,y=0.5,va='center',ha='center')
641
- # ax_cbar.text(s='50%',x=0.5,y=0.5,va='center',ha='center')
642
- ax_cbar.set_xticks([])
643
- ax_cbar.set_yticks([])
644
- ax_cbar.set_xticklabels([])
645
- ax_cbar.set_yticklabels([])
646
-
647
- # Display only the outline of the axis
648
- for spine in ax_cbar.spines.values():
649
- spine.set_visible(True) # Show only the outline
650
- spine.set_color('black') # Set the color to black
651
-
652
- # fig.set_facecolor('#ffffff')
653
-
654
- return fig.subplots_adjust(left=0.03, right=0.97, top=0.95, bottom=0.05)
655
-
656
-
657
- return plot_card(sport_id_input=sport_id_input,
658
- batter_select=batter_select,
659
- df_roll=df_roll,
660
- df_summ_player=df_summ_player,
661
- df_summ_batter_pitch_pct=df_summ_batter_pitch_pct,
662
- )
663
-
664
-
665
-
666
- from shiny import App, Inputs, Outputs, Session, reactive, render, req, ui
667
-
668
-
669
-
670
- app = App(ui.page_fluid(
671
- # ui.tags.base(href=base_url),
672
- ui.tags.div(
673
- {"style": "width:90%;margin: 0 auto;max-width: 1600px;"},
674
- ui.tags.style(
675
- """
676
- h4 {
677
- margin-top: 1em;font-size:35px;
678
- }
679
- h2{
680
- font-size:25px;
681
- }
682
- """
683
- ),
684
- shinyswatch.theme.simplex(),
685
- ui.tags.h4("TJStats"),
686
- ui.tags.i("Baseball Analytics and Visualizations"),
687
- ui.row(
688
- ui.layout_sidebar(
689
-
690
- ui.panel_sidebar(ui.output_ui('test',"Select Batter"),
691
- ui.input_select('stat_1',"Select Rolling Stat 1",stat_roll_dict,selectize=True),
692
- ui.input_numeric('window_1',"Select Rolling Window 1",value=100),
693
- ui.input_select('stat_2',"Select Rolling Stat 2",stat_roll_dict,selected='k_percent',selectize=True),
694
- ui.input_numeric('window_2',"Select Rolling Stat 2",value=100),
695
- ui.input_select('stat_3',"Select Rolling Stat 3",stat_roll_dict,selected='bb_percent',selectize=True),
696
- ui.input_numeric('window_3',"Select Rolling Stat 3",value=100),
697
- ui.input_action_button("go", "Generate",class_="btn-primary"),width=2),
698
-
699
- ui.page_navbar(
700
-
701
- ui.nav_panel("Player Cards",
702
- ui.output_plot('a_plot',width='1000px',height='1000px')),
703
- id="my_tabs",
704
- ))),)),server)
705
-
706
-
707
-
708
- # app = App(app_ui, server)