wsba-hockey 1.1.1__py3-none-any.whl → 1.1.3__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/api/api/index.py +1 -1
- wsba_hockey/tools/plotting.py +1 -1
- wsba_hockey/tools/scraping.py +1 -1
- wsba_hockey/tools/xg_model.py +3 -3
- {wsba_hockey-1.1.1.dist-info → wsba_hockey-1.1.3.dist-info}/METADATA +1 -1
- {wsba_hockey-1.1.1.dist-info → wsba_hockey-1.1.3.dist-info}/RECORD +9 -21
- wsba_hockey/api/api/main.py +0 -4
- wsba_hockey/api/api/tools/__init__.py +0 -0
- wsba_hockey/api/api/tools/agg.py +0 -374
- wsba_hockey/api/api/tools/archive/old_scraping.py +0 -1104
- wsba_hockey/api/api/tools/plotting.py +0 -144
- wsba_hockey/api/api/tools/scraping.py +0 -1000
- wsba_hockey/api/api/tools/utils/__init__.py +0 -1
- wsba_hockey/api/api/tools/utils/config.py +0 -14
- wsba_hockey/api/api/tools/utils/save_pages.py +0 -133
- wsba_hockey/api/api/tools/utils/shared.py +0 -450
- wsba_hockey/api/api/tools/xg_model.py +0 -455
- wsba_hockey/api/api/wsba_main.py +0 -1213
- {wsba_hockey-1.1.1.dist-info → wsba_hockey-1.1.3.dist-info}/WHEEL +0 -0
- {wsba_hockey-1.1.1.dist-info → wsba_hockey-1.1.3.dist-info}/licenses/LICENSE +0 -0
- {wsba_hockey-1.1.1.dist-info → wsba_hockey-1.1.3.dist-info}/top_level.txt +0 -0
wsba_hockey/api/api/index.py
CHANGED
wsba_hockey/tools/plotting.py
CHANGED
@@ -6,7 +6,7 @@ from hockey_rink import NHLRink
|
|
6
6
|
from hockey_rink import CircularImage
|
7
7
|
from scipy.interpolate import griddata
|
8
8
|
from scipy.ndimage import gaussian_filter
|
9
|
-
from tools.xg_model import *
|
9
|
+
from wsba_hockey.tools.xg_model import *
|
10
10
|
|
11
11
|
### PLOTTING FUNCTIONS ###
|
12
12
|
# Provided in this file are basic plotting functions for the WSBA Hockey Python package. #
|
wsba_hockey/tools/scraping.py
CHANGED
wsba_hockey/tools/xg_model.py
CHANGED
@@ -4,8 +4,8 @@ import pandas as pd
|
|
4
4
|
import numpy as np
|
5
5
|
import xgboost as xgb
|
6
6
|
import scipy.sparse as sp
|
7
|
-
import wsba_main as wsba
|
8
|
-
import tools.scraping as scraping
|
7
|
+
import wsba_hockey.wsba_main as wsba
|
8
|
+
import wsba_hockey.tools.scraping as scraping
|
9
9
|
import matplotlib.pyplot as plt
|
10
10
|
from sklearn.calibration import calibration_curve
|
11
11
|
from sklearn.metrics import roc_curve, auc
|
@@ -118,7 +118,7 @@ def fix_players(pbp):
|
|
118
118
|
|
119
119
|
def prep_xG_data(data):
|
120
120
|
#Prep data for xG training and calculation
|
121
|
-
|
121
|
+
data = fix_players(data)
|
122
122
|
|
123
123
|
#Informal groupby
|
124
124
|
data = data.sort_values(by=['season','game_id','period','seconds_elapsed','event_num'])
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: wsba_hockey
|
3
|
-
Version: 1.1.
|
3
|
+
Version: 1.1.3
|
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/
|
@@ -2,19 +2,7 @@ wsba_hockey/__init__.py,sha256=yfr8z5PA503iaIQv30ngancwT_WnsuK-tZETKlHcI0M,377
|
|
2
2
|
wsba_hockey/data_pipelines.py,sha256=wjyxw1ikv4N3kmfTuHxdHj7_W5bz0wAM-DIgxvJVg2s,10852
|
3
3
|
wsba_hockey/workspace.py,sha256=ECScWNqkmx8SDoxTtZYZtM1K1_oX-wQSXXsb_1Bjca4,2014
|
4
4
|
wsba_hockey/wsba_main.py,sha256=c8KEXBpjHHEadMMStMRXsNYqbvtoYdZbmOl8_FBmHQg,53761
|
5
|
-
wsba_hockey/api/api/index.py,sha256=
|
6
|
-
wsba_hockey/api/api/main.py,sha256=QaObP7kSFr-zjJL549sSWv7LtqHq5mBqvpyjjs2nVn8,87
|
7
|
-
wsba_hockey/api/api/wsba_main.py,sha256=zrQFsy-AqW1GENm-gOm9VCZNrK4TAINHRadbPi156k8,53757
|
8
|
-
wsba_hockey/api/api/tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
9
|
-
wsba_hockey/api/api/tools/agg.py,sha256=SYZDykUQFygDfRaazlBMKcfs_1eYP7GTJNpUnNKHH-8,21409
|
10
|
-
wsba_hockey/api/api/tools/plotting.py,sha256=3x59nyqMV6pIoL548m17dfDbc39ZkMTj4EjEdJVG4uo,6017
|
11
|
-
wsba_hockey/api/api/tools/scraping.py,sha256=i6Br0XCwq4EL1Nq9z9sTzISGQ6kPZ5EYnASVJMD9lyk,45645
|
12
|
-
wsba_hockey/api/api/tools/xg_model.py,sha256=nOr_2RBijLgPmJ0TTs4wbSsORYmRqWCKRjLKDm7sAhI,18342
|
13
|
-
wsba_hockey/api/api/tools/archive/old_scraping.py,sha256=hEjMI1RtfeZnf0RBiJFI38oXkLZ3WofeH5xqcF4pzgM,49585
|
14
|
-
wsba_hockey/api/api/tools/utils/__init__.py,sha256=vccXhOtzARoR99fmEWU1OEI3qCIdQ9Z42AlRA_BUhrs,114
|
15
|
-
wsba_hockey/api/api/tools/utils/config.py,sha256=D3Uk05-YTyrhfReMTTLfNI3HN_rON2uo_CDE9oER3Lg,351
|
16
|
-
wsba_hockey/api/api/tools/utils/save_pages.py,sha256=CsyL_0n-b-4pJoUauwU3HpnCO6n69-RlBMJQBd_qGDc,4979
|
17
|
-
wsba_hockey/api/api/tools/utils/shared.py,sha256=dH_JwZfia5fib8rksy5sW-mBp0pluBPvw37Vdr8Kap0,14211
|
5
|
+
wsba_hockey/api/api/index.py,sha256=b2QEOJ72TxOCZT9KsHvIPPow0RwLRCOUyeyrIrSqb6o,5926
|
18
6
|
wsba_hockey/evidence/weakside-breakout/node_modules/duckdb/vendor.py,sha256=lmu0TB0rIYkAuV9-csFJgW-1hJojso_-EZpEoorUUKM,4949
|
19
7
|
wsba_hockey/evidence/weakside-breakout/node_modules/flatted/python/flatted.py,sha256=ke8FuEflns-WlphCcQ9CC0qJqWqX3zEEuak74o6rgE8,3879
|
20
8
|
wsba_hockey/evidence/weakside-breakout/node_modules/flatted/python/test.py,sha256=uTOn6HJd7KeY_PTRvvufv60dmvON3KWp3nnqACj8IlA,2129
|
@@ -140,16 +128,16 @@ wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/team_heatmaps
|
|
140
128
|
wsba_hockey/flask/app.py,sha256=J51iA65h9xyJfLgdH0h2sVSbfIR7xgGd2Oy8bJsmpAk,1873
|
141
129
|
wsba_hockey/tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
142
130
|
wsba_hockey/tools/agg.py,sha256=SYZDykUQFygDfRaazlBMKcfs_1eYP7GTJNpUnNKHH-8,21409
|
143
|
-
wsba_hockey/tools/plotting.py,sha256=
|
144
|
-
wsba_hockey/tools/scraping.py,sha256=
|
145
|
-
wsba_hockey/tools/xg_model.py,sha256=
|
131
|
+
wsba_hockey/tools/plotting.py,sha256=81hBaM7tcwUNB4-tovPn7QreOUz6B2NuI_SR4-djVSk,6029
|
132
|
+
wsba_hockey/tools/scraping.py,sha256=y6vvotniMaGS6-bNg0Vct1gUN3gAsKEy5FLXGkgi1w0,45657
|
133
|
+
wsba_hockey/tools/xg_model.py,sha256=nOr_2RBijLgPmJ0TTs4wbSsORYmRqWCKRjLKDm7sAhI,18342
|
146
134
|
wsba_hockey/tools/archive/old_scraping.py,sha256=hEjMI1RtfeZnf0RBiJFI38oXkLZ3WofeH5xqcF4pzgM,49585
|
147
135
|
wsba_hockey/tools/utils/__init__.py,sha256=vccXhOtzARoR99fmEWU1OEI3qCIdQ9Z42AlRA_BUhrs,114
|
148
136
|
wsba_hockey/tools/utils/config.py,sha256=D3Uk05-YTyrhfReMTTLfNI3HN_rON2uo_CDE9oER3Lg,351
|
149
137
|
wsba_hockey/tools/utils/save_pages.py,sha256=CsyL_0n-b-4pJoUauwU3HpnCO6n69-RlBMJQBd_qGDc,4979
|
150
138
|
wsba_hockey/tools/utils/shared.py,sha256=dH_JwZfia5fib8rksy5sW-mBp0pluBPvw37Vdr8Kap0,14211
|
151
|
-
wsba_hockey-1.1.
|
152
|
-
wsba_hockey-1.1.
|
153
|
-
wsba_hockey-1.1.
|
154
|
-
wsba_hockey-1.1.
|
155
|
-
wsba_hockey-1.1.
|
139
|
+
wsba_hockey-1.1.3.dist-info/licenses/LICENSE,sha256=Nr_Um1Pd5FQJTWWgm7maZArdtYMbDhzXYSwyJIZDGik,1114
|
140
|
+
wsba_hockey-1.1.3.dist-info/METADATA,sha256=pGBQxsZfILi46XgUEfLDk3Q5TEadxe3pJNxCDGFZVpk,3542
|
141
|
+
wsba_hockey-1.1.3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
142
|
+
wsba_hockey-1.1.3.dist-info/top_level.txt,sha256=acU7s3x-RZC1zGiqCOmO0g267iqCg34lzIfdmYxxGmQ,12
|
143
|
+
wsba_hockey-1.1.3.dist-info/RECORD,,
|
wsba_hockey/api/api/main.py
DELETED
File without changes
|
wsba_hockey/api/api/tools/agg.py
DELETED
@@ -1,374 +0,0 @@
|
|
1
|
-
import pandas as pd
|
2
|
-
import numpy as np
|
3
|
-
from wsba_hockey.tools.xg_model import *
|
4
|
-
|
5
|
-
## AGGREGATE FUNCTIONS ##
|
6
|
-
|
7
|
-
## GLOBAL VARIABLES ##
|
8
|
-
shot_types = ['wrist','deflected','tip-in','slap','backhand','snap','wrap-around','poke','bat','cradle','between-legs']
|
9
|
-
fenwick_events = ['missed-shot','shot-on-goal','goal']
|
10
|
-
|
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(
|
32
|
-
Gi=('event_type', lambda x: (x == "goal").sum()),
|
33
|
-
Fi=('event_type', lambda x: (x.isin(fenwick_events)).sum()),
|
34
|
-
Ci=('event_type', lambda x: (x.isin(fenwick_events+['blocked-shot'])).sum()),
|
35
|
-
xGi=('xG', 'sum'),
|
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'})
|
45
|
-
)
|
46
|
-
|
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'})
|
56
|
-
)
|
57
|
-
|
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'})
|
72
|
-
)
|
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)
|
77
|
-
|
78
|
-
#Shot Types
|
79
|
-
for type in shot_types:
|
80
|
-
shot = (
|
81
|
-
pbp.loc[(pbp['event_type'].isin(["goal", "shot-on-goal", "missed-shot"])&(pbp['shot_type']==type))].groupby(raw_group_1).agg(
|
82
|
-
Gi=('event_type', lambda x: (x == "goal").sum()),
|
83
|
-
Fi=('event_type', lambda x: (x != "blocked-shot").sum()),
|
84
|
-
xGi=('xG', 'sum'),
|
85
|
-
).reset_index().rename(columns={'event_player_1_id': 'ID', 'event_team_abbr': 'Team', 'season': 'Season', 'game_id':'Game'})
|
86
|
-
)
|
87
|
-
|
88
|
-
shot = shot.rename(columns={
|
89
|
-
'Gi':f'{type.capitalize()}Gi',
|
90
|
-
'Fi':f'{type.capitalize()}Fi',
|
91
|
-
'xGi':f'{type.capitalize()}xGi',
|
92
|
-
})
|
93
|
-
indv = pd.merge(indv,shot,how='outer',on=clean_group)
|
94
|
-
|
95
|
-
indv[['Gi','A1','A2','Penl','Draw','FW','FL']] = indv[['Gi','A1','A2','Penl','Draw','FW','FL']].fillna(0)
|
96
|
-
|
97
|
-
indv['P1'] = indv['Gi']+indv['A1']
|
98
|
-
indv['P'] = indv['P1']+indv['A2']
|
99
|
-
indv['xGi/Fi'] = indv['xGi']/indv['Fi']
|
100
|
-
indv['Gi/xGi'] = indv['Gi']/indv['xGi']
|
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'])
|
107
|
-
|
108
|
-
return indv
|
109
|
-
|
110
|
-
def calc_onice(pbp,game_strength,second_group):
|
111
|
-
#Convert player on-ice columns to vectors
|
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)
|
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)
|
114
|
-
|
115
|
-
#Remove NA players
|
116
|
-
pbp['home_on_ice'] = pbp['home_on_ice'].str.replace(';nan', '', regex=True)
|
117
|
-
pbp['away_on_ice'] = pbp['away_on_ice'].str.replace(';nan', '', regex=True)
|
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
|
-
|
130
|
-
df[on_ice_col] = df[on_ice_col].str.split(';')
|
131
|
-
df = df.explode(on_ice_col)
|
132
|
-
df = df.rename(columns={on_ice_col: 'ID', 'season': 'Season'})
|
133
|
-
df['xGF'] = np.where(df['event_team_abbr'] == df[team_col], df['xG'], 0)
|
134
|
-
df['xGA'] = np.where(df['event_team_abbr'] == df[opp_col], df['xG'], 0)
|
135
|
-
df['GF'] = np.where((df['event_type'] == "goal") & (df['event_team_abbr'] == df[team_col]), 1, 0)
|
136
|
-
df['GA'] = np.where((df['event_type'] == "goal") & (df['event_team_abbr'] == df[opp_col]), 1, 0)
|
137
|
-
df['FF'] = np.where((df['event_type'].isin(fenwick_events)) & (df['event_team_abbr'] == df[team_col]), 1, 0)
|
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)
|
144
|
-
|
145
|
-
stats = df.groupby(['ID',team_col,'Season']+(['game_id'] if 'game_id' in second_group else [])).agg(
|
146
|
-
GP=('game_id','nunique'),
|
147
|
-
TOI=('event_length','sum'),
|
148
|
-
FF=('FF', 'sum'),
|
149
|
-
FA=('FA', 'sum'),
|
150
|
-
GF=('GF', 'sum'),
|
151
|
-
GA=('GA', 'sum'),
|
152
|
-
xGF=('xGF', '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')
|
159
|
-
).reset_index()
|
160
|
-
|
161
|
-
return stats.rename(columns={team_col:"Team", 'game_id':'Game'})
|
162
|
-
|
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)
|
165
|
-
|
166
|
-
onice_stats = pd.concat([home_stats,away_stats]).groupby(['ID','Team','Season']+(['Game'] if 'game_id' in second_group else [])).agg(
|
167
|
-
GP=('GP','sum'),
|
168
|
-
TOI=('TOI','sum'),
|
169
|
-
FF=('FF', 'sum'),
|
170
|
-
FA=('FA', 'sum'),
|
171
|
-
GF=('GF', 'sum'),
|
172
|
-
GA=('GA', 'sum'),
|
173
|
-
xGF=('xGF', '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')
|
180
|
-
).reset_index()
|
181
|
-
|
182
|
-
onice_stats['xGF/FF'] = onice_stats['xGF']/onice_stats['FF']
|
183
|
-
onice_stats['GF/xGF'] = onice_stats['GF']/onice_stats['xGF']
|
184
|
-
onice_stats['FshF%'] = onice_stats['GF']/onice_stats['FF']
|
185
|
-
onice_stats['xGA/FA'] = onice_stats['xGA']/onice_stats['FA']
|
186
|
-
onice_stats['GA/xGA'] = onice_stats['GA']/onice_stats['xGA']
|
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'])
|
191
|
-
|
192
|
-
return onice_stats
|
193
|
-
|
194
|
-
def calc_team(pbp,game_strength,second_group):
|
195
|
-
teams = []
|
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
|
-
|
205
|
-
pbp['xGF'] = np.where(pbp['event_team_abbr'] == pbp[f'{team[0]}_team_abbr'], pbp['xG'], 0)
|
206
|
-
pbp['xGA'] = np.where(pbp['event_team_abbr'] == pbp[f'{team[1]}_team_abbr'], pbp['xG'], 0)
|
207
|
-
pbp['GF'] = np.where((pbp['event_type'] == "goal") & (pbp['event_team_abbr'] == pbp[f'{team[0]}_team_abbr']), 1, 0)
|
208
|
-
pbp['GA'] = np.where((pbp['event_type'] == "goal") & (pbp['event_team_abbr'] == pbp[f'{team[1]}_team_abbr']), 1, 0)
|
209
|
-
pbp['FF'] = np.where((pbp['event_type'].isin(fenwick_events)) & (pbp['event_team_abbr'] == pbp[f'{team[0]}_team_abbr']), 1, 0)
|
210
|
-
pbp['FA'] = np.where((pbp['event_type'].isin(fenwick_events)) & (pbp['event_team_abbr'] == pbp[f'{team[1]}_team_abbr']), 1, 0)
|
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(
|
231
|
-
GP=('game_id','nunique'),
|
232
|
-
TOI=('event_length','sum'),
|
233
|
-
FF=('FF', 'sum'),
|
234
|
-
FA=('FA', 'sum'),
|
235
|
-
GF=('GF', 'sum'),
|
236
|
-
GA=('GA', 'sum'),
|
237
|
-
xGF=('xGF', 'sum'),
|
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'),
|
251
|
-
RushF=('RushF','sum'),
|
252
|
-
RushA=('RushA','sum'),
|
253
|
-
RushFxG=('RushFxG','sum'),
|
254
|
-
RushAxG=('RushAxG','sum'),
|
255
|
-
RushFG=('RushFG','sum'),
|
256
|
-
RushAG=('RushAG','sum'),
|
257
|
-
).reset_index().rename(columns={f'{team[0]}_team_abbr':"Team",'season':"Season",'game_id':'Game'})
|
258
|
-
teams.append(stats)
|
259
|
-
|
260
|
-
onice_stats = pd.concat(teams).groupby(['Team','Season']+(['Game'] if 'game_id' in second_group else [])).agg(
|
261
|
-
GP=('GP','sum'),
|
262
|
-
TOI=('TOI','sum'),
|
263
|
-
FF=('FF', 'sum'),
|
264
|
-
FA=('FA', 'sum'),
|
265
|
-
GF=('GF', 'sum'),
|
266
|
-
GA=('GA', 'sum'),
|
267
|
-
xGF=('xGF', 'sum'),
|
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'),
|
281
|
-
RushF=('RushF','sum'),
|
282
|
-
RushA=('RushA','sum'),
|
283
|
-
RushFxG=('RushFxG','sum'),
|
284
|
-
RushAxG=('RushAxG','sum'),
|
285
|
-
RushFG=('RushFG','sum'),
|
286
|
-
RushAG=('RushAG','sum'),
|
287
|
-
).reset_index()
|
288
|
-
|
289
|
-
onice_stats['xGF/FF'] = onice_stats['xGF']/onice_stats['FF']
|
290
|
-
onice_stats['GF/xGF'] = onice_stats['GF']/onice_stats['xGF']
|
291
|
-
onice_stats['FshF%'] = onice_stats['GF']/onice_stats['FF']
|
292
|
-
onice_stats['xGA/FA'] = onice_stats['xGA']/onice_stats['FA']
|
293
|
-
onice_stats['GA/xGA'] = onice_stats['GA']/onice_stats['xGA']
|
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)
|
326
|
-
|
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
|