wsba-hockey 1.1.3__py3-none-any.whl → 1.1.6__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 +68 -28
- wsba_hockey/data_pipelines.py +3 -2
- wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/duos/app.py +210 -0
- wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/duos/calc.py +163 -0
- wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/line-combos/app.py +245 -0
- wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/line-combos/plot.py +275 -0
- wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/line-combos/rink_plot.py +245 -0
- wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/matchups/app.py +2 -2
- wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/pbp/app.py +1 -0
- wsba_hockey/tools/agg.py +30 -0
- wsba_hockey/tools/scraping.py +168 -4
- wsba_hockey/workspace.py +4 -24
- wsba_hockey/wsba_main.py +52 -51
- {wsba_hockey-1.1.3.dist-info → wsba_hockey-1.1.6.dist-info}/METADATA +9 -5
- {wsba_hockey-1.1.3.dist-info → wsba_hockey-1.1.6.dist-info}/RECORD +18 -13
- {wsba_hockey-1.1.3.dist-info → wsba_hockey-1.1.6.dist-info}/WHEEL +0 -0
- {wsba_hockey-1.1.3.dist-info → wsba_hockey-1.1.6.dist-info}/licenses/LICENSE +0 -0
- {wsba_hockey-1.1.3.dist-info → wsba_hockey-1.1.6.dist-info}/top_level.txt +0 -0
wsba_hockey/wsba_main.py
CHANGED
@@ -4,16 +4,16 @@ import requests as rs
|
|
4
4
|
import pandas as pd
|
5
5
|
import time
|
6
6
|
from datetime import datetime, timedelta, date
|
7
|
-
from .tools.scraping import *
|
8
|
-
from .tools.xg_model import *
|
9
|
-
from .tools.agg import *
|
10
|
-
from .tools.plotting import *
|
7
|
+
from wsba_hockey.tools.scraping import *
|
8
|
+
from wsba_hockey.tools.xg_model import *
|
9
|
+
from wsba_hockey.tools.agg import *
|
10
|
+
from wsba_hockey.tools.plotting import *
|
11
11
|
|
12
12
|
### WSBA HOCKEY ###
|
13
13
|
## Provided below are all integral functions in the WSBA Hockey Python package. ##
|
14
14
|
|
15
15
|
## GLOBAL VARIABLES ##
|
16
|
-
|
16
|
+
SEASONS = [
|
17
17
|
'20072008',
|
18
18
|
'20082009',
|
19
19
|
'20092010',
|
@@ -34,7 +34,7 @@ seasons = [
|
|
34
34
|
'20242025'
|
35
35
|
]
|
36
36
|
|
37
|
-
|
37
|
+
CONVERT_SEASONS = {'2007': '20072008',
|
38
38
|
'2008': '20082009',
|
39
39
|
'2009': '20092010',
|
40
40
|
'2010': '20102011',
|
@@ -53,17 +53,17 @@ convert_seasons = {'2007': '20072008',
|
|
53
53
|
'2023': '20232024',
|
54
54
|
'2024': '20242025'}
|
55
55
|
|
56
|
-
|
56
|
+
CONVERT_TEAM_ABBR = {'L.A':'LAK',
|
57
57
|
'N.J':'NJD',
|
58
58
|
'S.J':'SJS',
|
59
59
|
'T.B':'TBL',
|
60
60
|
'PHX':'ARI'}
|
61
61
|
|
62
|
-
|
62
|
+
PER_SIXTY = ['Fi','xGi','Gi','A1','A2','P1','P','Si','OZF','NZF','DZF','FF','FA','xGF','xGA','GF','GA','SF','SA','CF','CA','HF','HA','Give','Take','Penl','Penl2','Penl5','Draw','Block','GSAx']
|
63
63
|
|
64
64
|
#Some games in the API are specifically known to cause errors in scraping.
|
65
65
|
#This list is updated as frequently as necessary
|
66
|
-
|
66
|
+
KNOWN_PROBS = {
|
67
67
|
'2007020011':'Missing shifts data for game between Chicago and Minnesota.',
|
68
68
|
'2007021178':'Game between the Bruins and Sabres is missing data after the second period, for some reason.',
|
69
69
|
'2008020259':'HTML data is completely missing for this game.',
|
@@ -79,11 +79,11 @@ known_probs = {
|
|
79
79
|
'2019020876':'Due to the frightening collapse of Blues defensemen Jay Bouwmeester, a game on February 2nd, 2020 between the Ducks and Blues was postponed. \nWhen the game resumed, Ducks defensemen Hampus Lindholm, who assisted on a goal in the inital game, did not play in the resumed match.'
|
80
80
|
}
|
81
81
|
|
82
|
-
|
82
|
+
SHOT_TYPES = ['wrist','deflected','tip-in','slap','backhand','snap','wrap-around','poke','bat','cradle','between-legs']
|
83
83
|
|
84
|
-
|
84
|
+
NEW = 2024
|
85
85
|
|
86
|
-
|
86
|
+
STANDINGS_END = {
|
87
87
|
'20072008':'04-06',
|
88
88
|
'20082009':'04-12',
|
89
89
|
'20092010':'04-11',
|
@@ -104,12 +104,12 @@ standings_end = {
|
|
104
104
|
'20242025':'04-17'
|
105
105
|
}
|
106
106
|
|
107
|
-
|
107
|
+
EVENTS = ['faceoff','hit','giveaway','takeaway','blocked-shot','missed-shot','shot-on-goal','goal','penalty']
|
108
108
|
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
109
|
+
DIR = os.path.dirname(os.path.realpath(__file__))
|
110
|
+
SCHEDULE_PATH = os.path.join(DIR,'tools\\schedule\\schedule.csv')
|
111
|
+
INFO_PATH = os.path.join(DIR,'tools\\teaminfo\\nhl_teaminfo.csv')
|
112
|
+
DEFAULT_ROSTER = os.path.join(DIR,'tools\\rosters\\nhl_rosters.csv')
|
113
113
|
|
114
114
|
## SCRAPE FUNCTIONS ##
|
115
115
|
def nhl_scrape_game(game_ids,split_shifts = False, remove = ['period-start','period-end','challenge','stoppage','shootout-complete','game-end'],verbose = False, sources = False, errors = False):
|
@@ -189,8 +189,8 @@ def nhl_scrape_game(game_ids,split_shifts = False, remove = ['period-start','per
|
|
189
189
|
except:
|
190
190
|
#Games such as the all-star game and pre-season games will incur this error
|
191
191
|
#Other games have known problems
|
192
|
-
if game_id in
|
193
|
-
print(f"\nGame {game_id} has a known problem: {
|
192
|
+
if game_id in KNOWN_PROBS.keys():
|
193
|
+
print(f"\nGame {game_id} has a known problem: {KNOWN_PROBS[game_id]}")
|
194
194
|
else:
|
195
195
|
print(f"\nUnable to scrape game {game_id}. Ensure the ID is properly inputted and formatted.")
|
196
196
|
|
@@ -302,7 +302,7 @@ def nhl_scrape_schedule(season,start = "09-01", end = "08-01"):
|
|
302
302
|
#Return: specificed schedule data
|
303
303
|
return df
|
304
304
|
|
305
|
-
def nhl_scrape_season(season,split_shifts = False, season_types = [2,3], remove = ['period-start','period-end','game-end','challenge','stoppage'], start = "09-01", end = "08-01", local=False, local_path =
|
305
|
+
def nhl_scrape_season(season,split_shifts = False, season_types = [2,3], remove = ['period-start','period-end','game-end','challenge','stoppage'], start = "09-01", end = "08-01", local=False, local_path = SCHEDULE_PATH, verbose = False, sources = False, errors = False):
|
306
306
|
#Given season, scrape all play-by-play occuring within the season
|
307
307
|
# param 'season' - NHL season to scrape
|
308
308
|
# param 'split_shifts' - boolean which splits pbp and shift events if true
|
@@ -382,7 +382,7 @@ def nhl_scrape_standings(arg = "now", season_type = 2):
|
|
382
382
|
#arg param is ignored when set to "now" if season_type param is 3
|
383
383
|
if season_type == 3:
|
384
384
|
if arg == "now":
|
385
|
-
arg =
|
385
|
+
arg = NEW
|
386
386
|
|
387
387
|
print(f"Scraping playoff bracket for date: {arg}")
|
388
388
|
api = f"https://api-web.nhle.com/v1/playoff-bracket/{arg}"
|
@@ -394,12 +394,12 @@ def nhl_scrape_standings(arg = "now", season_type = 2):
|
|
394
394
|
else:
|
395
395
|
if arg == "now":
|
396
396
|
print("Scraping standings as of now...")
|
397
|
-
elif arg in
|
397
|
+
elif arg in SEASONS:
|
398
398
|
print(f'Scraping standings for season: {arg}')
|
399
399
|
else:
|
400
400
|
print(f"Scraping standings for date: {arg}")
|
401
401
|
|
402
|
-
api = f"https://api-web.nhle.com/v1/standings/{arg[4:8]}-{
|
402
|
+
api = f"https://api-web.nhle.com/v1/standings/{arg[4:8]}-{STANDINGS_END[arg]}"
|
403
403
|
data = rs.get(api).json()['standings']
|
404
404
|
|
405
405
|
return pd.json_normalize(data)
|
@@ -687,7 +687,7 @@ def nhl_shooting_impacts(agg,type):
|
|
687
687
|
pos[f'{group[0]}-FNI-T'] = (pos[f'{group[0]}-FNI']/60)*pos['TOI']
|
688
688
|
|
689
689
|
#Rank per 60 stats
|
690
|
-
for stat in
|
690
|
+
for stat in PER_SIXTY[11:len(PER_SIXTY)]:
|
691
691
|
pos[f'{stat}/60-P'] = pos[f'{stat}/60'].rank(pct=True)
|
692
692
|
|
693
693
|
#Flip percentiles for against stats
|
@@ -788,7 +788,7 @@ def nhl_shooting_impacts(agg,type):
|
|
788
788
|
pos['RushesFi'] = pos['RushFi/60'].rank(pct=True)
|
789
789
|
|
790
790
|
#Rank per 60 stats
|
791
|
-
for stat in
|
791
|
+
for stat in PER_SIXTY:
|
792
792
|
pos[f'{stat}/60-P'] = pos[f'{stat}/60'].rank(pct=True)
|
793
793
|
|
794
794
|
#Flip percentiles for against stats
|
@@ -868,7 +868,7 @@ def nhl_shooting_impacts(agg,type):
|
|
868
868
|
#Return: skater stats with shooting impacts
|
869
869
|
return df
|
870
870
|
|
871
|
-
def nhl_calculate_stats(pbp,type,season_types,game_strength,split_game=False,roster_path=
|
871
|
+
def nhl_calculate_stats(pbp,type,season_types,game_strength,split_game=False,roster_path=DEFAULT_ROSTER,shot_impact=False):
|
872
872
|
#Given play-by-play, seasonal information, game_strength, rosters, and xG model, return aggregated stats
|
873
873
|
# param 'pbp' - play-by-play dataframe
|
874
874
|
# param 'type' - type of stats to calculate ('skater', 'goalie', or 'team')
|
@@ -911,10 +911,11 @@ def nhl_calculate_stats(pbp,type,season_types,game_strength,split_game=False,ros
|
|
911
911
|
complete['TOI'] = complete['TOI']/60
|
912
912
|
|
913
913
|
#Add per 60 stats
|
914
|
-
for stat in ['FF','FA','xGF','xGA','GF','GA','CF','CA','GSAx']:
|
914
|
+
for stat in ['FF','FA','xGF','xGA','GF','GA','SF','SA','CF','CA','GSAx']:
|
915
915
|
complete[f'{stat}/60'] = (complete[stat]/complete['TOI'])*60
|
916
916
|
|
917
917
|
complete['GF%'] = complete['GF']/(complete['GF']+complete['GA'])
|
918
|
+
complete['SF%'] = complete['SF']/(complete['SF']+complete['SA'])
|
918
919
|
complete['xGF%'] = complete['xGF']/(complete['xGF']+complete['xGA'])
|
919
920
|
complete['FF%'] = complete['FF']/(complete['FF']+complete['FA'])
|
920
921
|
complete['CF%'] = complete['CF']/(complete['CF']+complete['CA'])
|
@@ -953,10 +954,6 @@ def nhl_calculate_stats(pbp,type,season_types,game_strength,split_game=False,ros
|
|
953
954
|
#Find player headshot
|
954
955
|
complete['Headshot'] = 'https://assets.nhle.com/mugs/nhl/'+complete['Season'].astype(str)+'/'+complete['Team']+'/'+complete['ID'].astype(int).astype(str)+'.png'
|
955
956
|
|
956
|
-
end = time.perf_counter()
|
957
|
-
length = end-start
|
958
|
-
print(f'...finished in {(length if length <60 else length/60):.2f} {'seconds' if length <60 else 'minutes'}.')
|
959
|
-
|
960
957
|
head = ['Goalie','ID','Game'] if 'Game' in complete.columns else ['Goalie','ID']
|
961
958
|
complete = complete[head+[
|
962
959
|
"Season","Team",'WSBA',
|
@@ -964,12 +961,12 @@ def nhl_calculate_stats(pbp,type,season_types,game_strength,split_game=False,ros
|
|
964
961
|
'Height (in)','Weight (lbs)',
|
965
962
|
'Birthday','Age','Nationality',
|
966
963
|
'GP','TOI',
|
967
|
-
"GF","FF","xGF","xGF/FF","GF/xGF","FshF%",
|
968
|
-
"GA","FA","xGA","xGA/FA","GA/xGA","FshA%",
|
964
|
+
"GF","SF","FF","xGF","xGF/FF","GF/xGF","ShF%","FshF%",
|
965
|
+
"GA","SA","FA","xGA","xGA/FA","GA/xGA","ShA%","FshA%",
|
969
966
|
'CF','CA',
|
970
967
|
'GSAx',
|
971
968
|
'RushF','RushA','RushFxG','RushAxG','RushFG','RushAG'
|
972
|
-
]+[f'{stat}/60' for stat in ['FF','FA','xGF','xGA','GF','GA','CF','CA','GSAx']]]
|
969
|
+
]+[f'{stat}/60' for stat in ['FF','FA','xGF','xGA','GF','GA','SF','SA','CF','CA','GSAx']]]
|
973
970
|
|
974
971
|
#Apply shot impacts if necessary
|
975
972
|
if shot_impact:
|
@@ -991,10 +988,11 @@ def nhl_calculate_stats(pbp,type,season_types,game_strength,split_game=False,ros
|
|
991
988
|
complete['TOI'] = complete['TOI']/60
|
992
989
|
|
993
990
|
#Add per 60 stats
|
994
|
-
for stat in
|
991
|
+
for stat in PER_SIXTY[11:len(PER_SIXTY)]:
|
995
992
|
complete[f'{stat}/60'] = (complete[stat]/complete['TOI'])*60
|
996
993
|
|
997
994
|
complete['GF%'] = complete['GF']/(complete['GF']+complete['GA'])
|
995
|
+
complete['SF%'] = complete['SF']/(complete['SF']+complete['SA'])
|
998
996
|
complete['xGF%'] = complete['xGF']/(complete['xGF']+complete['xGA'])
|
999
997
|
complete['FF%'] = complete['FF']/(complete['FF']+complete['FA'])
|
1000
998
|
complete['CF%'] = complete['CF']/(complete['CF']+complete['CA'])
|
@@ -1003,16 +1001,17 @@ def nhl_calculate_stats(pbp,type,season_types,game_strength,split_game=False,ros
|
|
1003
1001
|
complete = complete[head+[
|
1004
1002
|
'Season','WSBA',
|
1005
1003
|
'GP','TOI',
|
1006
|
-
"GF","FF","xGF","xGF/FF","GF/xGF","FshF%",
|
1007
|
-
"GA","FA","xGA","xGA/FA","GA/xGA","FshA%",
|
1004
|
+
"GF","SF","FF","xGF","xGF/FF","GF/xGF","ShF%","FshF%",
|
1005
|
+
"GA","SA","FA","xGA","xGA/FA","GA/xGA","ShA%","FshA%",
|
1008
1006
|
'CF','CA',
|
1009
|
-
'GF%','FF%','xGF%','CF%',
|
1007
|
+
'GF%','SF%','FF%','xGF%','CF%',
|
1010
1008
|
'HF','HA','HF%',
|
1011
1009
|
'Penl','Penl2','Penl5','PIM','Draw','PENL%',
|
1012
1010
|
'Give','Take','PM%',
|
1013
1011
|
'Block',
|
1014
|
-
'RushF','RushA','RushFxG','RushAxG','RushFG','RushAG'
|
1015
|
-
|
1012
|
+
'RushF','RushA','RushFxG','RushAxG','RushFG','RushAG',
|
1013
|
+
'GSAx'
|
1014
|
+
]+[f'{stat}/60' for stat in PER_SIXTY[11:len(PER_SIXTY)]]]
|
1016
1015
|
#Apply shot impacts if necessary
|
1017
1016
|
if shot_impact:
|
1018
1017
|
complete = nhl_shooting_impacts(complete,'team')
|
@@ -1038,6 +1037,7 @@ def nhl_calculate_stats(pbp,type,season_types,game_strength,split_game=False,ros
|
|
1038
1037
|
complete['FC%'] = complete['Fi']/complete['FF']
|
1039
1038
|
complete['xGC%'] = complete['xGi']/complete['xGF']
|
1040
1039
|
complete['GF%'] = complete['GF']/(complete['GF']+complete['GA'])
|
1040
|
+
complete['SF%'] = complete['SF']/(complete['SF']+complete['SA'])
|
1041
1041
|
complete['xGF%'] = complete['xGF']/(complete['xGF']+complete['xGA'])
|
1042
1042
|
complete['FF%'] = complete['FF']/(complete['FF']+complete['FA'])
|
1043
1043
|
complete['CF%'] = complete['CF']/(complete['CF']+complete['CA'])
|
@@ -1082,13 +1082,13 @@ def nhl_calculate_stats(pbp,type,season_types,game_strength,split_game=False,ros
|
|
1082
1082
|
complete['WSBA'] = complete['Player']+complete['Season'].astype(str)+complete['Team']
|
1083
1083
|
|
1084
1084
|
#Add per 60 stats
|
1085
|
-
for stat in
|
1085
|
+
for stat in PER_SIXTY:
|
1086
1086
|
complete[f'{stat}/60'] = (complete[stat]/complete['TOI'])*60
|
1087
1087
|
|
1088
1088
|
#Shot Type Metrics
|
1089
1089
|
type_metrics = []
|
1090
1090
|
for type in shot_types:
|
1091
|
-
for stat in
|
1091
|
+
for stat in PER_SIXTY[:3]:
|
1092
1092
|
type_metrics.append(f'{type.capitalize()}{stat}')
|
1093
1093
|
|
1094
1094
|
head = ['Player','ID','Game'] if 'Game' in complete.columns else ['Player','ID']
|
@@ -1098,11 +1098,11 @@ def nhl_calculate_stats(pbp,type,season_types,game_strength,split_game=False,ros
|
|
1098
1098
|
'Height (in)','Weight (lbs)',
|
1099
1099
|
'Birthday','Age','Nationality',
|
1100
1100
|
'GP','TOI',
|
1101
|
-
"Gi","A1","A2",'P1','P',
|
1101
|
+
"Gi","A1","A2",'P1','P','Si','Shi%',
|
1102
1102
|
'Give','Take','PM%','HF','HA','HF%',
|
1103
1103
|
"Fi","xGi",'xGi/Fi',"Gi/xGi","Fshi%",
|
1104
|
-
"GF","FF","xGF","xGF/FF","GF/xGF","FshF%",
|
1105
|
-
"GA","FA","xGA","xGA/FA","GA/xGA","FshA%",
|
1104
|
+
"GF","SF","FF","xGF","xGF/FF","GF/xGF","ShF%","FshF%",
|
1105
|
+
"GA","SA","FA","xGA","xGA/FA","GA/xGA","ShA%","FshA%",
|
1106
1106
|
'Ci','CF','CA','CF%',
|
1107
1107
|
'FF%','xGF%','GF%',
|
1108
1108
|
'Rush',"Rush xG",'Rush G',"GC%","AC%","GI%","FC%","xGC%",
|
@@ -1112,7 +1112,8 @@ def nhl_calculate_stats(pbp,type,season_types,game_strength,split_game=False,ros
|
|
1112
1112
|
'Block',
|
1113
1113
|
'OZF','NZF','DZF',
|
1114
1114
|
'OZF%','NZF%','DZF%',
|
1115
|
-
|
1115
|
+
'GSAx'
|
1116
|
+
]+[f'{stat}/60' for stat in PER_SIXTY]+type_metrics].fillna(0).sort_values(['Player','Season','Team','ID'])
|
1116
1117
|
|
1117
1118
|
#Apply shot impacts if necessary (Note: this will remove skaters with fewer than 150 minutes of TOI due to the shot impact TOI rule)
|
1118
1119
|
if shot_impact:
|
@@ -1176,7 +1177,7 @@ def repo_load_rosters(seasons = []):
|
|
1176
1177
|
#Returns roster data from repository
|
1177
1178
|
# param 'seasons' - list of seasons to include
|
1178
1179
|
|
1179
|
-
data = pd.read_csv(
|
1180
|
+
data = pd.read_csv(DEFAULT_ROSTER)
|
1180
1181
|
if len(seasons)>0:
|
1181
1182
|
data = data.loc[data['season'].isin(seasons)]
|
1182
1183
|
|
@@ -1186,7 +1187,7 @@ def repo_load_schedule(seasons = []):
|
|
1186
1187
|
#Returns schedule data from repository
|
1187
1188
|
# param 'seasons' - list of seasons to include
|
1188
1189
|
|
1189
|
-
data = pd.read_csv(
|
1190
|
+
data = pd.read_csv(SCHEDULE_PATH)
|
1190
1191
|
if len(seasons)>0:
|
1191
1192
|
data = data.loc[data['season'].isin(seasons)]
|
1192
1193
|
|
@@ -1195,7 +1196,7 @@ def repo_load_schedule(seasons = []):
|
|
1195
1196
|
def repo_load_teaminfo():
|
1196
1197
|
#Returns team data from repository
|
1197
1198
|
|
1198
|
-
return pd.read_csv(
|
1199
|
+
return pd.read_csv(INFO_PATH)
|
1199
1200
|
|
1200
1201
|
def repo_load_pbp(seasons = []):
|
1201
1202
|
#Returns play-by-play data from repository
|
@@ -1203,11 +1204,11 @@ def repo_load_pbp(seasons = []):
|
|
1203
1204
|
|
1204
1205
|
#Add parquet to total
|
1205
1206
|
print(f'Loading play-by-play from the following seasons: {seasons}...')
|
1206
|
-
dfs = [pd.read_parquet(f"https://weakside-breakout.s3.us-east-2.amazonaws.com/pbp/{season}.parquet") for season in seasons]
|
1207
|
+
dfs = [pd.read_parquet(f"https://weakside-breakout.s3.us-east-2.amazonaws.com/pbp/parquet/nhl_pbp_{season}.parquet") for season in seasons]
|
1207
1208
|
|
1208
1209
|
return pd.concat(dfs)
|
1209
1210
|
|
1210
1211
|
def repo_load_seasons():
|
1211
1212
|
#List of available seasons to scrape
|
1212
1213
|
|
1213
|
-
return
|
1214
|
+
return SEASONS
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: wsba_hockey
|
3
|
-
Version: 1.1.
|
3
|
+
Version: 1.1.6
|
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/
|
@@ -64,12 +64,18 @@ wsba.nhl_scrape_prospects('BOS')
|
|
64
64
|
|
65
65
|
|
66
66
|
## DATA ANALYTICS
|
67
|
-
### Expected Goals
|
67
|
+
### Expected Goals
|
68
|
+
```python
|
69
|
+
pbp = wsba.nhl_scrape_game(['2024020918'],split_shifts=False,remove=['game-end'])
|
70
|
+
pbp = wsba.nhl_apply_xG(pbp)
|
71
|
+
```
|
72
|
+
|
68
73
|
### Goal Impacts and Shot Analysis
|
74
|
+
|
69
75
|
### Stat Aggregation
|
70
76
|
```python
|
71
77
|
pbp = wsba.nhl_scrape_season('20232024',remove=[], local = True)
|
72
|
-
wsba.nhl_calculate_stats(pbp,'skater',[2],['5v5','4v4','3v3'],
|
78
|
+
wsba.nhl_calculate_stats(pbp,'skater',[2],['5v5','4v4','3v3'],shot_impact = True)
|
73
79
|
```
|
74
80
|
### Shot Plotting (Plots, Heatmaps, etc.)
|
75
81
|
```python
|
@@ -105,6 +111,4 @@ Dan Morse - Creator of the hockeyR package; another important inspiration and mo
|
|
105
111
|
|
106
112
|
Patrick Bacon - Creator of TopDownHockey package
|
107
113
|
|
108
|
-
MoneyPuck - Source of available xG data in the package
|
109
|
-
|
110
114
|
Anyone in the NHL Public Analytics community who has stuck around and supported WeakSide Breakout Analysis hockey.
|
@@ -1,8 +1,8 @@
|
|
1
1
|
wsba_hockey/__init__.py,sha256=yfr8z5PA503iaIQv30ngancwT_WnsuK-tZETKlHcI0M,377
|
2
|
-
wsba_hockey/data_pipelines.py,sha256=
|
3
|
-
wsba_hockey/workspace.py,sha256=
|
4
|
-
wsba_hockey/wsba_main.py,sha256=
|
5
|
-
wsba_hockey/api/api/index.py,sha256=
|
2
|
+
wsba_hockey/data_pipelines.py,sha256=SITapG3nbea6-_EsXujMW2JBQxtRaQ33XMcE6ohn2Ko,10853
|
3
|
+
wsba_hockey/workspace.py,sha256=MwuyqyLW0dHNa06WEm60RkvbFoCn8LBXhnki66V-ttY,954
|
4
|
+
wsba_hockey/wsba_main.py,sha256=Ucies8d27gWtzf8xprnu7hEcqGGHvOza8HCE0O80X-s,54031
|
5
|
+
wsba_hockey/api/api/index.py,sha256=tABWg5cYCY-fPaNJ6W_bMJKEYrjn93YGy84VlkHzIXA,6853
|
6
6
|
wsba_hockey/evidence/weakside-breakout/node_modules/duckdb/vendor.py,sha256=lmu0TB0rIYkAuV9-csFJgW-1hJojso_-EZpEoorUUKM,4949
|
7
7
|
wsba_hockey/evidence/weakside-breakout/node_modules/flatted/python/flatted.py,sha256=ke8FuEflns-WlphCcQ9CC0qJqWqX3zEEuak74o6rgE8,3879
|
8
8
|
wsba_hockey/evidence/weakside-breakout/node_modules/flatted/python/test.py,sha256=uTOn6HJd7KeY_PTRvvufv60dmvON3KWp3nnqACj8IlA,2129
|
@@ -105,6 +105,8 @@ wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gy
|
|
105
105
|
wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/tools/pretty_sln.py,sha256=b_Fxm-SXUCPL3Tix4EyNwZNmQ-zkeRIFFmuL0R5wFhw,5482
|
106
106
|
wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/gyp/tools/pretty_vcproj.py,sha256=AwQrxK1F-jhjsbbT35XQjrvWNbc3IBFaKXoJogqMh_o,10633
|
107
107
|
wsba_hockey/evidence/weakside-breakout/node_modules/sqlite3/node_modules/node-gyp/test/fixtures/test-charmap.py,sha256=5raXzaQnO2eJnrlFtlDtWftryhZX7Fj0amFW3hdSnhE,547
|
108
|
+
wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/duos/app.py,sha256=PBdVi5qnR3Ye_dNjgqxmh5LIe6Tu_yu9-gebaaQnTfA,7947
|
109
|
+
wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/duos/calc.py,sha256=5T_TselP85ofTwf0inl3P7dtyRcosWg5ngUUL95jzLw,8789
|
108
110
|
wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/game_stats/app.py,sha256=P3vDaWyuij-DXlwk6XJ0aiAjrfs-NHi5hmngk-c9r8U,12704
|
109
111
|
wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/game_stats/name_fix.py,sha256=v7IN4JWrudeFuIsBdjLLlHsr9wU65jYi9-34pI_ZpoM,1488
|
110
112
|
wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/goalie/app.py,sha256=f5uwSvNKbtud91e7B17zC0HbPnYIvUgnShhdJZCOtkE,3820
|
@@ -113,10 +115,13 @@ wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/goalie/rink_p
|
|
113
115
|
wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/heatmaps/app.py,sha256=XDoZ6-uTgT1vCAOjJ8KjW3r7T0eNDfShGScDxY95HyU,4255
|
114
116
|
wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/heatmaps/plot.py,sha256=QERvb9I_OJPhrz84Omsf9Mq6JjaECark_ql1KfWha-I,4648
|
115
117
|
wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/heatmaps/rink_plot.py,sha256=RB_csrnTxlFR4OyFEhZXbHDSR3dP-KgME0xGBR2JE-4,11994
|
116
|
-
wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/
|
118
|
+
wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/line-combos/app.py,sha256=V9tcLkASOpvlnYNYwjYhxi5CgL1S8NUBmbnYcWjBSQ0,9457
|
119
|
+
wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/line-combos/plot.py,sha256=r-kPrlup8WrfKs5-Q0RGnLmF0hCOy7zWA_uKDvGy18o,14552
|
120
|
+
wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/line-combos/rink_plot.py,sha256=RB_csrnTxlFR4OyFEhZXbHDSR3dP-KgME0xGBR2JE-4,11994
|
121
|
+
wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/matchups/app.py,sha256=dRpnCLE9G2H7VOCBgHUOfEmoruEkUcnS2qhyiV54dQ8,6136
|
117
122
|
wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/matchups/plot.py,sha256=t3XRT88L0lh5jE-PSSboLZZ-Yg_u8L4gzJh-egWiRcY,3935
|
118
123
|
wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/matchups/rink_plot.py,sha256=RB_csrnTxlFR4OyFEhZXbHDSR3dP-KgME0xGBR2JE-4,11994
|
119
|
-
wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/pbp/app.py,sha256=
|
124
|
+
wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/pbp/app.py,sha256=hbMBjctovACO6KXswvb6gsN8AwQCOtT0BHHKR_EGBQM,13841
|
120
125
|
wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/pbp/plot.py,sha256=zfUTSic2M1AfXufvLFDTxxvpqQXw0RzwwQTGxALjjSw,2779
|
121
126
|
wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/pbp/rink_plot.py,sha256=RB_csrnTxlFR4OyFEhZXbHDSR3dP-KgME0xGBR2JE-4,11994
|
122
127
|
wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/skater/app.py,sha256=fNGWRHgqZr2G_QgACzh1l93ob-ugik1F9Wnq-sowWKU,4308
|
@@ -127,17 +132,17 @@ wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/team_heatmaps
|
|
127
132
|
wsba_hockey/evidence/weakside-breakout/wsba_nhl_apps/wsba_nhl_apps/team_heatmaps/rink_plot.py,sha256=RB_csrnTxlFR4OyFEhZXbHDSR3dP-KgME0xGBR2JE-4,11994
|
128
133
|
wsba_hockey/flask/app.py,sha256=J51iA65h9xyJfLgdH0h2sVSbfIR7xgGd2Oy8bJsmpAk,1873
|
129
134
|
wsba_hockey/tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
130
|
-
wsba_hockey/tools/agg.py,sha256=
|
135
|
+
wsba_hockey/tools/agg.py,sha256=OkIYd-ApvGVYe2JJLOI21jnDIN5LH8nkeH7eo0reWFI,23364
|
131
136
|
wsba_hockey/tools/plotting.py,sha256=81hBaM7tcwUNB4-tovPn7QreOUz6B2NuI_SR4-djVSk,6029
|
132
|
-
wsba_hockey/tools/scraping.py,sha256=
|
137
|
+
wsba_hockey/tools/scraping.py,sha256=h6C016U0qmNQpHWMh7Xvn3ud57zKzRbRQ06Odl-rC_I,52573
|
133
138
|
wsba_hockey/tools/xg_model.py,sha256=nOr_2RBijLgPmJ0TTs4wbSsORYmRqWCKRjLKDm7sAhI,18342
|
134
139
|
wsba_hockey/tools/archive/old_scraping.py,sha256=hEjMI1RtfeZnf0RBiJFI38oXkLZ3WofeH5xqcF4pzgM,49585
|
135
140
|
wsba_hockey/tools/utils/__init__.py,sha256=vccXhOtzARoR99fmEWU1OEI3qCIdQ9Z42AlRA_BUhrs,114
|
136
141
|
wsba_hockey/tools/utils/config.py,sha256=D3Uk05-YTyrhfReMTTLfNI3HN_rON2uo_CDE9oER3Lg,351
|
137
142
|
wsba_hockey/tools/utils/save_pages.py,sha256=CsyL_0n-b-4pJoUauwU3HpnCO6n69-RlBMJQBd_qGDc,4979
|
138
143
|
wsba_hockey/tools/utils/shared.py,sha256=dH_JwZfia5fib8rksy5sW-mBp0pluBPvw37Vdr8Kap0,14211
|
139
|
-
wsba_hockey-1.1.
|
140
|
-
wsba_hockey-1.1.
|
141
|
-
wsba_hockey-1.1.
|
142
|
-
wsba_hockey-1.1.
|
143
|
-
wsba_hockey-1.1.
|
144
|
+
wsba_hockey-1.1.6.dist-info/licenses/LICENSE,sha256=Nr_Um1Pd5FQJTWWgm7maZArdtYMbDhzXYSwyJIZDGik,1114
|
145
|
+
wsba_hockey-1.1.6.dist-info/METADATA,sha256=2CLs8qTA1iS8P7ToF4My86KkMRrt5zYoX9ynbQTS4zk,3566
|
146
|
+
wsba_hockey-1.1.6.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
147
|
+
wsba_hockey-1.1.6.dist-info/top_level.txt,sha256=acU7s3x-RZC1zGiqCOmO0g267iqCg34lzIfdmYxxGmQ,12
|
148
|
+
wsba_hockey-1.1.6.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|