nesticot commited on
Commit
72ba72d
·
1 Parent(s): 2325624

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +241 -230
app.py CHANGED
@@ -16,6 +16,7 @@ from matplotlib.ticker import MaxNLocator
16
  import matplotlib.font_manager as font_manager
17
  import numpy as np
18
 
 
19
  # team_games_df = pd.read_csv('data/team_games_all.csv',index_col=[0])
20
  # player_games_df = pd.read_csv('data/player_games_cards.csv',index_col=[0]).sort_values(by='date').reset_index(drop=True)
21
  team_abv_nst = pd.read_csv('data/team_abv_nst.csv')
@@ -24,6 +25,7 @@ team_abv_nst = pd.read_csv('data/team_abv_nst.csv')
24
  #team_games_df = team_games_df.merge(right=team_abv,left_on='team',right_on='team_name',how='left').drop(columns='team_name')
25
  team_abv = pd.read_csv('data/team_abv.csv')
26
 
 
27
  import pickle
28
  from datetime import timedelta
29
 
@@ -31,33 +33,42 @@ from datetime import timedelta
31
  # r = requests.get('https://statsapi.web.nhl.com/api/v1/schedule?startDate=2022-10-01&endDate=2023-06-01')
32
  # schedule = r.json()
33
 
34
- schedule = json.loads(urlopen('https://statsapi.web.nhl.com/api/v1/schedule?startDate=2023-10-07&endDate=2024-04-19').read())
35
-
36
- def flatten(t):
37
- return [item for sublist in t for item in sublist]
38
-
39
- game_id = flatten([[x['gamePk'] for x in schedule['dates'][y]['games']] for y in range(0,len(schedule['dates']))])
40
- game_type = flatten([[x['gameType'] for x in schedule['dates'][y]['games']] for y in range(0,len(schedule['dates']))])
41
- game_date = flatten([[(pd.to_datetime(x['gameDate']) - timedelta(hours=8)) for x in schedule['dates'][y]['games']] for y in range(0,len(schedule['dates']))])
42
- game_final = flatten([[x['status']['detailedState'] for x in schedule['dates'][y]['games']] for y in range(0,len(schedule['dates']))])
43
- game_home = flatten([[x['teams']['home']['team']['name'] for x in schedule['dates'][y]['games']] for y in range(0,len(schedule['dates']))])
44
- game_away = flatten([[x['teams']['away']['team']['name'] for x in schedule['dates'][y]['games']] for y in range(0,len(schedule['dates']))])
45
-
46
- schedule_df = pd.DataFrame(data={'game_id': game_id, 'game_type':game_type,'game_date' : game_date, 'game_home' : game_home, 'game_away' : game_away,'status' : game_final})
47
- schedule_df = schedule_df[schedule_df.game_type == 'R'].reset_index(drop=True)
48
- schedule_df = schedule_df[schedule_df.status != 'Postponed']
49
- schedule_df = schedule_df.replace('Montréal Canadiens','Montreal Canadiens')
50
-
51
-
52
-
 
 
 
 
 
 
 
 
 
 
53
  schedule_df_merge = schedule_df.merge(right=team_abv,left_on='game_home',right_on='team_name',how='left')
54
  schedule_df_merge = schedule_df_merge.merge(right=team_abv,left_on='game_away',right_on='team_name',how='left')
55
  schedule_df_merge = schedule_df_merge.drop(columns={'team_name_x','team_name_y'})
56
  schedule_df_merge = schedule_df_merge.rename(columns={'team_abv_x' : 'team_abv_home','team_abv_y' : 'team_abv_away'})
57
 
58
-
59
-
60
-
61
  #schedule_df_merge.game_date = pd.to_datetime(schedule_df_merge['game_date']).dt.tz_convert(tz='US/Eastern').dt.date
62
  # schedule_df_merge = schedule_df_merge.set_index(pd.DatetimeIndex(schedule_df_merge.game_date).strftime('%Y-%m-%d'))
63
  schedule_df_merge.index = pd.to_datetime(schedule_df_merge.game_date)
@@ -67,16 +78,16 @@ schedule_df_merge.index = schedule_df_merge.index.date
67
  schedule_df_merge = schedule_df_merge.sort_index()
68
  schedule_df_merge = schedule_df_merge[schedule_df_merge.index <= date(2024,5,1)]
69
 
70
- schedule_df_merge_final = schedule_df_merge[schedule_df_merge['status']=='Final']
71
  schedule_ccount_df = pd.DataFrame(data={'date':list(schedule_df_merge_final.index)*2,'team':list(schedule_df_merge_final.team_abv_away)+list(schedule_df_merge_final.team_abv_home)}).sort_values(by='date').reset_index(drop=True)
72
  schedule_ccount_df['team_game'] = schedule_ccount_df.groupby('team').cumcount()+1
73
  schedule_ccount_df.date = pd.to_datetime(schedule_ccount_df.date)
74
-
75
  today = pd.to_datetime(datetime.now(pytz.timezone('US/Pacific')).strftime('%Y-%m-%d'))
76
  team_schdule = schedule_df_merge[(schedule_df_merge['team_abv_home']=='EDM')|(schedule_df_merge['team_abv_away']=='EDM')]
77
  team_schdule_live = team_schdule[team_schdule.index <= today]
78
  team_schdule_live.head()
79
-
80
  team_games_df = pd.read_csv('data/team_games_all.csv',index_col=[0])
81
  player_games_df = pd.read_csv('data/player_games_cards.csv',index_col=[0]).sort_values(by='date').reset_index(drop=True)
82
  team_abv_df = pd.read_csv('data/team_abv.csv')
