wsba-hockey 1.0.0__tar.gz → 1.0.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (24) hide show
  1. {wsba_hockey-1.0.0/src/wsba_hockey.egg-info → wsba_hockey-1.0.1}/PKG-INFO +2 -2
  2. {wsba_hockey-1.0.0 → wsba_hockey-1.0.1}/README.md +1 -1
  3. {wsba_hockey-1.0.0 → wsba_hockey-1.0.1}/pyproject.toml +1 -1
  4. wsba_hockey-1.0.1/src/wsba_hockey/tools/plotting.py +137 -0
  5. {wsba_hockey-1.0.0 → wsba_hockey-1.0.1}/src/wsba_hockey/tools/scraping.py +2 -3
  6. wsba_hockey-1.0.1/src/wsba_hockey/workspace.py +67 -0
  7. {wsba_hockey-1.0.0 → wsba_hockey-1.0.1}/src/wsba_hockey/wsba_main.py +10 -31
  8. {wsba_hockey-1.0.0 → wsba_hockey-1.0.1/src/wsba_hockey.egg-info}/PKG-INFO +2 -2
  9. {wsba_hockey-1.0.0 → wsba_hockey-1.0.1}/src/wsba_hockey.egg-info/SOURCES.txt +1 -0
  10. wsba_hockey-1.0.0/src/wsba_hockey/tools/plotting.py +0 -113
  11. {wsba_hockey-1.0.0 → wsba_hockey-1.0.1}/LICENSE +0 -0
  12. {wsba_hockey-1.0.0 → wsba_hockey-1.0.1}/setup.cfg +0 -0
  13. {wsba_hockey-1.0.0 → wsba_hockey-1.0.1}/src/wsba_hockey/__init__.py +0 -0
  14. {wsba_hockey-1.0.0 → wsba_hockey-1.0.1}/src/wsba_hockey/stats/calculate_viz/shot_impact.py +0 -0
  15. {wsba_hockey-1.0.0 → wsba_hockey-1.0.1}/src/wsba_hockey/tools/__init__.py +0 -0
  16. {wsba_hockey-1.0.0 → wsba_hockey-1.0.1}/src/wsba_hockey/tools/agg.py +0 -0
  17. {wsba_hockey-1.0.0 → wsba_hockey-1.0.1}/src/wsba_hockey/tools/archive/old_scraping.py +0 -0
  18. {wsba_hockey-1.0.0 → wsba_hockey-1.0.1}/src/wsba_hockey/tools/utils/__init__.py +0 -0
  19. {wsba_hockey-1.0.0 → wsba_hockey-1.0.1}/src/wsba_hockey/tools/utils/config.py +0 -0
  20. {wsba_hockey-1.0.0 → wsba_hockey-1.0.1}/src/wsba_hockey/tools/utils/save_pages.py +0 -0
  21. {wsba_hockey-1.0.0 → wsba_hockey-1.0.1}/src/wsba_hockey/tools/utils/shared.py +0 -0
  22. {wsba_hockey-1.0.0 → wsba_hockey-1.0.1}/src/wsba_hockey/tools/xg_model.py +0 -0
  23. {wsba_hockey-1.0.0 → wsba_hockey-1.0.1}/src/wsba_hockey.egg-info/dependency_links.txt +0 -0
  24. {wsba_hockey-1.0.0 → wsba_hockey-1.0.1}/src/wsba_hockey.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: wsba_hockey
3
- Version: 1.0.0
3
+ Version: 1.0.1
4
4
  Summary: WeakSide Breakout's complete Python package of access to hockey data, primairly including the scraping of National Hockey League schedule, play-by-play, and shifts information.
5
5
  Author-email: Owen Singh <owenbksingh@gmail.com>
6
6
  Project-URL: Homepage, https://github.com/owensingh38/wsba_hockey/
@@ -78,7 +78,7 @@ skater_dict = {
78
78
  }
79
79
  pbp = wsba.nhl_scrape_season('20212022',remove=[], local = True)
