wsba-hockey 1.0.3__py3-none-any.whl → 1.0.4__py3-none-any.whl
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.
- wsba_hockey/data_pipelines.py +183 -0
- wsba_hockey/evidence/weakside-breakout/node_modules/duckdb/vendor.py +146 -0
- wsba_hockey/evidence/weakside-breakout/node_modules/flatted/python/flatted.py +149 -0
- wsba_hockey/evidence/weakside-breakout/node_modules/flatted/python/test.py +63 -0
- wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/gyp_main.py +45 -0
- wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/MSVSNew.py +367 -0
- wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/MSVSProject.py +206 -0
- wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/MSVSSettings.py +1270 -0
- wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/MSVSSettings_test.py +1547 -0
- wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/MSVSToolFile.py +59 -0
- wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/MSVSUserFile.py +153 -0
- wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/MSVSUtil.py +271 -0
- wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/MSVSVersion.py +574 -0
- wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/__init__.py +690 -0
- wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/common.py +661 -0
- wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/common_test.py +78 -0
- wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/easy_xml.py +165 -0
- wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/easy_xml_test.py +109 -0
- wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/flock_tool.py +55 -0
- wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/generator/__init__.py +0 -0
- wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/generator/analyzer.py +808 -0
- wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/generator/android.py +1173 -0
- wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/generator/cmake.py +1321 -0
- wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/generator/compile_commands_json.py +120 -0
- wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/generator/dump_dependency_json.py +103 -0
- wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/generator/eclipse.py +464 -0
- wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/generator/gypd.py +89 -0
- wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/generator/gypsh.py +58 -0
- wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/generator/make.py +2714 -0
- wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/generator/msvs.py +3981 -0
- wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/generator/msvs_test.py +44 -0
- wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/generator/ninja.py +2936 -0
- wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/generator/ninja_test.py +55 -0
- wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/generator/xcode.py +1394 -0
- wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/generator/xcode_test.py +25 -0
- wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/input.py +3130 -0
- wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/input_test.py +98 -0
- wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/mac_tool.py +771 -0
- wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/msvs_emulation.py +1271 -0
- wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/ninja_syntax.py +174 -0
- wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/simple_copy.py +61 -0
- wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/win_tool.py +374 -0
- wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/xcode_emulation.py +1939 -0
- wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/xcode_ninja.py +302 -0
- wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/xcodeproj_file.py +3197 -0
- wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/pylib/gyp/xml_fix.py +65 -0
- wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/test_gyp.py +261 -0
- wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/tools/graphviz.py +102 -0
- wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/tools/pretty_gyp.py +156 -0
- wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/tools/pretty_sln.py +181 -0
- wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/gyp/tools/pretty_vcproj.py +339 -0
- wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/test/fixtures/test-charmap.py +31 -0
- wsba_hockey/evidence/weakside-breakout/node_modules/node-gyp/update-gyp.py +64 -0
- wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/gyp_main.py +45 -0
- wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/MSVSNew.py +367 -0
- wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/MSVSProject.py +206 -0
- wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/MSVSSettings.py +1270 -0
- wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/MSVSSettings_test.py +1547 -0
- wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/MSVSToolFile.py +59 -0
- wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/MSVSUserFile.py +153 -0
- wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/MSVSUtil.py +271 -0
- wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/MSVSVersion.py +574 -0
- wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/__init__.py +666 -0
- wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/common.py +654 -0
- wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/common_test.py +78 -0
- wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/easy_xml.py +165 -0
- wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/easy_xml_test.py +109 -0
- wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/flock_tool.py +55 -0
- wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/generator/__init__.py +0 -0
- wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/generator/analyzer.py +808 -0
- wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/generator/android.py +1173 -0
- wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/generator/cmake.py +1321 -0
- wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/generator/compile_commands_json.py +120 -0
- wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/generator/dump_dependency_json.py +103 -0
- wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/generator/eclipse.py +464 -0
- wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/generator/gypd.py +89 -0
- wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/generator/gypsh.py +58 -0
- wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/generator/make.py +2518 -0
- wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/generator/msvs.py +3978 -0
- wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/generator/msvs_test.py +44 -0
- wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/generator/ninja.py +2936 -0
- wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/generator/ninja_test.py +55 -0
- wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/generator/xcode.py +1394 -0
- wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/generator/xcode_test.py +25 -0
- wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/input.py +3137 -0
- wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/input_test.py +98 -0
- wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/mac_tool.py +771 -0
- wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/msvs_emulation.py +1271 -0
- wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/ninja_syntax.py +174 -0
- wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/simple_copy.py +61 -0
- wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/win_tool.py +374 -0
- wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/xcode_emulation.py +1939 -0
- wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/xcode_ninja.py +302 -0
- wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/xcodeproj_file.py +3197 -0
- wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/pylib/gyp/xml_fix.py +65 -0
- wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/setup.py +42 -0
- wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/test_gyp.py +260 -0
- wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/tools/graphviz.py +102 -0
- wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/tools/pretty_gyp.py +156 -0
- wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/tools/pretty_sln.py +181 -0
- wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/tools/pretty_vcproj.py +339 -0
- wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/test/fixtures/test-charmap.py +31 -0
- wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/update-gyp.py +46 -0
- wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/game_stats/app.py +401 -0
- wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/game_stats/name_fix.py +47 -0
- wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/heatmaps/app.py +108 -0
- wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/heatmaps/plot.py +93 -0
- wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/heatmaps/rink_plot.py +245 -0
- wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/matchups/app.py +145 -0
- wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/matchups/plot.py +77 -0
- wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/matchups/rink_plot.py +245 -0
- wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/pbp/app.py +389 -0
- wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/pbp/plot.py +70 -0
- wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/pbp/rink_plot.py +245 -0
- wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/skater/app.py +110 -0
- wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/skater/plot.py +58 -0
- wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/skater/rink_plot.py +245 -0
- wsba_hockey/tools/agg.py +242 -53
- wsba_hockey/tools/plotting.py +12 -17
- wsba_hockey/tools/scraping.py +149 -258
- wsba_hockey/tools/xg_model.py +357 -311
- wsba_hockey/workspace.py +22 -117
- wsba_hockey/wsba_main.py +493 -165
- {wsba_hockey-1.0.3.dist-info → wsba_hockey-1.0.4.dist-info}/METADATA +1 -1
- wsba_hockey-1.0.4.dist-info/RECORD +135 -0
- {wsba_hockey-1.0.3.dist-info → wsba_hockey-1.0.4.dist-info}/WHEEL +1 -1
- wsba_hockey/stats/calculate_viz/shot_impact.py +0 -2
- wsba_hockey-1.0.3.dist-info/RECORD +0 -19
- {wsba_hockey-1.0.3.dist-info → wsba_hockey-1.0.4.dist-info}/licenses/LICENSE +0 -0
- {wsba_hockey-1.0.3.dist-info → wsba_hockey-1.0.4.dist-info}/top_level.txt +0 -0
wsba_hockey/tools/agg.py
CHANGED
@@ -8,46 +8,81 @@ from .xg_model import *
|
|
8
8
|
shot_types = ['wrist','deflected','tip-in','slap','backhand','snap','wrap-around','poke','bat','cradle','between-legs']
|
9
9
|
fenwick_events = ['missed-shot','shot-on-goal','goal']
|
10
10
|
|
11
|
-
def calc_indv(pbp):
|
12
|
-
|
13
|
-
|
11
|
+
def calc_indv(pbp,game_strength,second_group):
|
12
|
+
# Filter by game strength if not "all"
|
13
|
+
if game_strength != "all":
|
14
|
+
pbp = pbp.loc[pbp['strength_state'].isin(game_strength)]
|
15
|
+
|
16
|
+
#Add second event-team column for necessary situations
|
17
|
+
pbp['event_team_abbr_2'] = np.where(pbp['event_team_abbr'].notna(),
|
18
|
+
np.where(pbp['event_team_abbr']==pbp['home_team_abbr'],pbp['away_team_abbr'],pbp['home_team_abbr']),np.nan)
|
19
|
+
|
20
|
+
#Change second event team to goal-scoring team for goal events
|
21
|
+
pbp['event_team_abbr_2'] = np.where(pbp['event_type']=='goal',pbp['event_team_abbr'],pbp['event_team_abbr_2'])
|
22
|
+
|
23
|
+
#Determine how to group
|
24
|
+
raw_group_1 = ['event_player_1_id','event_team_abbr']+second_group
|
25
|
+
raw_group_2 = ['event_player_2_id','event_team_abbr_2']+second_group
|
26
|
+
raw_group_3 = ['event_player_3_id','event_team_abbr']+second_group
|
27
|
+
clean_group = ['ID','Team','Season']+(['Game'] if 'game_id' in second_group else [])
|
28
|
+
|
29
|
+
#First event player stats
|
30
|
+
ep1 = (
|
31
|
+
pbp.loc[pbp['event_type'].isin(["goal", "shot-on-goal", "missed-shot","blocked-shot",'hit','giveaway','takeaway','faceoff','penalty'])].groupby(raw_group_1).agg(
|
14
32
|
Gi=('event_type', lambda x: (x == "goal").sum()),
|
15
|
-
Fi=('event_type', lambda x: (x
|
33
|
+
Fi=('event_type', lambda x: (x.isin(fenwick_events)).sum()),
|
34
|
+
Ci=('event_type', lambda x: (x.isin(fenwick_events+['blocked-shot'])).sum()),
|
16
35
|
xGi=('xG', 'sum'),
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
).reset_index().rename(columns={'event_player_1_id': 'ID', 'event_team_abbr': 'Team', 'season': 'Season', '
|
36
|
+
HF=('event_type',lambda x: (x=='hit').sum()),
|
37
|
+
Give=('event_type',lambda x: (x=='giveaway').sum()),
|
38
|
+
Take=('event_type',lambda x: (x=='takeaway').sum()),
|
39
|
+
Penl=('event_type',lambda x: (x=='penalty').sum()),
|
40
|
+
Penl2=('penalty_duration',lambda x: (x==2).sum()),
|
41
|
+
Penl5=('penalty_duration',lambda x: (x==5).sum()),
|
42
|
+
PIM=('penalty_duration','sum'),
|
43
|
+
FW=('event_type',lambda x: (x=='faceoff').sum())
|
44
|
+
).reset_index().rename(columns={'event_player_1_id': 'ID', 'event_team_abbr': 'Team', 'season': 'Season', 'game_id':'Game'})
|
26
45
|
)
|
27
46
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
47
|
+
#Second event player stats
|
48
|
+
ep2 = (
|
49
|
+
pbp.loc[(pbp['event_type'].isin(['goal','blocked-shot','hit','faceoff','penalty']))&~(pbp['description'].str.lower().str.contains('blocked by teammate',na=False))].groupby(raw_group_2).agg(
|
50
|
+
A1=('event_type',lambda x: (x=='goal').sum()),
|
51
|
+
HA=('event_type',lambda x: (x=='hit').sum()),
|
52
|
+
Draw=('event_type',lambda x: (x=='penalty').sum()),
|
53
|
+
FL=('event_type',lambda x: (x=='faceoff').sum()),
|
54
|
+
Block=('event_type',lambda x:(x=='blocked-shot').sum())
|
55
|
+
).reset_index().rename(columns={'event_player_2_id': 'ID', 'event_team_abbr_2': 'Team', 'season': 'Season', 'game_id':'Game'})
|
32
56
|
)
|
33
57
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
58
|
+
#Third event player stats
|
59
|
+
ep3 = (
|
60
|
+
pbp.loc[pbp['event_type'].isin(["goal"])].groupby(raw_group_3).agg(
|
61
|
+
A2=('event_type', 'count')
|
62
|
+
).reset_index().rename(columns={'event_player_3_id': 'ID', 'event_team_abbr': 'Team', 'season': 'Season', 'game_id':'Game'})
|
63
|
+
)
|
64
|
+
|
65
|
+
#Rush events
|
66
|
+
rush = (
|
67
|
+
pbp.loc[(pbp['event_type'].isin(fenwick_events))&(pbp['rush']>0)].groupby(raw_group_1).agg(
|
68
|
+
Rush=('event_type','count'),
|
69
|
+
Rush_G=('event_type',lambda x: (x == 'goal').sum()),
|
70
|
+
Rush_xG=('xG','sum')
|
71
|
+
).reset_index().rename(columns={'event_player_1_id': 'ID', 'event_team_abbr': 'Team', 'season': 'Season', 'game_id':'Game', 'Rush_G': 'Rush G', 'Rush_xG': 'Rush xG'})
|
38
72
|
)
|
39
|
-
|
40
|
-
indv = pd.merge(
|
41
|
-
indv = pd.merge(indv,
|
73
|
+
|
74
|
+
indv = pd.merge(ep1,ep2,how='outer',on=clean_group)
|
75
|
+
indv = pd.merge(indv,ep3,how='outer',on=clean_group)
|
76
|
+
indv = pd.merge(indv,rush,how='outer',on=clean_group)
|
42
77
|
|
43
78
|
#Shot Types
|
44
79
|
for type in shot_types:
|
45
80
|
shot = (
|
46
|
-
pbp.loc[(pbp['event_type'].isin(["goal", "shot-on-goal", "missed-shot"])&(pbp['shot_type']==type))].groupby(
|
81
|
+
pbp.loc[(pbp['event_type'].isin(["goal", "shot-on-goal", "missed-shot"])&(pbp['shot_type']==type))].groupby(raw_group_1).agg(
|
47
82
|
Gi=('event_type', lambda x: (x == "goal").sum()),
|
48
83
|
Fi=('event_type', lambda x: (x != "blocked-shot").sum()),
|
49
84
|
xGi=('xG', 'sum'),
|
50
|
-
).reset_index().rename(columns={'event_player_1_id': 'ID', 'event_team_abbr': 'Team', 'season': 'Season'})
|
85
|
+
).reset_index().rename(columns={'event_player_1_id': 'ID', 'event_team_abbr': 'Team', 'season': 'Season', 'game_id':'Game'})
|
51
86
|
)
|
52
87
|
|
53
88
|
shot = shot.rename(columns={
|
@@ -55,29 +90,43 @@ def calc_indv(pbp):
|
|
55
90
|
'Fi':f'{type.capitalize()}Fi',
|
56
91
|
'xGi':f'{type.capitalize()}xGi',
|
57
92
|
})
|
58
|
-
indv = pd.merge(indv,shot,how='outer',on=
|
93
|
+
indv = pd.merge(indv,shot,how='outer',on=clean_group)
|
59
94
|
|
60
|
-
indv[['Gi','A1','A2']] = indv[['Gi','A1','A2']].fillna(0)
|
95
|
+
indv[['Gi','A1','A2','Penl','Draw','FW','FL']] = indv[['Gi','A1','A2','Penl','Draw','FW','FL']].fillna(0)
|
61
96
|
|
62
97
|
indv['P1'] = indv['Gi']+indv['A1']
|
63
98
|
indv['P'] = indv['P1']+indv['A2']
|
64
99
|
indv['xGi/Fi'] = indv['xGi']/indv['Fi']
|
65
100
|
indv['Gi/xGi'] = indv['Gi']/indv['xGi']
|
66
101
|
indv['Fshi%'] = indv['Gi']/indv['Fi']
|
102
|
+
indv['F'] = indv['FW']+indv['FL']
|
103
|
+
indv['F%'] = indv['FW']/indv['F']
|
104
|
+
indv['PM%'] = indv['Take']/(indv['Give']+indv['Take'])
|
105
|
+
indv['HF%'] = indv['HF']/(indv['HF']+indv['HA'])
|
106
|
+
indv['PENL%'] = indv['Draw']/(indv['Draw']+indv['Penl'])
|
67
107
|
|
68
108
|
return indv
|
69
109
|
|
70
|
-
def calc_onice(pbp):
|
71
|
-
#
|
110
|
+
def calc_onice(pbp,game_strength,second_group):
|
111
|
+
#Convert player on-ice columns to vectors
|
72
112
|
pbp['home_on_ice'] = pbp['home_on_1_id'].astype(str) + ";" + pbp['home_on_2_id'].astype(str) + ";" + pbp['home_on_3_id'].astype(str) + ";" + pbp['home_on_4_id'].astype(str) + ";" + pbp['home_on_5_id'].astype(str) + ";" + pbp['home_on_6_id'].astype(str)
|
73
113
|
pbp['away_on_ice'] = pbp['away_on_1_id'].astype(str) + ";" + pbp['away_on_2_id'].astype(str) + ";" + pbp['away_on_3_id'].astype(str) + ";" + pbp['away_on_4_id'].astype(str) + ";" + pbp['away_on_5_id'].astype(str) + ";" + pbp['away_on_6_id'].astype(str)
|
74
114
|
|
75
|
-
#
|
115
|
+
#Remove NA players
|
76
116
|
pbp['home_on_ice'] = pbp['home_on_ice'].str.replace(';nan', '', regex=True)
|
77
117
|
pbp['away_on_ice'] = pbp['away_on_ice'].str.replace(';nan', '', regex=True)
|
78
|
-
|
79
|
-
def process_team_stats(df, on_ice_col, team_col, opp_col):
|
80
|
-
df = df[['season','game_id',
|
118
|
+
|
119
|
+
def process_team_stats(df, on_ice_col, team_col, opp_col, game_strength):
|
120
|
+
df = df[['season','game_id','strength_state','event_num', team_col, opp_col, 'event_type', 'event_team_venue','event_team_abbr', on_ice_col,'ids_on','shift_type','event_length','zone_code','xG']].copy()
|
121
|
+
|
122
|
+
#Flip strength state (when necessary) and filter by game strength if not "all"
|
123
|
+
if game_strength != "all":
|
124
|
+
if game_strength not in ['3v3','4v4','5v5']:
|
125
|
+
for strength in game_strength:
|
126
|
+
df['strength_state'] = np.where(np.logical_and(df['event_team_venue']==opp_col[0:4],df['strength_state']==strength[::-1]),strength,df['strength_state'])
|
127
|
+
|
128
|
+
df = df.loc[df['strength_state'].isin(game_strength)]
|
129
|
+
|
81
130
|
df[on_ice_col] = df[on_ice_col].str.split(';')
|
82
131
|
df = df.explode(on_ice_col)
|
83
132
|
df = df.rename(columns={on_ice_col: 'ID', 'season': 'Season'})
|
@@ -87,8 +136,13 @@ def calc_onice(pbp):
|
|
87
136
|
df['GA'] = np.where((df['event_type'] == "goal") & (df['event_team_abbr'] == df[opp_col]), 1, 0)
|
88
137
|
df['FF'] = np.where((df['event_type'].isin(fenwick_events)) & (df['event_team_abbr'] == df[team_col]), 1, 0)
|
89
138
|
df['FA'] = np.where((df['event_type'].isin(fenwick_events)) & (df['event_team_abbr'] == df[opp_col]), 1, 0)
|
139
|
+
df['CF'] = np.where((df['event_type'].isin(fenwick_events+['blocked-shot'])) & (df['event_team_abbr'] == df[team_col]), 1, 0)
|
140
|
+
df['CA'] = np.where((df['event_type'].isin(fenwick_events+['blocked-shot'])) & (df['event_team_abbr'] == df[opp_col]), 1, 0)
|
141
|
+
df['OZF'] = np.where((df['event_type']=='faceoff') & ((df['zone_code']=='O')&((df['event_team_abbr'] == df[team_col])) | (df['zone_code']=='D')&((df['event_team_abbr'] == df[opp_col]))), 1, 0)
|
142
|
+
df['NZF'] = np.where((df['zone_code']=='N') & (df['event_team_abbr']==df[team_col]),1,0)
|
143
|
+
df['DZF'] = np.where((df['event_type']=='faceoff') & ((df['zone_code']=='D')&((df['event_team_abbr'] == df[team_col])) | (df['zone_code']=='O')&((df['event_team_abbr'] == df[opp_col]))), 1, 0)
|
90
144
|
|
91
|
-
stats = df.groupby(['ID',team_col,'Season']).agg(
|
145
|
+
stats = df.groupby(['ID',team_col,'Season']+(['game_id'] if 'game_id' in second_group else [])).agg(
|
92
146
|
GP=('game_id','nunique'),
|
93
147
|
TOI=('event_length','sum'),
|
94
148
|
FF=('FF', 'sum'),
|
@@ -96,15 +150,20 @@ def calc_onice(pbp):
|
|
96
150
|
GF=('GF', 'sum'),
|
97
151
|
GA=('GA', 'sum'),
|
98
152
|
xGF=('xGF', 'sum'),
|
99
|
-
xGA=('xGA', 'sum')
|
153
|
+
xGA=('xGA', 'sum'),
|
154
|
+
CF=('CF','sum'),
|
155
|
+
CA=('CA','sum'),
|
156
|
+
OZF=('OZF','sum'),
|
157
|
+
NZF=('NZF','sum'),
|
158
|
+
DZF=('DZF','sum')
|
100
159
|
).reset_index()
|
101
160
|
|
102
|
-
return stats.rename(columns={team_col:"Team"})
|
161
|
+
return stats.rename(columns={team_col:"Team", 'game_id':'Game'})
|
103
162
|
|
104
|
-
home_stats = process_team_stats(pbp, 'home_on_ice', 'home_team_abbr', 'away_team_abbr')
|
105
|
-
away_stats = process_team_stats(pbp, 'away_on_ice', 'away_team_abbr', 'home_team_abbr')
|
163
|
+
home_stats = process_team_stats(pbp, 'home_on_ice', 'home_team_abbr', 'away_team_abbr',game_strength)
|
164
|
+
away_stats = process_team_stats(pbp, 'away_on_ice', 'away_team_abbr', 'home_team_abbr',game_strength)
|
106
165
|
|
107
|
-
onice_stats = pd.concat([home_stats,away_stats]).groupby(['ID','Team','Season']).agg(
|
166
|
+
onice_stats = pd.concat([home_stats,away_stats]).groupby(['ID','Team','Season']+(['Game'] if 'game_id' in second_group else [])).agg(
|
108
167
|
GP=('GP','sum'),
|
109
168
|
TOI=('TOI','sum'),
|
110
169
|
FF=('FF', 'sum'),
|
@@ -112,7 +171,12 @@ def calc_onice(pbp):
|
|
112
171
|
GF=('GF', 'sum'),
|
113
172
|
GA=('GA', 'sum'),
|
114
173
|
xGF=('xGF', 'sum'),
|
115
|
-
xGA=('xGA', 'sum')
|
174
|
+
xGA=('xGA', 'sum'),
|
175
|
+
CF=('CF','sum'),
|
176
|
+
CA=('CA','sum'),
|
177
|
+
OZF=('OZF','sum'),
|
178
|
+
NZF=('NZF','sum'),
|
179
|
+
DZF=('DZF','sum')
|
116
180
|
).reset_index()
|
117
181
|
|
118
182
|
onice_stats['xGF/FF'] = onice_stats['xGF']/onice_stats['FF']
|
@@ -121,26 +185,49 @@ def calc_onice(pbp):
|
|
121
185
|
onice_stats['xGA/FA'] = onice_stats['xGA']/onice_stats['FA']
|
122
186
|
onice_stats['GA/xGA'] = onice_stats['GA']/onice_stats['xGA']
|
123
187
|
onice_stats['FshA%'] = onice_stats['GA']/onice_stats['FA']
|
188
|
+
onice_stats['OZF%'] = onice_stats['OZF']/(onice_stats['OZF']+onice_stats['NZF']+onice_stats['DZF'])
|
189
|
+
onice_stats['NZF%'] = onice_stats['NZF']/(onice_stats['OZF']+onice_stats['NZF']+onice_stats['DZF'])
|
190
|
+
onice_stats['DZF%'] = onice_stats['DZF']/(onice_stats['OZF']+onice_stats['NZF']+onice_stats['DZF'])
|
124
191
|
|
125
192
|
return onice_stats
|
126
193
|
|
127
|
-
def calc_team(pbp):
|
194
|
+
def calc_team(pbp,game_strength,second_group):
|
128
195
|
teams = []
|
129
196
|
for team in [('away','home'),('home','away')]:
|
197
|
+
#Flip strength state (when necessary) and filter by game strength if not "all"
|
198
|
+
if game_strength != "all":
|
199
|
+
if game_strength not in ['3v3','4v4','5v5']:
|
200
|
+
for strength in game_strength:
|
201
|
+
pbp['strength_state'] = np.where(np.logical_and(pbp['event_team_venue']==team[1],pbp['strength_state']==strength[::-1]),strength,pbp['strength_state'])
|
202
|
+
|
203
|
+
pbp = pbp.loc[pbp['strength_state'].isin(game_strength)]
|
204
|
+
|
130
205
|
pbp['xGF'] = np.where(pbp['event_team_abbr'] == pbp[f'{team[0]}_team_abbr'], pbp['xG'], 0)
|
131
206
|
pbp['xGA'] = np.where(pbp['event_team_abbr'] == pbp[f'{team[1]}_team_abbr'], pbp['xG'], 0)
|
132
207
|
pbp['GF'] = np.where((pbp['event_type'] == "goal") & (pbp['event_team_abbr'] == pbp[f'{team[0]}_team_abbr']), 1, 0)
|
133
208
|
pbp['GA'] = np.where((pbp['event_type'] == "goal") & (pbp['event_team_abbr'] == pbp[f'{team[1]}_team_abbr']), 1, 0)
|
134
209
|
pbp['FF'] = np.where((pbp['event_type'].isin(fenwick_events)) & (pbp['event_team_abbr'] == pbp[f'{team[0]}_team_abbr']), 1, 0)
|
135
210
|
pbp['FA'] = np.where((pbp['event_type'].isin(fenwick_events)) & (pbp['event_team_abbr'] == pbp[f'{team[1]}_team_abbr']), 1, 0)
|
136
|
-
pbp['
|
137
|
-
pbp['
|
138
|
-
pbp['
|
139
|
-
pbp['
|
140
|
-
pbp['
|
141
|
-
pbp['
|
142
|
-
|
143
|
-
|
211
|
+
pbp['CF'] = np.where((pbp['event_type'].isin(fenwick_events+['blocked-shot'])) & (pbp['event_team_abbr'] == pbp[f'{team[0]}_team_abbr']), 1, 0)
|
212
|
+
pbp['CA'] = np.where((pbp['event_type'].isin(fenwick_events+['blocked-shot'])) & (pbp['event_team_abbr'] == pbp[f'{team[1]}_team_abbr']), 1, 0)
|
213
|
+
pbp['HF'] = np.where((pbp['event_type']=='hit') & (pbp['event_team_abbr'] == pbp[f'{team[0]}_team_abbr']), 1, 0)
|
214
|
+
pbp['HA'] = np.where((pbp['event_type']=='hit') & (pbp['event_team_abbr'] == pbp[f'{team[1]}_team_abbr']), 1, 0)
|
215
|
+
pbp['Penl'] = np.where((pbp['event_type']=='penalty') & (pbp['event_team_abbr'] == pbp[f'{team[0]}_team_abbr']), 1, 0)
|
216
|
+
pbp['Penl2'] = np.where((pbp['event_type']=='penalty') & (pbp['penalty_duration']==2) & (pbp['event_team_abbr'] == pbp[f'{team[0]}_team_abbr']), 1, 0)
|
217
|
+
pbp['Penl5'] = np.where((pbp['event_type']=='penalty') & (pbp['penalty_duration']==5) & (pbp['event_team_abbr'] == pbp[f'{team[0]}_team_abbr']), 1, 0)
|
218
|
+
pbp['PIM'] = np.where((pbp['event_team_abbr'] == pbp[f'{team[0]}_team_abbr']), pbp['penalty_duration'], 0)
|
219
|
+
pbp['Draw'] = np.where((pbp['event_type']=='penalty') & (pbp['event_team_abbr'] == pbp[f'{team[1]}_team_abbr']), 1, 0)
|
220
|
+
pbp['Give'] = np.where((pbp['event_type']=='giveaway') & (pbp['event_team_abbr'] == pbp[f'{team[0]}_team_abbr']), 1, 0)
|
221
|
+
pbp['Take'] = np.where((pbp['event_type']=='takeaway') & (pbp['event_team_abbr'] == pbp[f'{team[0]}_team_abbr']), 1, 0)
|
222
|
+
pbp['Block'] = pbp['CA'] - pbp['FA']
|
223
|
+
pbp['RushF'] = np.where((pbp['event_team_abbr'] == pbp[f'{team[0]}_team_abbr'])&(pbp['rush']>0), 1, 0)
|
224
|
+
pbp['RushA'] = np.where((pbp['event_team_abbr'] == pbp[f'{team[1]}_team_abbr'])&(pbp['rush']>0), 1, 0)
|
225
|
+
pbp['RushFxG'] = np.where((pbp['event_team_abbr'] == pbp[f'{team[0]}_team_abbr'])&(pbp['rush']>0), pbp['xG'], 0)
|
226
|
+
pbp['RushAxG'] = np.where((pbp['event_team_abbr'] == pbp[f'{team[1]}_team_abbr'])&(pbp['rush']>0), pbp['xG'], 0)
|
227
|
+
pbp['RushFG'] = np.where((pbp['event_type'] == "goal") & (pbp['event_team_abbr'] == pbp[f'{team[0]}_team_abbr'])&(pbp['rush']>0), 1, 0)
|
228
|
+
pbp['RushAG'] = np.where((pbp['event_type'] == "goal") & (pbp['event_team_abbr'] == pbp[f'{team[1]}_team_abbr'])&(pbp['rush']>0), 1, 0)
|
229
|
+
|
230
|
+
stats = pbp.groupby([f'{team[0]}_team_abbr']+second_group).agg(
|
144
231
|
GP=('game_id','nunique'),
|
145
232
|
TOI=('event_length','sum'),
|
146
233
|
FF=('FF', 'sum'),
|
@@ -149,16 +236,28 @@ def calc_team(pbp):
|
|
149
236
|
GA=('GA', 'sum'),
|
150
237
|
xGF=('xGF', 'sum'),
|
151
238
|
xGA=('xGA', 'sum'),
|
239
|
+
CF=('CF','sum'),
|
240
|
+
CA=('CA','sum'),
|
241
|
+
HF=('HF','sum'),
|
242
|
+
HA=('HA','sum'),
|
243
|
+
Penl=('Penl','sum'),
|
244
|
+
Penl2=('Penl2','sum'),
|
245
|
+
Penl5=('Penl5','sum'),
|
246
|
+
PIM=('PIM','sum'),
|
247
|
+
Draw=('Draw','sum'),
|
248
|
+
Give=('Give','sum'),
|
249
|
+
Take=('Take','sum'),
|
250
|
+
Block=('Block','sum'),
|
152
251
|
RushF=('RushF','sum'),
|
153
252
|
RushA=('RushA','sum'),
|
154
253
|
RushFxG=('RushFxG','sum'),
|
155
254
|
RushAxG=('RushAxG','sum'),
|
156
255
|
RushFG=('RushFG','sum'),
|
157
256
|
RushAG=('RushAG','sum'),
|
158
|
-
).reset_index().rename(columns={f'{team[0]}_team_abbr':"Team",'season':"Season"})
|
257
|
+
).reset_index().rename(columns={f'{team[0]}_team_abbr':"Team",'season':"Season",'game_id':'Game'})
|
159
258
|
teams.append(stats)
|
160
259
|
|
161
|
-
onice_stats = pd.concat(teams).groupby(['Team','Season']).agg(
|
260
|
+
onice_stats = pd.concat(teams).groupby(['Team','Season']+(['Game'] if 'game_id' in second_group else [])).agg(
|
162
261
|
GP=('GP','sum'),
|
163
262
|
TOI=('TOI','sum'),
|
164
263
|
FF=('FF', 'sum'),
|
@@ -167,6 +266,18 @@ def calc_team(pbp):
|
|
167
266
|
GA=('GA', 'sum'),
|
168
267
|
xGF=('xGF', 'sum'),
|
169
268
|
xGA=('xGA', 'sum'),
|
269
|
+
CF=('CF','sum'),
|
270
|
+
CA=('CA','sum'),
|
271
|
+
HF=('HF','sum'),
|
272
|
+
HA=('HA','sum'),
|
273
|
+
Penl=('Penl','sum'),
|
274
|
+
Penl2=('Penl2','sum'),
|
275
|
+
Penl5=('Penl5','sum'),
|
276
|
+
PIM=('PIM','sum'),
|
277
|
+
Draw=('Draw','sum'),
|
278
|
+
Give=('Give','sum'),
|
279
|
+
Take=('Take','sum'),
|
280
|
+
Block=('Block','sum'),
|
170
281
|
RushF=('RushF','sum'),
|
171
282
|
RushA=('RushA','sum'),
|
172
283
|
RushFxG=('RushFxG','sum'),
|
@@ -181,5 +292,83 @@ def calc_team(pbp):
|
|
181
292
|
onice_stats['xGA/FA'] = onice_stats['xGA']/onice_stats['FA']
|
182
293
|
onice_stats['GA/xGA'] = onice_stats['GA']/onice_stats['xGA']
|
183
294
|
onice_stats['FshA%'] = onice_stats['GA']/onice_stats['FA']
|
295
|
+
onice_stats['PM%'] = onice_stats['Take']/(onice_stats['Give']+onice_stats['Take'])
|
296
|
+
onice_stats['HF%'] = onice_stats['HF']/(onice_stats['HF']+onice_stats['HA'])
|
297
|
+
onice_stats['PENL%'] = onice_stats['Draw']/(onice_stats['Draw']+onice_stats['Penl'])
|
298
|
+
|
299
|
+
return onice_stats
|
300
|
+
|
301
|
+
def calc_goalie(pbp,game_strength,second_group):
|
302
|
+
teams=[]
|
303
|
+
for team in [('away','home'),('home','away')]:
|
304
|
+
#Flip strength state (when necessary) and filter by game strength if not "all"
|
305
|
+
if game_strength != "all":
|
306
|
+
if game_strength not in ['3v3','4v4','5v5']:
|
307
|
+
for strength in game_strength:
|
308
|
+
pbp['strength_state'] = np.where(np.logical_and(pbp['event_team_venue']==team[1],pbp['strength_state']==strength[::-1]),strength,pbp['strength_state'])
|
309
|
+
|
310
|
+
pbp = pbp.loc[pbp['strength_state'].isin(game_strength)]
|
311
|
+
|
312
|
+
pbp['xGF'] = np.where(pbp['event_team_abbr'] == pbp[f'{team[0]}_team_abbr'], pbp['xG'], 0)
|
313
|
+
pbp['xGA'] = np.where(pbp['event_team_abbr'] == pbp[f'{team[1]}_team_abbr'], pbp['xG'], 0)
|
314
|
+
pbp['GF'] = np.where((pbp['event_type'] == "goal") & (pbp['event_team_abbr'] == pbp[f'{team[0]}_team_abbr']), 1, 0)
|
315
|
+
pbp['GA'] = np.where((pbp['event_type'] == "goal") & (pbp['event_team_abbr'] == pbp[f'{team[1]}_team_abbr']), 1, 0)
|
316
|
+
pbp['FF'] = np.where((pbp['event_type'].isin(fenwick_events)) & (pbp['event_team_abbr'] == pbp[f'{team[0]}_team_abbr']), 1, 0)
|
317
|
+
pbp['FA'] = np.where((pbp['event_type'].isin(fenwick_events)) & (pbp['event_team_abbr'] == pbp[f'{team[1]}_team_abbr']), 1, 0)
|
318
|
+
pbp['CF'] = np.where((pbp['event_type'].isin(fenwick_events+['blocked-shot'])) & (pbp['event_team_abbr'] == pbp[f'{team[0]}_team_abbr']), 1, 0)
|
319
|
+
pbp['CA'] = np.where((pbp['event_type'].isin(fenwick_events+['blocked-shot'])) & (pbp['event_team_abbr'] == pbp[f'{team[1]}_team_abbr']), 1, 0)
|
320
|
+
pbp['RushF'] = np.where((pbp['event_team_abbr'] == pbp[f'{team[0]}_team_abbr'])&(pbp['rush']>0), 1, 0)
|
321
|
+
pbp['RushA'] = np.where((pbp['event_team_abbr'] == pbp[f'{team[1]}_team_abbr'])&(pbp['rush']>0), 1, 0)
|
322
|
+
pbp['RushFxG'] = np.where((pbp['event_team_abbr'] == pbp[f'{team[0]}_team_abbr'])&(pbp['rush']>0), pbp['xG'], 0)
|
323
|
+
pbp['RushAxG'] = np.where((pbp['event_team_abbr'] == pbp[f'{team[1]}_team_abbr'])&(pbp['rush']>0), pbp['xG'], 0)
|
324
|
+
pbp['RushFG'] = np.where((pbp['event_type'] == "goal") & (pbp['event_team_abbr'] == pbp[f'{team[0]}_team_abbr'])&(pbp['rush']>0), 1, 0)
|
325
|
+
pbp['RushAG'] = np.where((pbp['event_type'] == "goal") & (pbp['event_team_abbr'] == pbp[f'{team[1]}_team_abbr'])&(pbp['rush']>0), 1, 0)
|
184
326
|
|
185
|
-
|
327
|
+
stats = pbp.groupby([f'{team[0]}_goalie_id',f'{team[0]}_team_abbr']+second_group).agg(
|
328
|
+
GP=('game_id','nunique'),
|
329
|
+
TOI=('event_length','sum'),
|
330
|
+
FF=('FF', 'sum'),
|
331
|
+
FA=('FA', 'sum'),
|
332
|
+
GF=('GF', 'sum'),
|
333
|
+
GA=('GA', 'sum'),
|
334
|
+
xGF=('xGF', 'sum'),
|
335
|
+
xGA=('xGA', 'sum'),
|
336
|
+
CF=('CF','sum'),
|
337
|
+
CA=('CA','sum'),
|
338
|
+
RushF=('RushF','sum'),
|
339
|
+
RushA=('RushA','sum'),
|
340
|
+
RushFxG=('RushFxG','sum'),
|
341
|
+
RushAxG=('RushAxG','sum'),
|
342
|
+
RushFG=('RushFG','sum'),
|
343
|
+
RushAG=('RushAG','sum'),
|
344
|
+
).reset_index().rename(columns={f'{team[0]}_goalie_id':"ID",f'{team[0]}_team_abbr':"Team",'season':"Season",'game_id':'Game'})
|
345
|
+
teams.append(stats)
|
346
|
+
|
347
|
+
onice_stats = pd.concat(teams).groupby(['ID','Team','Season']+(['Game'] if 'game_id' in second_group else [])).agg(
|
348
|
+
GP=('GP','sum'),
|
349
|
+
TOI=('TOI','sum'),
|
350
|
+
FF=('FF', 'sum'),
|
351
|
+
FA=('FA', 'sum'),
|
352
|
+
GF=('GF', 'sum'),
|
353
|
+
GA=('GA', 'sum'),
|
354
|
+
xGF=('xGF', 'sum'),
|
355
|
+
xGA=('xGA', 'sum'),
|
356
|
+
CF=('CF','sum'),
|
357
|
+
CA=('CA','sum'),
|
358
|
+
RushF=('RushF','sum'),
|
359
|
+
RushA=('RushA','sum'),
|
360
|
+
RushFxG=('RushFxG','sum'),
|
361
|
+
RushAxG=('RushAxG','sum'),
|
362
|
+
RushFG=('RushFG','sum'),
|
363
|
+
RushAG=('RushAG','sum'),
|
364
|
+
).reset_index()
|
365
|
+
|
366
|
+
onice_stats['xGF/FF'] = onice_stats['xGF']/onice_stats['FF']
|
367
|
+
onice_stats['GF/xGF'] = onice_stats['GF']/onice_stats['xGF']
|
368
|
+
onice_stats['FshF%'] = onice_stats['GF']/onice_stats['FF']
|
369
|
+
onice_stats['xGA/FA'] = onice_stats['xGA']/onice_stats['FA']
|
370
|
+
onice_stats['GA/xGA'] = onice_stats['GA']/onice_stats['xGA']
|
371
|
+
onice_stats['FshA%'] = onice_stats['GA']/onice_stats['FA']
|
372
|
+
onice_stats['GSAx'] = onice_stats['xGA']-onice_stats['GA']
|
373
|
+
|
374
|
+
return onice_stats
|
wsba_hockey/tools/plotting.py
CHANGED
@@ -38,19 +38,16 @@ def wsba_rink(display_range='offense',rotation = 0):
|
|
38
38
|
despine=True
|
39
39
|
)
|
40
40
|
|
41
|
-
def prep_plot_data(pbp,events,strengths,marker_dict=event_markers
|
41
|
+
def prep_plot_data(pbp,events,strengths,marker_dict=event_markers):
|
42
42
|
try: pbp['xG']
|
43
43
|
except:
|
44
|
-
|
45
|
-
pbp = wsba_xG(pbp)
|
46
|
-
else:
|
47
|
-
pbp = moneypuck_xG(pbp)
|
44
|
+
pbp = wsba_xG(pbp)
|
48
45
|
pbp['xG'] = np.where(pbp['xG'].isna(),0,pbp['xG'])
|
49
46
|
|
50
47
|
pbp['WSBA'] = pbp['event_player_1_name']+pbp['season'].astype(str)+pbp['event_team_abbr']
|
51
48
|
|
52
|
-
pbp['x_plot'] = pbp['
|
53
|
-
pbp['y_plot'] = pbp['
|
49
|
+
pbp['x_plot'] = np.where(pbp['x']<0,-pbp['y_adj'],pbp['y_adj'])
|
50
|
+
pbp['y_plot'] = abs(pbp['x_adj'])
|
54
51
|
|
55
52
|
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)
|
56
53
|
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)
|
@@ -61,9 +58,7 @@ def prep_plot_data(pbp,events,strengths,marker_dict=event_markers,xg='moneypuck'
|
|
61
58
|
pbp['size'] = np.where(pbp['xG']<=0,40,pbp['xG']*400)
|
62
59
|
pbp['marker'] = pbp['event_type'].replace(marker_dict)
|
63
60
|
|
64
|
-
pbp = pbp.loc[(pbp['event_type'].isin(events))
|
65
|
-
(pbp['event_distance']<=89)&
|
66
|
-
(pbp['x_fixed']<=89)]
|
61
|
+
pbp = pbp.loc[(pbp['event_type'].isin(events))]
|
67
62
|
|
68
63
|
if strengths != 'all':
|
69
64
|
pbp = pbp.loc[(pbp['strength_state'].isin(strengths))]
|
@@ -81,9 +76,9 @@ def league_shots(pbp,events,strengths):
|
|
81
76
|
|
82
77
|
return xgoals_smooth
|
83
78
|
|
84
|
-
def plot_skater_shots(pbp, player, season, team, strengths, title = None, marker_dict=event_markers, onice='for', legend=False
|
79
|
+
def plot_skater_shots(pbp, player, season, team, strengths, title = None, marker_dict=event_markers, onice='for', legend=False):
|
85
80
|
shots = ['missed-shot','shot-on-goal','goal']
|
86
|
-
pbp = prep_plot_data(pbp,shots,strengths,marker_dict
|
81
|
+
pbp = prep_plot_data(pbp,shots,strengths,marker_dict)
|
87
82
|
pbp = pbp.loc[(pbp['season'].astype(str)==season)&((pbp['away_team_abbr']==team)|(pbp['home_team_abbr']==team))]
|
88
83
|
|
89
84
|
team_data = pd.read_csv('teaminfo/nhl_teaminfo.csv')
|
@@ -111,14 +106,14 @@ def plot_skater_shots(pbp, player, season, team, strengths, title = None, marker
|
|
111
106
|
|
112
107
|
return fig
|
113
108
|
|
114
|
-
def plot_game_events(pbp,game_id,events,strengths,marker_dict=event_markers,team_colors={'away':'secondary','home':'primary'},legend=False
|
115
|
-
pbp = prep_plot_data(pbp,events,strengths,marker_dict
|
116
|
-
pbp = pbp.loc[pbp['game_id'].astype(str)==game_id]
|
117
|
-
|
109
|
+
def plot_game_events(pbp,game_id,events,strengths,marker_dict=event_markers,team_colors={'away':'secondary','home':'primary'},legend=False):
|
110
|
+
pbp = prep_plot_data(pbp,events,strengths,marker_dict)
|
111
|
+
pbp = pbp.loc[pbp['game_id'].astype(str)==str(game_id)]
|
112
|
+
|
118
113
|
away_abbr = list(pbp['away_team_abbr'])[0]
|
119
114
|
home_abbr = list(pbp['home_team_abbr'])[0]
|
120
115
|
date = list(pbp['game_date'])[0]
|
121
|
-
season =
|
116
|
+
season = list(pbp['season'])[0]
|
122
117
|
|
123
118
|
team_data = pd.read_csv('teaminfo/nhl_teaminfo.csv')
|
124
119
|
team_info ={
|