@@ -86,34 +97,38 @@ team_games_df = team_games_df.merge(right=team_abv_df,left_on='team',right_on='t
86
 
87
  player_games_df = player_games_df.drop_duplicates(subset=['player_id','date'],keep='last').reset_index(drop=True)
88
  player_games_df.date = pd.to_datetime(player_games_df.date)
89
- team_games_df = team_games_df[team_games_df['date']=='Final']
90
- schedule_df_merge_final = schedule_df_merge[schedule_df_merge['status']=='Final']
 
 
 
91
  schedule_ccount_df = pd.DataFrame(data={'date':list(schedule_df_merge_final.index)*2,'team':list(schedule_df_merge_final.team_abv_away)+list(schedule_df_merge_final.team_abv_home)}).sort_values(by='date').reset_index(drop=True)
92
  schedule_ccount_df['team_game'] = schedule_ccount_df.groupby('team').cumcount()+1
93
  schedule_ccount_df.date = pd.to_datetime(schedule_ccount_df.date)
94
  team_games_df['team_game'] = team_games_df.groupby('team').cumcount()+1
95
  player_games_df = player_games_df.merge(right=schedule_ccount_df,left_on=['Team','date'],right_on=['team','date'],how='left')
96
  player_games_df['player_game'] = player_games_df.groupby('player_id').cumcount()+1
97
-
98
  date_range_list = pd.date_range(start=player_games_df.date.min()+timedelta(days=6),end=player_games_df.date.max())
99
 
100
-
101
  team_abv_nst_dict = {'All':''} | team_abv_nst.set_index('team_abv')['team_name'].to_dict()
102
 
103
  position_dict = {'All':'','F':'Forwards','D':'Defense'}
104
-
 
105
  player_games_df = player_games_df.rename(columns={'Total Points_pp':'PP Points'})
106
 
107
  stat_input_list = ['TOI', 'Goals', 'Total Assists',
108
  'First Assists', 'Total Points', 'PP Points','Shots', 'Hits',
109
  'Shots Blocked']
110
-
111
 
112
  df_cum_stat_total = player_games_df.groupby(['player_id','Player','Position']).agg(
113
  GP = ('GP','count'),
114
- Total_Points = ('Total Points','sum')
115
  ).reset_index()
116
 
 
117
  df_all_sort = df_cum_stat_total.copy()
118
  stat_pick = 'Total_Points'
119
  count=11
@@ -169,7 +184,7 @@ import matplotlib.image as mpimg
169
  app_ui = ui.page_fluid(
170
  #shinyswatch.theme.cosmo(),
171
  ui.layout_sidebar(
172
-
173
  # Available themes:
174
  # cerulean, cosmo, cyborg, darkly, flatly, journal, litera, lumen, lux,
175
  # materia, minty, morph, pulse, quartz, sandstone, simplex, sketchy, slate,
@@ -204,35 +219,35 @@ app_ui = ui.page_fluid(
204
  # ui.input_date("x", "Date input"),),
205
  # ui.column(
206
  # 1,
207
- # ui.input_select("level_id", "Select Level",level_dict,width=1)),
208
- # ui.column(
209
- # 3,
210
- # ui.input_select("stat_id", "Select Stat",plot_dict_small,width=1)),
211
- # ui.column(
212
- # 2,
213
- # ui.input_numeric("n", "Rolling Window Size", value=50)),
214
- # ),
215
- # ui.output_table("result_batters")),
216
-
217
- # ui.nav(
218
- # "Pitchers",
219
-
220
- # ui.row(
221
- # ui.column(
222
- # 3,
223
- # ui.input_select("id_pitch", "Select Pitcher",pitcher_dict,width=1,selected=675911),
224
- # ),
225
- # ui.column(
226
- # 1,
227
- # ui.input_select("level_id_pitch", "Select Level",level_dict,width=1)),
228
- # ui.column(
229
- # 3,
230
- # ui.input_select("stat_id_pitch", "Select Stat",plot_dict_small_pitch,width=1)),
231
- # ui.column(
232
- # 2,
233
- # ui.input_numeric("n_pitch", "Rolling Window Size", value=50)),
234
- # ),
235
- # ui.output_table("result_pitchers")),
236
  # )
237
  # )
238
  # )
@@ -246,29 +261,28 @@ app_ui = ui.page_fluid(
246
 
247
 
248
 
249
-
250
  def server(input, output, session):
251
 
252
 
253
  @reactive.Effect
254
  def _():
255
-
256
 
 
257
  team_select_list = [input.team_select()]
258
  position_select_list = [input.position_select()]
259
-
260
  if team_select_list[0] == 'All':
261
  team_select_list = team_abv_nst.team_abv.unique()
262
-
263
  if position_select_list[0] == 'All':
264
  position_select_list = player_games_df.Position.unique()
265
-
266
  elif position_select_list[0] == 'F':
267
  position_select_list = player_games_df[player_games_df.Position != 'D'].Position.unique()
268
 
269
  else:
270
  position_select_list = ['D']
271
-
272
  print(team_select_list)
273
 
274
 
@@ -289,7 +303,7 @@ def server(input, output, session):
289
  GP = ('GP','count'),
290
  Total_Points = (f'{input.stat()}','sum')
291
  ).reset_index()
292
-
293
  df_all_sort = df_cum_stat_total.copy()
294
  stat_pick = 'Total_Points'
295
  count=6
@@ -307,195 +321,192 @@ def server(input, output, session):
307
  temp_df['temp'] = temp_df[stat_pick+' per game Rank'].rank()#.sort_values(ascending=True)#.reset_index(drop=True)
308
  temp_df = temp_df.sort_values(by='temp',ascending=True)#.reset_index(drop=True)
309
  temp = temp_df[temp_df['temp']<=(count-len(df_all_sort_list))]
310
-
311
  players_list_new = list(pd.concat([df_all_sort_list,temp]).reset_index(drop=True)['player_id'])
312
-
313
-
314
  skater_dict = df_cum_stat_total.sort_values(by=['Total_Points','GP'],ascending=[False,True]).drop_duplicates(subset='player_id').set_index('player_id')#.sort_values(by='Player')
315
  #skater_dict['skater_team'] = skater_dict.Player + ' - ' + skater_dict.Team
316
  skater_dict = skater_dict['Player'].to_dict()
317
  # players_list = list(df_all_sort['Player'])
318
-
319
  ui.update_select(
320
  "id",
321
  label="Select Skater (max. 10 Skaters)",
322
  choices=skater_dict,
323
  selected=list(players_list_new[0:10]))
324
-
325
-
326
- @output
327
- @render.table
328
- def result():
329
- if input.rookie_switch():
330
-
331
- return player_games_df[(player_games_df.date <= pd.to_datetime(input.date()))&(player_games_df.player_id.isin(rookie_list))].groupby(['player_id','Player','Position']).agg(
332
- GP = ('GP','count'),
333
- Stat = (f'{input.stat()}','sum')
334
- ).reset_index().sort_values(by=['Stat','GP'],ascending=[False,True]).reset_index(drop=True)
335
-
336
- else:
337
- return player_games_df[player_games_df.date <= pd.to_datetime(input.date())].groupby(['player_id','Player','Position']).agg(
338
- GP = ('GP','count'),
339
- Stat = (f'{input.stat()}','sum')
340
- ).reset_index().sort_values(by=['Stat','GP'],ascending=[False,True]).reset_index(drop=True)
341
-
342
-
343
- @output
344
- @render.plot(alt="A histogram")
345
- def plot():
346
-
347
-
348
- team_select_list = [input.team_select()]
349
- position_select_list = [input.position_select()]
350
-
351
-
352
-
353
- if team_select_list[0] == 'All':
354
- team_select_title = 'NHL '
355
- else:
356
- team_select_title = f'{team_abv_nst_dict[team_select_list[0]]} '
357
-
358
 
359
- if position_select_list[0] == 'All':
360
- position_select_title = ''
 
 
 
361
 
362
- elif position_select_list[0] == 'F':
363
- position_select_title = 'Forwards '
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
364
 
365
- else:
366
- position_select_title = 'Defense '
 
367
 
368
- rookie = ''
369
- if input.rookie_switch():
370
- rookie = 'Rookie '
371
-
372
- i = 0
373
- #rookie = ''
374
- current_season = '2023'
375
- start_season = '2024'
376
 
377
- # player_lookup_list = ['Connor McDavid','David Pastrnak','Nathan MacKinnon']
 
 
 
 
 
 
 
 
378
 
 
 
379
 
380
- type(input.id())
381
- print(input.id())
382
- player_lookup_list = list(input.id())[0:10]
 
383
 
 
 
 
 
 
 
 
384
  stat = input.stat()
385
- sns.set_theme(style="whitegrid", palette="pastel")
386
- #print(type([input.date()))
387
- date_range_list = [pd.to_datetime(input.date())]
388
- for k in range(len(date_range_list)):
389
- print(date_range_list[k])
390
- stat = input.stat()
391
- team_schedule_url_merge = []
392
- max_games_player = []
393
- max_games_team = []
394
- max_stat = []
395
- per_game = False
396
- for i in range(0,len(player_lookup_list)):
397
- team_schedule_url_merge.append(player_games_df[(player_games_df.player_id == int(player_lookup_list[i]))&(date_range_list[k] >= player_games_df.date)].reset_index(drop=True))
398
- #print('touble',i, player_lookup_list[i],len(player_games_df[(player_games_df.player_id == player_lookup_list[i])]))
399
- team_schedule_url_merge[i].index = team_schedule_url_merge[i].team_game
400
- team_schedule_url_merge[i] = team_schedule_url_merge[i].reindex(np.arange(team_schedule_url_merge[i].team_game.min(), team_schedule_url_merge[i].team_game.max() + 1)).reset_index(drop=True)
401
- #team_schedule_url_merge[0]['team_game'] = team_schedule_url_merge[0]['index']
402
- #team_schedule_url_merge[0]['player_game'] =
403
- #schedule_ccount_df[schedule_ccount_df['team'].isin(team_schedule_url_merge[0].Team.unique())].merge(right=team_schedule_url_merge[0],left_on=['date','team'],right_on=['date','Team'],how='left')
404
-
405
- team_schedule_url_merge[i]['stat'] = team_schedule_url_merge[i][stat].cumsum()
406
-
407
-
408
- #team_schedule_url_merge[i]['stat'] = team_schedule_url_merge[i][stat_pick]
409
- team_schedule_url_merge[i] = team_schedule_url_merge[i].append(team_schedule_url_merge[i]).sort_index()
410
- team_schedule_url_merge[i] = team_schedule_url_merge[i].append(team_schedule_url_merge[i].iloc[0]).sort_index().reset_index(drop=True)
411
-
412
- team_schedule_url_merge[i]['team_game'][0] = 0
413
- team_schedule_url_merge[i]['player_game'][0] = 0
414
- team_schedule_url_merge[i]['stat'][0] = 0
415
-
416
- for j in range(1,len(team_schedule_url_merge[i]),2):
417
- team_schedule_url_merge[i]['player_game'][j] = team_schedule_url_merge[i]['player_game'][j]-1
418
- team_schedule_url_merge[i]['team_game'][j] = team_schedule_url_merge[i]['team_game'][j]-1
419
- team_schedule_url_merge[i]['stat'][j] = team_schedule_url_merge[i]['stat'][j] - team_schedule_url_merge[i][stat][j]
420
-
421
- if len(team_schedule_url_merge[i]) >3:
422
- if pd.isna(team_schedule_url_merge[i].iloc[3]['player_game']) and pd.isna(team_schedule_url_merge[i].iloc[1]['player_game']) == True:
423
- team_schedule_url_merge[i]['player_game'][2] = np.nan
424
- team_schedule_url_merge[i]['stat'][2] = np.nan
425
-
426
- if len(team_schedule_url_merge[i]) >3:
427
- if pd.isna(team_schedule_url_merge[i].iloc[len(team_schedule_url_merge[i])-1]['player_game']) == True:
428
- team_schedule_url_merge[i]['stat'][len(team_schedule_url_merge[i])-1] = np.nanmax(team_schedule_url_merge[i]['stat'])
429
-
430
- if not (team_schedule_url_merge[i]['team_game'].values[1] == team_schedule_url_merge[i]['player_game'].values[0]):
431
- team_schedule_url_merge[i].loc[0,'team_game'] = np.nan
432
-
433
-
434
- max_games_player.append(np.around(np.nanmax(team_schedule_url_merge[i]['player_game'])))
435
- max_games_team.append(np.around(np.nanmax(team_schedule_url_merge[i]['team_game'])))
436
- max_stat.append((np.around(np.nanmax(team_schedule_url_merge[i]['stat']))))
437
-
438
-
439
-
440
-
441
-
442
-
443
- fig, ax = plt.subplots(figsize=(15,15))
444
- cgfont = {'fontname':'Century Gothic'}
445
- font = font_manager.FontProperties(family='Century Gothic',
446
- style='normal', size=18)
447
-
448
-
449
- ax.axhline(0,color='black',linestyle ="--",linewidth=2,alpha=1.0,label='Missed Games')
450
- ax.axhline(0,color='black',linestyle ="-",linewidth=2,alpha=1.0)
451
-
452
-
453
- if 'Total' in stat:
454
- stat = stat.replace('Total ',"")
455
-
456
-
457
- colour_scheme = ['#648FFF','#785EF0','#DC267F','#FE6100','#FFB000','#FAEF3B','#861318','#2ED3BC','#341BBF','#B37E2C']
458
-
459
- for i in range(len(team_schedule_url_merge)):
460
- sns.lineplot(team_schedule_url_merge[i].reset_index()['team_game'],team_schedule_url_merge[i].reset_index()['stat'],linewidth=3-i*.2,color=colour_scheme[i])
461
- plt.plot(team_schedule_url_merge[i]['team_game'],team_schedule_url_merge[i]['stat'],color=ax.lines[i*2+2].get_color(),label=str(i+1)+'. '+team_schedule_url_merge[i]['Player'][0]+', '+str(int(max_stat[i]))+' '+stat+' in '+str(int(max(team_schedule_url_merge[i]['player_game'])))+' Games',linewidth=6)
462
- ax.lines[i*2+2].set_linestyle("--")
463
-
464
 
 
 
465
 
466
- fig.set_facecolor('#ffffff')
467
- ax.set(xlim=(0,max([team_schedule_url_merge[x].team_game.max() for x in range(len(team_schedule_url_merge))])))
468
- ax.set(ylim=(0,max([team_schedule_url_merge[x].stat.max() for x in range(len(team_schedule_url_merge))])))
469
 
470
- ax.legend_.remove()
 
 
 
471
 
 
 
 
472
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
473
 
474
- if per_game == False:
475
- fig.suptitle(f'{rookie}{team_select_title}{position_select_title}{stat} Race',y=.98,fontsize=32,color='black',**cgfont)
476
- ax.set_ylabel(stat,fontsize=20,color='black',**cgfont)
477
- # else:
478
- # fig.suptitle(stat+' Per Game, All Situations',y=.99,fontsize=48,color='black',**cgfont)
479
- # ax.set_ylabel(stat+"/GP",fontsize=20,color='black',**cgfont)
480
 
 
 
481
 
 
 
482
 
483
- ax.set_title(str(current_season)[0:4]+'-'+str(start_season)[-4:]+' Season',y=1.01,fontsize=18,color='black',**cgfont,x=0,ha='left')
484
- ax.set_xlabel('Team Game',fontsize=20,color='black',**cgfont)
485
- ax.tick_params(axis="x", labelsize=24,colors='black')
486
- ax.set_facecolor('#ffffff')
487
- ax.xaxis.set_major_locator(MaxNLocator(integer=True))
488
- ax.tick_params(axis="y", labelsize=24,colors='black')
489
- ax.yaxis.set_major_locator(MaxNLocator(integer=True))
490
 
491
- fig.text(x=0.025,y=0.01,s="Created By: @TJStats",color='black', fontsize=20, horizontalalignment='left',**cgfont)
492
- fig.text(x=0.975,y=0.01,s="Data: Natural Stat Trick",color='black', fontsize=20, horizontalalignment='right',**cgfont)
493
- fig.text(x=.975,y=0.92,s='Date: '+input.date().strftime('%B %d, %Y'),color='black', fontsize=18, horizontalalignment='right',**cgfont)
494
 
495
- ax.legend(prop=font,bbox_to_anchor=(0.01, 0.99),loc='upper left',framealpha=1,frameon=True)
496
- plt.tight_layout()
497
- #fig.savefig('gif_race/'+stat+rookie+str(date_range_list[k].date())+'.png', facecolor=fig.get_facecolor(), edgecolor='none',bbox_inches='tight',dpi=100)
498
- #plt.close()
499
- #fig.legend(prop=font,loc='best',framealpha=1,frameon=True)
500
 
501
- app = App(app_ui, server)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16
  import matplotlib.font_manager as font_manager
17
  import numpy as np
18
 
19
+
20
  # team_games_df = pd.read_csv('data/team_games_all.csv',index_col=[0])
21
  # player_games_df = pd.read_csv('data/player_games_cards.csv',index_col=[0]).sort_values(by='date').reset_index(drop=True)
22
  team_abv_nst = pd.read_csv('data/team_abv_nst.csv')
 
25
  #team_games_df = team_games_df.merge(right=team_abv,left_on='team',right_on='team_name',how='left').drop(columns='team_name')
26
  team_abv = pd.read_csv('data/team_abv.csv')
27
 
28
+
29
  import pickle
30
  from datetime import timedelta
31
 
 
33
  # r = requests.get('https://statsapi.web.nhl.com/api/v1/schedule?startDate=2022-10-01&endDate=2023-06-01')
34
  # schedule = r.json()
35
 
36
+ # schedule = json.loads(urlopen('https://statsapi.web.nhl.com/api/v1/schedule?startDate=2023-10-07&endDate=2024-04-19').read())
37
+
38
+ # def flatten(t):
39
+ # return [item for sublist in t for item in sublist]
40
+
41
+ # game_id = flatten([[x['gamePk'] for x in schedule['dates'][y]['games']] for y in range(0,len(schedule['dates']))])
42
+ # game_type = flatten([[x['gameType'] for x in schedule['dates'][y]['games']] for y in range(0,len(schedule['dates']))])
43
+ # game_date = flatten([[(pd.to_datetime(x['gameDate']) - timedelta(hours=8)) for x in schedule['dates'][y]['games']] for y in range(0,len(schedule['dates']))])
44
+ # game_final = flatten([[x['status']['detailedState'] for x in schedule['dates'][y]['games']] for y in range(0,len(schedule['dates']))])
45
+ # game_home = flatten([[x['teams']['home']['team']['name'] for x in schedule['dates'][y]['games']] for y in range(0,len(schedule['dates']))])
46
+ # game_away = flatten([[x['teams']['away']['team']['name'] for x in schedule['dates'][y]['games']] for y in range(0,len(schedule['dates']))])
47
+
48
+ # schedule_df = pd.DataFrame(data={'game_id': game_id, 'game_type':game_type,'game_date' : game_date, 'game_home' : game_home, 'game_away' : game_away,'status' : game_final})
49
+ # schedule_df = schedule_df[schedule_df.game_type == 'R'].reset_index(drop=True)
50
+ # schedule_df = schedule_df[schedule_df.status != 'Postponed']
51
+ # schedule_df = schedule_df.replace('Montréal Canadiens','Montreal Canadiens')
52
+ schedule = pd.read_csv('2024_schedule_href.csv')
53
+ #schedule = pd.read_html('https://www.hockey-reference.com/leagues/NHL_2024_games.html')[0]
54
+ #schedule.to_csv('schedule/schedule_'+str(date.today())+'.csv')
55
+ #schedule = pd.read_csv('schedule/schedule_'+str(date.today())+'.csv')
56
+ schedule = schedule.replace('St Louis Blues','St. Louis Blues')
57
+
58
+
59
+ schedule_df = schedule.merge(right=team_abv,left_on='Visitor',right_on='team_name',how='inner',suffixes=['','_away'])
60
+ schedule_df = schedule_df.merge(right=team_abv,left_on='Home',right_on='team_name',how='inner',suffixes=['','_home'])
61
+
62
+ schedule_df = schedule_df.rename(columns={'Visitor':'game_away','Home':'game_home','Date':'game_date'})
63
+
64
+
65
  schedule_df_merge = schedule_df.merge(right=team_abv,left_on='game_home',right_on='team_name',how='left')
66
  schedule_df_merge = schedule_df_merge.merge(right=team_abv,left_on='game_away',right_on='team_name',how='left')
67
  schedule_df_merge = schedule_df_merge.drop(columns={'team_name_x','team_name_y'})
68
  schedule_df_merge = schedule_df_merge.rename(columns={'team_abv_x' : 'team_abv_home','team_abv_y' : 'team_abv_away'})
69
 
70
+
71
+ schedule_df_merge = schedule_df_merge.loc[:,~schedule_df_merge.columns.duplicated()].copy()
 
72
  #schedule_df_merge.game_date = pd.to_datetime(schedule_df_merge['game_date']).dt.tz_convert(tz='US/Eastern').dt.date
73
  # schedule_df_merge = schedule_df_merge.set_index(pd.DatetimeIndex(schedule_df_merge.game_date).strftime('%Y-%m-%d'))
74
  schedule_df_merge.index = pd.to_datetime(schedule_df_merge.game_date)
 
78
  schedule_df_merge = schedule_df_merge.sort_index()
79
  schedule_df_merge = schedule_df_merge[schedule_df_merge.index <= date(2024,5,1)]
80
 
81
+ schedule_df_merge_final = schedule_df_merge[schedule_df_merge.index<date.today()]
82
  schedule_ccount_df = pd.DataFrame(data={'date':list(schedule_df_merge_final.index)*2,'team':list(schedule_df_merge_final.team_abv_away)+list(schedule_df_merge_final.team_abv_home)}).sort_values(by='date').reset_index(drop=True)
83
  schedule_ccount_df['team_game'] = schedule_ccount_df.groupby('team').cumcount()+1
84
  schedule_ccount_df.date = pd.to_datetime(schedule_ccount_df.date)
85
+
86
  today = pd.to_datetime(datetime.now(pytz.timezone('US/Pacific')).strftime('%Y-%m-%d'))
87
  team_schdule = schedule_df_merge[(schedule_df_merge['team_abv_home']=='EDM')|(schedule_df_merge['team_abv_away']=='EDM')]
88
  team_schdule_live = team_schdule[team_schdule.index <= today]
89
  team_schdule_live.head()
90
+
91
  team_games_df = pd.read_csv('data/team_games_all.csv',index_col=[0])
92
  player_games_df = pd.read_csv('data/player_games_cards.csv',index_col=[0]).sort_values(by='date').reset_index(drop=True)
93
  team_abv_df = pd.read_csv('data/team_abv.csv')
 
97
 
98
  player_games_df = player_games_df.drop_duplicates(subset=['player_id','date'],keep='last').reset_index(drop=True)
99
  player_games_df.date = pd.to_datetime(player_games_df.date)
100
+
101
+ team_games_df['date'] = pd.to_datetime(team_games_df['date']).dt.date
102
+ team_games_df = team_games_df[team_games_df['date']<date.today()]
103
+
104
+ #schedule_df_merge_final = schedule_df_merge[schedule_df_merge['status']=='Final']
105
  schedule_ccount_df = pd.DataFrame(data={'date':list(schedule_df_merge_final.index)*2,'team':list(schedule_df_merge_final.team_abv_away)+list(schedule_df_merge_final.team_abv_home)}).sort_values(by='date').reset_index(drop=True)
106
  schedule_ccount_df['team_game'] = schedule_ccount_df.groupby('team').cumcount()+1
107
  schedule_ccount_df.date = pd.to_datetime(schedule_ccount_df.date)
108
  team_games_df['team_game'] = team_games_df.groupby('team').cumcount()+1
109
  player_games_df = player_games_df.merge(right=schedule_ccount_df,left_on=['Team','date'],right_on=['team','date'],how='left')
110
  player_games_df['player_game'] = player_games_df.groupby('player_id').cumcount()+1
111
+
112
  date_range_list = pd.date_range(start=player_games_df.date.min()+timedelta(days=6),end=player_games_df.date.max())
113
 
 
114
  team_abv_nst_dict = {'All':''} | team_abv_nst.set_index('team_abv')['team_name'].to_dict()
115
 
116
  position_dict = {'All':'','F':'Forwards','D':'Defense'}
117
+
118
+ player_games_df.player_id = player_games_df.player_id.astype(int)
119
  player_games_df = player_games_df.rename(columns={'Total Points_pp':'PP Points'})
120
 
121
  stat_input_list = ['TOI', 'Goals', 'Total Assists',
122
  'First Assists', 'Total Points', 'PP Points','Shots', 'Hits',
123
  'Shots Blocked']
124
+
125
 
126
  df_cum_stat_total = player_games_df.groupby(['player_id','Player','Position']).agg(
127
  GP = ('GP','count'),
128
+ Total_Points = ('Total Points','sum')
129
  ).reset_index()
130
 
131
+
132
  df_all_sort = df_cum_stat_total.copy()
133
  stat_pick = 'Total_Points'
134
  count=11
 
184
  app_ui = ui.page_fluid(
185
  #shinyswatch.theme.cosmo(),
186
  ui.layout_sidebar(
187
+
188
  # Available themes:
189
  # cerulean, cosmo, cyborg, darkly, flatly, journal, litera, lumen, lux,
190
  # materia, minty, morph, pulse, quartz, sandstone, simplex, sketchy, slate,
 
219
  # ui.input_date("x", "Date input"),),
220
  # ui.column(
221
  # 1,
222
+ # ui.input_select("level_id", "Select Level",level_dict,width=1)),
223
+ # ui.column(
224
+ # 3,
225
+ # ui.input_select("stat_id", "Select Stat",plot_dict_small,width=1)),
226
+ # ui.column(
227
+ # 2,
228
+ # ui.input_numeric("n", "Rolling Window Size", value=50)),
229
+ # ),
230
+ # ui.output_table("result_batters")),
231
+
232
+ # ui.nav(
233
+ # "Pitchers",
234
+
235
+ # ui.row(
236
+ # ui.column(
237
+ # 3,
238
+ # ui.input_select("id_pitch", "Select Pitcher",pitcher_dict,width=1,selected=675911),
239
+ # ),
240
+ # ui.column(
241
+ # 1,
242
+ # ui.input_select("level_id_pitch", "Select Level",level_dict,width=1)),
243
+ # ui.column(
244
+ # 3,
245
+ # ui.input_select("stat_id_pitch", "Select Stat",plot_dict_small_pitch,width=1)),
246
+ # ui.column(
247
+ # 2,
248
+ # ui.input_numeric("n_pitch", "Rolling Window Size", value=50)),
249
+ # ),
250
+ # ui.output_table("result_pitchers")),
251
  # )
252
  # )
253
  # )
 
261
 
262
 
263
 
 
264
  def server(input, output, session):
265
 
266
 
267
  @reactive.Effect
268
  def _():
 
269
 
270
+
271
  team_select_list = [input.team_select()]
272
  position_select_list = [input.position_select()]
273
+
274
  if team_select_list[0] == 'All':
275
  team_select_list = team_abv_nst.team_abv.unique()
276
+
277
  if position_select_list[0] == 'All':
278
  position_select_list = player_games_df.Position.unique()
279
+
280
  elif position_select_list[0] == 'F':
281
  position_select_list = player_games_df[player_games_df.Position != 'D'].Position.unique()
282
 
283
  else:
284
  position_select_list = ['D']
285
+
286
  print(team_select_list)
287
 
288
 
 
303
  GP = ('GP','count'),
304
  Total_Points = (f'{input.stat()}','sum')
305
  ).reset_index()
306
+
307
  df_all_sort = df_cum_stat_total.copy()
308
  stat_pick = 'Total_Points'
309
  count=6
 
321
  temp_df['temp'] = temp_df[stat_pick+' per game Rank'].rank()#.sort_values(ascending=True)#.reset_index(drop=True)
322
  temp_df = temp_df.sort_values(by='temp',ascending=True)#.reset_index(drop=True)
323
  temp = temp_df[temp_df['temp']<=(count-len(df_all_sort_list))]
324
+
325
  players_list_new = list(pd.concat([df_all_sort_list,temp]).reset_index(drop=True)['player_id'])
326
+
327
+
328
  skater_dict = df_cum_stat_total.sort_values(by=['Total_Points','GP'],ascending=[False,True]).drop_duplicates(subset='player_id').set_index('player_id')#.sort_values(by='Player')
329
  #skater_dict['skater_team'] = skater_dict.Player + ' - ' + skater_dict.Team
330
  skater_dict = skater_dict['Player'].to_dict()
331
  # players_list = list(df_all_sort['Player'])
332
+
333
  ui.update_select(
334
  "id",
335
  label="Select Skater (max. 10 Skaters)",
336
  choices=skater_dict,
337
  selected=list(players_list_new[0:10]))
338
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
339
 
340
+
341
+ @output
342
+ @render.table
343
+ def result():
344
+ if input.rookie_switch():
345
 
346
+ return player_games_df[(player_games_df.date <= pd.to_datetime(input.date()))&(player_games_df.player_id.isin(rookie_list))].groupby(['player_id','Player','Position']).agg(
347
+ GP = ('GP','count'),
348
+ Stat = (f'{input.stat()}','sum')
349
+ ).reset_index().sort_values(by=['Stat','GP'],ascending=[False,True]).reset_index(drop=True)
350
+
351
+ else:
352
+ return player_games_df[player_games_df.date <= pd.to_datetime(input.date())].groupby(['player_id','Player','Position']).agg(
353
+ GP = ('GP','count'),
354
+ Stat = (f'{input.stat()}','sum')
355
+ ).reset_index().sort_values(by=['Stat','GP'],ascending=[False,True]).reset_index(drop=True)
356
+
357
+
358
+ @output
359
+ @render.plot(alt="A histogram")
360
+ def plot():
361
+
362
+ team_select_list = [input.team_select()]
363
+ position_select_list = [input.position_select()]
364
+
365
+ if team_select_list[0] == 'All':
366
+ team_select_title = 'NHL '
367
+ else:
368
+ team_select_title = f'{team_abv_nst_dict[team_select_list[0]]} '
369
+
370
+
371
+ if position_select_list[0] == 'All':
372
+ position_select_title = ''
373
 
374
+
375
+ elif position_select_list[0] == 'F':
376
+ position_select_title = 'Forwards '
377
 
378
+
379
+ else:
380
+ position_select_title = 'Defense '
 
 
 
 
 
381
 
382
+
383
+ rookie = ''
384
+ if input.rookie_switch():
385
+ rookie = 'Rookie '
386
+
387
+ i = 0
388
+ #rookie = ''
389
+ current_season = '2023'
390
+ start_season = '2024'
391
 
392
+
393
+ # player_lookup_list = ['Connor McDavid','David Pastrnak','Nathan MacKinnon']
394
 
395
+
396
+ type(input.id())
397
+ print(input.id())
398
+ player_lookup_list = list(input.id())[0:10]
399
 
400
+
401
+ stat = input.stat()
402
+ sns.set_theme(style="whitegrid", palette="pastel")
403
+ #print(type([input.date()))
404
+ date_range_list = [pd.to_datetime(input.date())]
405
+ for k in range(len(date_range_list)):
406
+ print(date_range_list[k])
407
  stat = input.stat()
408
+ team_schedule_url_merge = []
409
+ max_games_player = []
410
+ max_games_team = []
411
+ max_stat = []
412
+ per_game = False
413
+ for i in range(0,len(player_lookup_list)):
414
+ team_schedule_url_merge.append(player_games_df[(player_games_df.player_id == int(player_lookup_list[i]))&(date_range_list[k] >= player_games_df.date)].reset_index(drop=True))
415
+ #print('touble',i, player_lookup_list[i],len(player_games_df[(player_games_df.player_id == player_lookup_list[i])]))
416
+ team_schedule_url_merge[i].index = team_schedule_url_merge[i].team_game
417
+ team_schedule_url_merge[i] = team_schedule_url_merge[i].reindex(np.arange(team_schedule_url_merge[i].team_game.min(), team_schedule_url_merge[i].team_game.max() + 1)).reset_index(drop=True)
418
+ #team_schedule_url_merge[0]['team_game'] = team_schedule_url_merge[0]['index']
419
+ #team_schedule_url_merge[0]['player_game'] =
420
+ #schedule_ccount_df[schedule_ccount_df['team'].isin(team_schedule_url_merge[0].Team.unique())].merge(right=team_schedule_url_merge[0],left_on=['date','team'],right_on=['date','Team'],how='left')
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
421
 
422
+
423
+ team_schedule_url_merge[i]['stat'] = team_schedule_url_merge[i][stat].cumsum()
424
 
425
+
 
 
426
 
427
+
428
+ #team_schedule_url_merge[i]['stat'] = team_schedule_url_merge[i][stat_pick]
429
+ team_schedule_url_merge[i] = team_schedule_url_merge[i].append(team_schedule_url_merge[i]).sort_index()
430
+ team_schedule_url_merge[i] = team_schedule_url_merge[i].append(team_schedule_url_merge[i].iloc[0]).sort_index().reset_index(drop=True)
431
 
432
+ team_schedule_url_merge[i]['team_game'][0] = 0
433
+ team_schedule_url_merge[i]['player_game'][0] = 0
434
+ team_schedule_url_merge[i]['stat'][0] = 0
435
 
436
+
437
+ for j in range(1,len(team_schedule_url_merge[i]),2):
438
+ team_schedule_url_merge[i]['player_game'][j] = team_schedule_url_merge[i]['player_game'][j]-1
439
+ team_schedule_url_merge[i]['team_game'][j] = team_schedule_url_merge[i]['team_game'][j]-1
440
+ team_schedule_url_merge[i]['stat'][j] = team_schedule_url_merge[i]['stat'][j] - team_schedule_url_merge[i][stat][j]
441
+
442
+ if len(team_schedule_url_merge[i]) >3:
443
+ if pd.isna(team_schedule_url_merge[i].iloc[3]['player_game']) and pd.isna(team_schedule_url_merge[i].iloc[1]['player_game']) == True:
444
+ team_schedule_url_merge[i]['player_game'][2] = np.nan
445
+ team_schedule_url_merge[i]['stat'][2] = np.nan
446
+
447
+ if len(team_schedule_url_merge[i]) >3:
448
+ if pd.isna(team_schedule_url_merge[i].iloc[len(team_schedule_url_merge[i])-1]['player_game']) == True:
449
+ team_schedule_url_merge[i]['stat'][len(team_schedule_url_merge[i])-1] = np.nanmax(team_schedule_url_merge[i]['stat'])
450
+
451
+ if not (team_schedule_url_merge[i]['team_game'].values[1] == team_schedule_url_merge[i]['player_game'].values[0]):
452
+ team_schedule_url_merge[i].loc[0,'team_game'] = np.nan
453
+
454
+
455
+ max_games_player.append(np.around(np.nanmax(team_schedule_url_merge[i]['player_game'])))
456
+ max_games_team.append(np.around(np.nanmax(team_schedule_url_merge[i]['team_game'])))
457
+ max_stat.append((np.around(np.nanmax(team_schedule_url_merge[i]['stat']))))
458
 
459
+
460
+ fig, ax = plt.subplots(figsize=(15,15))
461
+ cgfont = {'fontname':'Century Gothic'}
462
+ font = font_manager.FontProperties(family='Century Gothic',
463
+ style='normal', size=14)
 
464
 
465
+ ax.axhline(0,color='black',linestyle ="--",linewidth=2,alpha=1.0,label='Missed Games')
466
+ ax.axhline(0,color='black',linestyle ="-",linewidth=2,alpha=1.0)
467
 
468
+ if 'Total' in stat:
469
+ stat = stat.replace('Total ',"")
470
 
 
 
 
 
 
 
 
471
 
472
+ colour_scheme = ['#648FFF','#785EF0','#DC267F','#FE6100','#FFB000','#FAEF3B','#861318','#2ED3BC','#341BBF','#B37E2C']
 
 
473
 
474
+
475
+ for i in range(len(team_schedule_url_merge)):
476
+ sns.lineplot(team_schedule_url_merge[i].reset_index()['team_game'],team_schedule_url_merge[i].reset_index()['stat'],linewidth=3-i*.2,color=colour_scheme[i])
477
+ plt.plot(team_schedule_url_merge[i]['team_game'],team_schedule_url_merge[i]['stat'],color=ax.lines[i*2+2].get_color(),label=str(i+1)+'. '+team_schedule_url_merge[i]['Player'][0]+', '+str(int(max_stat[i]))+' '+stat+' in '+str(int(max(team_schedule_url_merge[i]['player_game'])))+' Games',linewidth=6)
478
+ ax.lines[i*2+2].set_linestyle("--")
479
 
480
+
481
+ fig.set_facecolor('#ffffff')
482
+ ax.set(xlim=(0,max([team_schedule_url_merge[x].team_game.max() for x in range(len(team_schedule_url_merge))])))
483
+ ax.set(ylim=(0,max([team_schedule_url_merge[x].stat.max() for x in range(len(team_schedule_url_merge))])))
484
+
485
+ ax.legend_.remove()
486
+
487
+ if per_game == False:
488
+ fig.suptitle(f'{rookie}{team_select_title}{position_select_title}{stat} Race',y=.98,fontsize=32,color='black',**cgfont)
489
+ ax.set_ylabel(stat,fontsize=20,color='black',**cgfont)
490
+ # else:
491
+ # fig.suptitle(stat+' Per Game, All Situations',y=.99,fontsize=48,color='black',**cgfont)
492
+ # ax.set_ylabel(stat+"/GP",fontsize=20,color='black',**cgfont)
493
+ ax.set_title(str(current_season)[0:4]+'-'+str(start_season)[-4:]+' Season',y=1.01,fontsize=18,color='black',**cgfont,x=0,ha='left')
494
+ ax.set_xlabel('Team Game',fontsize=20,color='black',**cgfont)
495
+ ax.tick_params(axis="x", labelsize=24,colors='black')
496
+ ax.set_facecolor('#ffffff')
497
+ ax.xaxis.set_major_locator(MaxNLocator(integer=True))
498
+ ax.tick_params(axis="y", labelsize=24,colors='black')
499
+ ax.yaxis.set_major_locator(MaxNLocator(integer=True))
500
+
501
+ fig.text(x=0.025,y=0.01,s="Created By: @TJStats",color='black', fontsize=20, horizontalalignment='left',**cgfont)
502
+ fig.text(x=0.975,y=0.01,s="Data: Natural Stat Trick",color='black', fontsize=20, horizontalalignment='right',**cgfont)
503
+ fig.text(x=.975,y=0.92,s='Date: '+input.date().strftime('%B %d, %Y'),color='black', fontsize=18, horizontalalignment='right',**cgfont)
504
+
505
+ ax.legend(prop=font,bbox_to_anchor=(0.01, 0.99),loc='upper left',framealpha=1,frameon=True)
506
+ plt.tight_layout()
507
+ #fig.savefig('gif_race/'+stat+rookie+str(date_range_list[k].date())+'.png', facecolor=fig.get_facecolor(), edgecolor='none',bbox_inches='tight',dpi=100)
508
+ #plt.close()
509
+ #fig.legend(prop=font,loc='best',framealpha=1,frameon=True)
510
+
511
+
512
+ app = App(app_ui, server)