80
80
 
81
- wsba.nhl_plot_skater_shots(pbp,skater_dict,['5v5'],legend=True)
81
+ wsba.nhl_plot_skaters_shots(pbp,skater_dict,['5v5'],onice='for',legend=True)
82
82
  wsba.nhl_plot_games(pbp,legend=True)
83
83
  ```
84
84
 
@@ -63,7 +63,7 @@ skater_dict = {
63
63
  }
64
64
  pbp = wsba.nhl_scrape_season('20212022',remove=[], local = True)
65
65
 
66
- wsba.nhl_plot_skater_shots(pbp,skater_dict,['5v5'],legend=True)
66
+ wsba.nhl_plot_skaters_shots(pbp,skater_dict,['5v5'],onice='for',legend=True)
67
67
  wsba.nhl_plot_games(pbp,legend=True)
68
68
  ```
69
69
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "wsba_hockey"
3
- version = "1.0.0"
3
+ version = "1.0.1"
4
4
  authors = [
5
5
  { name="Owen Singh", email="owenbksingh@gmail.com" },
6
6
  ]
@@ -0,0 +1,137 @@
1
+ import matplotlib.pyplot as plt
2
+ import matplotlib.image as img
3
+ import numpy as np
4
+ import pandas as pd
5
+ from scipy.interpolate import griddata
6
+ from scipy.ndimage import gaussian_filter
7
+ from .xg_model import *
8
+ from hockey_rink import NHLRink
9
+ from hockey_rink import CircularImage
10
+
11
+ event_markers = {
12
+ 'faceoff':'X',
13
+ 'hit':'P',
14
+ 'blocked-shot':'v',
15
+ 'missed-shot':'H',
16
+ 'shot-on-goal':'D',
17
+ 'goal':'o',
18
+ 'giveaway':'1',
19
+ 'takeaway':'2',
20
+ }
21
+
22
+ def wsba_rink(display_range='offense',rotation = 0):
23
+ img = 'tools/utils/wsba.png'
24
+ rink = NHLRink(center_logo={
25
+ "feature_class": CircularImage,
26
+ "image_path": img,
27
+ "length": 25, "width": 25,
28
+ "x": 0, "y": 0,
29
+ "radius": 14,
30
+ "zorder": 11,
31
+ }
32
+ )
33
+ rink.draw(
34
+ display_range=display_range,
35
+ rotation=rotation,
36
+ despine=True
37
+ )
38
+
39
+ def prep_plot_data(pbp,events,strengths,marker_dict=event_markers,xg='moneypuck'):
40
+ try: pbp['xG']
41
+ except:
42
+ if xg == 'wsba':
43
+ pbp = wsba_xG(pbp)
44
+ else:
45
+ pbp = moneypuck_xG(pbp)
46
+ pbp['xG'] = np.where(pbp['xG'].isna(),0,pbp['xG'])
47
+
48
+ pbp['WSBA'] = pbp['event_player_1_name']+pbp['season'].astype(str)+pbp['event_team_abbr']
49
+
50
+ pbp['x_plot'] = pbp['y_fixed']*-1
51
+ pbp['y_plot'] = pbp['x_fixed']
52
+
53
+ pbp['home_on_ice'] = pbp['home_on_1'].astype(str) + ";" + pbp['home_on_2'].astype(str) + ";" + pbp['home_on_3'].astype(str) + ";" + pbp['home_on_4'].astype(str) + ";" + pbp['home_on_5'].astype(str) + ";" + pbp['home_on_6'].astype(str)
54
+ pbp['away_on_ice'] = pbp['away_on_1'].astype(str) + ";" + pbp['away_on_2'].astype(str) + ";" + pbp['away_on_3'].astype(str) + ";" + pbp['away_on_4'].astype(str) + ";" + pbp['away_on_5'].astype(str) + ";" + pbp['away_on_6'].astype(str)
55
+
56
+ pbp['onice_for'] = np.where(pbp['home_team_abbr']==pbp['event_team_abbr'],pbp['home_on_ice'],pbp['away_on_ice'])
57
+ pbp['onice_against'] = np.where(pbp['away_team_abbr']==pbp['event_team_abbr'],pbp['home_on_ice'],pbp['away_on_ice'])
58
+
59
+ pbp['size'] = np.where(pbp['xG']<=0,40,pbp['xG']*400)
60
+ pbp['marker'] = pbp['event_type'].replace(marker_dict)
61
+
62
+ pbp = pbp.loc[(pbp['event_type'].isin(events))&
63
+ (pbp['event_distance']<=89)&
64
+ (pbp['x_fixed']<=89)]
65
+
66
+ if strengths != 'all':
67
+ pbp = pbp.loc[(pbp['strength_state'].isin(strengths))]
68
+
69
+ return pbp
70
+
71
+ def league_shots(pbp,events,strengths):
72
+ pbp = prep_plot_data(pbp,events,strengths)
73
+
74
+ print(pbp[['event_player_1_name','xG','x_plot','y_plot']].head(10))
75
+
76
+ [x,y] = np.round(np.meshgrid(np.linspace(-42.5,42.5,85),np.linspace(0,100,100)))
77
+ xgoals = griddata((pbp[f'x_plot'],pbp[f'y_plot']),pbp['xG'],(x,y),method='cubic',fill_value=0)
78
+ xgoals_smooth = gaussian_filter(xgoals,sigma = 3)
79
+
80
+ return xgoals_smooth
81
+
82
+ def plot_skater_shots(pbp, player, season, team, strengths, title = None, marker_dict=event_markers, onice='for', legend=False,xg='moneypuck'):
83
+ shots = ['missed-shot','shot-on-goal','goal']
84
+ pbp = prep_plot_data(pbp,shots,strengths,marker_dict,xg)
85
+ pbp = pbp.loc[(pbp['season'].astype(str)==season)&((pbp['away_team_abbr']==team)|(pbp['home_team_abbr']==team))]
86
+
87
+ team_data = pd.read_csv('teaminfo/nhl_teaminfo.csv')
88
+ team_color = list(team_data.loc[team_data['WSBA']==f'{team}{season}','Primary Color'])[0]
89
+ team_color_2nd = list(team_data.loc[team_data['WSBA']==f'{team}{season}','Secondary Color'])[0]
90
+
91
+ if onice in ['for','against']:
92
+ skater = pbp.loc[(pbp[f'onice_{onice}'].str.contains(player.upper()))]
93
+ skater['color'] = np.where(skater['event_player_1_name']==player.upper(),team_color,team_color_2nd)
94
+
95
+ else:
96
+ skater = pbp.loc[pbp['event_player_1_name']==player.upper()]
97
+ skater['color'] = team_color
98
+
99
+ fig, ax = plt.subplots()
100
+ wsba_rink(rotation=90)
101
+
102
+ for event in shots:
103
+ plays = skater.loc[skater['event_type']==event]
104
+ ax.scatter(plays['x_plot'],plays['y_plot'],plays['size'],plays['color'],marker=event_markers[event],label=event,zorder=5)
105
+
106
+ ax.set_title(title) if title else ''
107
+ ax.legend().set_visible(legend)
108
+ ax.legend().set_zorder(1000)
109
+
110
+ return fig
111
+
112
+ def plot_game_events(pbp,game_id,events,strengths,marker_dict=event_markers,legend=False,xg='moneypuck'):
113
+ pbp = prep_plot_data(pbp,events,strengths,marker_dict,xg)
114
+ pbp = pbp.loc[pbp['game_id'].astype(str)==game_id]
115
+
116
+ away_abbr = list(pbp['away_team_abbr'])[0]
117
+ home_abbr = list(pbp['home_team_abbr'])[0]
118
+ date = list(pbp['game_date'])[0]
119
+ season = f'{game_id[0:4]}{int(game_id[0:4])+1}'
120
+
121
+ team_data = pd.read_csv('teaminfo/nhl_teaminfo.csv')
122
+ away_color = list(team_data.loc[team_data['WSBA']==f'{away_abbr}{season}','Primary Color'])[0]
123
+ home_color = list(team_data.loc[team_data['WSBA']==f'{home_abbr}{season}','Primary Color'])[0]
124
+
125
+ pbp['color'] = np.where(pbp['event_team_abbr']==away_abbr,away_color,home_color)
126
+
127
+ fig, ax = plt.subplots()
128
+ wsba_rink(display_range='full')
129
+
130
+ for event in events:
131
+ plays = pbp.loc[pbp['event_type']==event]
132
+ ax.scatter(plays['x_adj'],plays['y_adj'],plays['size'],plays['color'],marker=event_markers[event],label=event,zorder=5)
133
+
134
+ ax.set_title(f'{away_abbr} @ {home_abbr} - {date}')
135
+ ax.legend(bbox_to_anchor =(0.5,-0.35), loc='lower center',ncol=1).set_visible(legend)
136
+
137
+ return fig
@@ -337,7 +337,6 @@ def parse_espn(date,away,home):
337
337
  coords_df = coords_df.assign(
338
338
  coords_x = coords_df[~pd.isna(coords_df.coordinate)].coordinate.apply(lambda x: x['x']).astype(int),
339
339
  coords_y = coords_df[~pd.isna(coords_df.coordinate)].coordinate.apply(lambda y: y['y']).astype(int),
340
- event_player_1_name = coords_df[~pd.isna(coords_df.athlete)]['athlete'].apply(lambda x: x['name'])
341
340
  )
342
341
 
343
342
  #Combine
@@ -356,7 +355,7 @@ def parse_espn(date,away,home):
356
355
  coords_y = np.where((pd.isna(espn_events.coords_x)) & (pd.isna(espn_events.coords_y)) &
357
356
  (espn_events.event_type=='Face Off'), 0, espn_events.coords_y))
358
357
 
359
- espn_events = espn_events[(~pd.isna(espn_events.coords_x)) & (~pd.isna(espn_events.coords_y)) & (~pd.isna(espn_events.event_player_1_name))]
358
+ espn_events = espn_events[(~pd.isna(espn_events.coords_x)) & (~pd.isna(espn_events.coords_y))]
360
359
 
361
360
  espn_events = espn_events.assign(
362
361
  coords_x = espn_events.coords_x.astype(int),
@@ -711,7 +710,7 @@ def combine_pbp(info):
711
710
  #Route data combining - json if season is after 2009-2010:
712
711
  if str(info['season']) in ['20052006','20062007','20072008','20082009','20092010']:
713
712
  #ESPN x HTML
714
- espn_pbp = parse_espn(str(info['game_date']),info['away_team_abbr'],info['home_team_abbr']).rename(columns={'coords_x':'x',"coords_y":'y'}).drop(columns=['event_player_1_name'])
713
+ espn_pbp = parse_espn(str(info['game_date']),info['away_team_abbr'],info['home_team_abbr']).rename(columns={'coords_x':'x',"coords_y":'y'})
715
714
  merge_col = ['period','seconds_elapsed','event_type','event_team_abbr']
716
715
 
717
716
  df = pd.merge(html_pbp,espn_pbp,how='left',on=merge_col)
@@ -0,0 +1,67 @@
1
+ import numpy as np
2
+ import pandas as pd
3
+ import matplotlib
4
+ import matplotlib.pyplot as plt
5
+ import wsba_hockey as wsba
6
+
7
+ season_load = wsba.repo_load_seasons()
8
+
9
+ def workspace(seasons,type):
10
+ if type == 'pbp':
11
+ #Scrape pbp
12
+ errors=[]
13
+ for season in seasons:
14
+ data = wsba.nhl_scrape_season(season,remove=[],local=True,errors=True)
15
+ errors.append(data['errors'])
16
+ data['pbp'].to_csv(f'pbp/nhl_pbp_{season}.csv',index=False)
17
+ print(f'Errors: {errors}')
18
+
19
+ elif type == 'convert':
20
+ for season in seasons[6:12]:
21
+ data = pd.read_csv(f"pbp/nhl_pbp_{season}.csv")
22
+ data = wsba.wsba_main.moneypuck_xG(data)
23
+ data.to_parquet(f'pbp/parquet/nhl_pbp_{season}.parquet',index=False)
24
+
25
+ elif type == 'standings':
26
+ #Scrape standings
27
+ stand = [wsba.nhl_scrape_standings(season) for season in season]
28
+ pd.concat(stand).to_csv('teaminfo/nhl_standings.csv',index=False)
29
+
30
+ elif type == 'stats':
31
+ #Stats building
32
+ stats = []
33
+ for season in seasons[6:18]:
34
+ for group in ['skater','team']:
35
+ pbp = pd.read_parquet(f'pbp/parquet/nhl_pbp_{season}.parquet')
36
+ stat = wsba.nhl_calculate_stats(pbp,group,[2],['5v5'],shot_impact=True)
37
+ stat.to_csv(f'stats/{group}/wsba_nhl_{season}_{group}.csv',index=False)
38
+ stats.append(stat)
39
+ pd.concat(stats).to_csv(f'stats/db/wsba_nhl_{group}_db.csv',index=False)
40
+ else:
41
+ print('Nothing here.')
42
+
43
+ pbp = pd.read_parquet('pbp/parquet/nhl_pbp_20242025.parquet')
44
+
45
+ skaters={}
46
+
47
+ for shooter,season,team in zip(pbp['event_player_1_name'],pbp['season'].astype(str),pbp['event_team_abbr']):
48
+ if shooter is None:
49
+ continue
50
+ else:
51
+ skaters.update({
52
+ shooter:[season,team]
53
+ })
54
+
55
+ plots = wsba.nhl_plot_skaters_shots(pbp,skaters,['5v5'],onice='indv',legend=True)
56
+
57
+ items = list(skaters.items())
58
+ for plot,skater in zip(plots,items):
59
+ plt.title('')
60
+ plot.savefig(f'plots/{skater[0]}{skater[1][0]}{skater[1][1]}_indv.png',bbox_inches='tight',transparent=True)
61
+
62
+ plots = wsba.nhl_plot_games(wsba.nhl_scrape_season('20242025',start='04-19',end='04-19'),wsba.wsba_main.fenwick_events,['5v5'],'all',legend=True)
63
+
64
+ i = 1
65
+ for plot in plots:
66
+ plot.savefig(f'plots/20242025_03_{i}_shotplot.png',bbox_inches='tight',transparent=True)
67
+ i += 1
@@ -328,8 +328,7 @@ def nhl_scrape_season(season,split_shifts = False, season_types = [2,3], remove
328
328
  pbp_dict.update({'errors':data['errors']})
329
329
  return pbp_dict
330
330
  else:
331
- pbp = data['pbp']
332
-
331
+ pbp = data
333
332
  if errors:
334
333
  pbp_dict = {'pbp':pbp,
335
334
  'errors':data['errors']}
@@ -337,13 +336,6 @@ def nhl_scrape_season(season,split_shifts = False, season_types = [2,3], remove
337
336
  else:
338
337
  return pbp
339
338
 
340
- #errors = []
341
- #for season in seasons[10:12]:
342
- # data = nhl_scrape_season(season,remove=[],local=True,errors=True)
343
- # errors.append(data['errors'])
344
- # data['pbp'].to_csv(f'pbp/csv/nhl_pbp_{season}.csv',index=False)
345
- #print(f'Errors: {errors}')
346
-
347
339
  def nhl_scrape_seasons_info(seasons = []):
348
340
  #Returns info related to NHL seasons (by default, all seasons are included)
349
341
  # param 'season' - list of seasons to include
@@ -394,9 +386,6 @@ def nhl_scrape_standings(arg = "now", season_type = 2):
394
386
 
395
387
  return pd.json_normalize(data)
396
388
 
397
- #stand = [nhl_scrape_standings(season) for season in seasons]
398
- #pd.concat(stand).to_csv('teaminfo/nhl_standings.csv',index=False)
399
-
400
389
  def nhl_scrape_roster(season):
401
390
  #Given a nhl season, return rosters for all participating teams
402
391
  # param 'season' - NHL season to scrape
@@ -782,20 +771,14 @@ def nhl_calculate_stats(pbp,type,season_types,game_strength,roster_path="rosters
782
771
  else:
783
772
  return complete
784
773
 
785
- #stats = []
786
- #for season in seasons[6:18]:
787
- # pbp = pd.read_parquet(f'pbp/parquet/nhl_pbp_{season}.parquet')
788
- # stat = nhl_calculate_stats(pbp,'skater',[2],['5v5'],shot_impact=True)
789
- # stat.to_csv(f'stats/skater/wsba_nhl_{season}.csv',index=False)
790
- # stats.append(stat)
791
- #pd.concat(stats).to_csv('stats/db/wsba_nhl_skater_db.csv',index=False)
792
-
793
- def nhl_plot_skaters_shots(pbp,skater_dict,strengths,color_dict=event_colors,legend=False,xg='moneypuck'):
774
+ def nhl_plot_skaters_shots(pbp,skater_dict,strengths,marker_dict=event_markers,onice = 'indv',title = True,legend=False,xg='moneypuck'):
794
775
  #Returns list of plots for specified skaters
795
776
  # param 'pbp' - pbp to plot data
796
777
  # param 'skater_dict' - skaters to plot shots for (format: {'Patrice Bergeron':['20242025','BOS']})
797
778
  # param 'strengths' - strengths to include in plotting
798
- # param 'color_dict' - dict with colors to use for events
779
+ # param 'marker_dict' - dict with markers to use for events
780
+ # param 'onice' - can set which shots to include in plotting for the specified skater ('indv', 'for', 'against')
781
+ # param 'title' - bool including title when true
799
782
  # param 'legend' - bool which includes legend if true
800
783
  # param 'xg' - xG model to apply to pbp for plotting
801
784
 
@@ -805,19 +788,19 @@ def nhl_plot_skaters_shots(pbp,skater_dict,strengths,color_dict=event_colors,leg
805
788
  skater_plots = []
806
789
  for skater in skater_dict.keys():
807
790
  skater_info = skater_dict[skater]
808
- title = f'{skater} Fenwick Shots for {skater_info[1]} in {skater_info[0][2:4]}-{skater_info[0][6:8]}'
809
- skater_plots.append(plot_skater_shots(pbp,skater,skater_info[0],skater_info[1],strengths,title,color_dict,legend,xg))
791
+ title = f'{skater} Fenwick Shots for {skater_info[1]} in {skater_info[0][2:4]}-{skater_info[0][6:8]}' if title else ''
792
+ skater_plots.append(plot_skater_shots(pbp,skater,skater_info[0],skater_info[1],strengths,title,marker_dict,onice,legend,xg))
810
793
 
811
794
  #Return: list of plotted skater shot charts
812
795
  return skater_plots
813
796
 
814
- def nhl_plot_games(pbp,events,strengths,game_ids='all',color_dict=event_colors,legend=False,xg='moneypuck'):
797
+ def nhl_plot_games(pbp,events,strengths,game_ids='all',marker_dict=event_markers,legend=False,xg='moneypuck'):
815
798
  #Returns list of plots for specified games
816
799
  # param 'pbp' - pbp to plot data
817
800
  # param 'events' - type of events to plot
818
801
  # param 'strengths' - strengths to include in plotting
819
802
  # param 'game_ids' - games to plot (list if not set to 'all')
820
- # param 'color_dict' - dict with colors to use for events
803
+ # param 'marker_dict' - dict with colors to use for events
821
804
  # param 'legend' - bool which includes legend if true
822
805
  # param 'xg' - xG model to apply to pbp for plotting
823
806
 
@@ -828,7 +811,7 @@ def nhl_plot_games(pbp,events,strengths,game_ids='all',color_dict=event_colors,l
828
811
  print(f'Plotting the following games: {game_ids}...')
829
812
 
830
813
  #Iterate through games, adding plot to list
831
- game_plots = [plot_game_events(pbp,game,events,strengths,color_dict,legend,xg) for game in game_ids]
814
+ game_plots = [plot_game_events(pbp,game,events,strengths,marker_dict,legend,xg) for game in game_ids]
832
815
 
833
816
  #Return: list of plotted game events
834
817
  return game_plots
@@ -878,7 +861,3 @@ def admin_convert_to_parquet(seasons):
878
861
  load = pd.read_csv(f'pbp/csv/nhl_pbp_{season}.csv')
879
862
 
880
863
  load.to_parquet(f'pbp/parquet/nhl_pbp_{season}.parquet',index=False)
881
-
882
- #for season in seasons[6:12]:
883
- # data = pd.read_csv(f"pbp/csv/nhl_pbp_{season}.csv")
884
- # data.to_parquet(f'pbp/parquet/nhl_pbp_{season}.parquet',index=False)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: wsba_hockey
3
- Version: 1.0.0
3
+ Version: 1.0.1
4
4
  Summary: WeakSide Breakout's complete Python package of access to hockey data, primairly including the scraping of National Hockey League schedule, play-by-play, and shifts information.
5
5
  Author-email: Owen Singh <owenbksingh@gmail.com>
6
6
  Project-URL: Homepage, https://github.com/owensingh38/wsba_hockey/
@@ -78,7 +78,7 @@ skater_dict = {
78
78
  }
79
79
  pbp = wsba.nhl_scrape_season('20212022',remove=[], local = True)
80
80
 
81
- wsba.nhl_plot_skater_shots(pbp,skater_dict,['5v5'],legend=True)
81
+ wsba.nhl_plot_skaters_shots(pbp,skater_dict,['5v5'],onice='for',legend=True)
82
82
  wsba.nhl_plot_games(pbp,legend=True)
83
83
  ```
84
84
 
@@ -2,6 +2,7 @@ LICENSE
2
2
  README.md
3
3
  pyproject.toml
4
4
  src/wsba_hockey/__init__.py
5
+ src/wsba_hockey/workspace.py
5
6
  src/wsba_hockey/wsba_main.py
6
7
  src/wsba_hockey.egg-info/PKG-INFO
7
8
  src/wsba_hockey.egg-info/SOURCES.txt
@@ -1,113 +0,0 @@
1
- import matplotlib.pyplot as plt
2
- import matplotlib.image as img
3
- import numpy as np
4
- import pandas as pd
5
- pd.options.mode.chained_assignment = None
6
- from scipy.interpolate import griddata
7
- from scipy.ndimage import gaussian_filter
8
- from .xg_model import *
9
- from hockey_rink import NHLRink
10
- from hockey_rink import CircularImage
11
-
12
- event_colors = {
13
- 'faceoff':'black',
14
- 'hit':'yellow',
15
- 'blocked-shot':'pink',
16
- 'missed-shot':'red',
17
- 'shot-on-goal':'purple',
18
- 'goal':'blue',
19
- 'giveaway':'orange',
20
- 'takeaway':'green',
21
- }
22
-
23
- def wsba_rink(display_range='offense',rotation = 0):
24
- img = 'tools/utils/wsba.png'
25
- rink = NHLRink(center_logo={
26
- "feature_class": CircularImage,
27
- "image_path": img,
28
- "length": 25, "width": 25,
29
- "x": 0, "y": 0,
30
- "radius": 14,
31
- "zorder": 11,
32
- }
33
- )
34
- rink.draw(
35
- display_range=display_range,
36
- rotation=rotation,
37
- despine=True
38
- )
39
-
40
- def prep_plot_data(pbp,events,strengths,color_dict=event_colors,xg='moneypuck'):
41
- try: pbp['xG']
42
- except:
43
- if xg == 'wsba':
44
- pbp = wsba_xG(pbp)
45
- else:
46
- pbp = moneypuck_xG(pbp)
47
- pbp['xG'] = np.where(pbp['xG'].isna(),0,pbp['xG'])
48
-
49
- pbp['WSBA'] = pbp['event_player_1_name']+pbp['season'].astype(str)+pbp['event_team_abbr']
50
-
51
- pbp['x_plot'] = pbp['y_fixed']*-1
52
- pbp['y_plot'] = pbp['x_fixed']
53
-
54
- pbp['size'] = np.where(pbp['xG']<=0,100,pbp['xG']*1000)
55
- pbp['color'] = pbp['event_type'].replace(color_dict)
56
-
57
- pbp = pbp.loc[(pbp['event_type'].isin(events))&
58
- (pbp['event_distance']<=89)&
59
- (pbp['x_fixed']<=89)&
60
- (pbp['strength_state'].isin(strengths))]
61
-
62
- return pbp
63
-
64
- def league_shots(pbp,cord = 'fixed'):
65
- [x,y] = np.round(np.meshgrid(np.linspace(0,100,100),np.linspace(-42.5,42.5,85)))
66
- xgoals = griddata((pbp[f'x_{cord}'],pbp[f'y_{cord}']),pbp['xG'],(x,y),method='cubic',fill_value=0)
67
- xgoals_smooth = gaussian_filter(xgoals,sigma = 3)
68
-
69
- fig = plt.figure(figsize=(10,12), facecolor='w', edgecolor='k')
70
- plt.imshow(xgoals_smooth,origin = 'lower')
71
- plt.colorbar(orientation = 'horizontal', pad = 0.05)
72
- plt.title('xGoal Array',fontdict={'fontsize': 15})
73
- plt.show()
74
-
75
- return xgoals_smooth
76
-
77
-
78
- def plot_skater_shots(pbp, player, season, team, strengths, title = None, color_dict=event_colors, legend=False,xg='moneypuck'):
79
- shots = ['missed-shot','shot-on-goal','goal']
80
- pbp = prep_plot_data(pbp,shots,strengths,color_dict,xg)
81
- skater = pbp.loc[pbp['WSBA'] == f'{player.upper()}{season}{team}']
82
-
83
- fig, ax = plt.subplots()
84
- wsba_rink(rotation=90)
85
-
86
- for event in shots:
87
- plays = skater.loc[skater['event_type']==event]
88
- ax.scatter(plays['x_plot'],plays['y_plot'],plays['size'],plays['color'],label=event)
89
-
90
- ax.set_title(title) if title else ''
91
- ax.legend().set_visible(legend)
92
-
93
- return fig
94
-
95
- def plot_game_events(pbp,game_id,events,strengths,color_dict=event_colors,legend=False,xg='moneypuck'):
96
- pbp = prep_plot_data(pbp,events,strengths,color_dict,xg)
97
- pbp = pbp.loc[pbp['game_id'].astype(str)==game_id]
98
-
99
- away_abbr = list(pbp['away_team_abbr'])[0]
100
- home_abbr = list(pbp['home_team_abbr'])[0]
101
- date = list(pbp['game_date'])[0]
102
-
103
- fig, ax = plt.subplots()
104
- wsba_rink(display_range='full')
105
-
106
- for event in events:
107
- plays = pbp.loc[pbp['event_type']==event]
108
- ax.scatter(plays['x_adj'],plays['y_adj'],plays['size'],plays['color'],label=event)
109
-
110
- ax.set_title(f'{away_abbr} @ {home_abbr} - {date}')
111
- ax.legend(bbox_to_anchor =(0.5,-0.4), loc='lower center',ncol=1).set_visible(legend)
112
-
113
- return fig
File without changes
File without changes