patrickramos commited on
Commit
a504793
·
1 Parent(s): 3eaff33

Add OFFB%, IFFB%, and AIR%

Browse files
Files changed (3) hide show
  1. pitch_leaderboard.py +3 -3
  2. player_team_leaderboard.py +6 -6
  3. stats.py +12 -6
pitch_leaderboard.py CHANGED
@@ -10,9 +10,9 @@ from stats import compute_pitch_stats, filter_data_by_date_and_game_kind
10
  from convert import ball_kind, ball_kind_to_color, get_text_color_from_color, team_names_short_to_color, get_text_color_from_team
11
  from plotting import stat_cmap
12
 
13
- STATS = ['Count', 'Usage', 'Avg Velo', 'Max Velo', 'Swing%', 'Z-Swing%', 'Chase%', 'Contact%', 'Z-Contact%', 'O-Contact%', 'SwStr%', 'Whiff%', 'CSW%', 'Strike%', 'Ball%', 'F-Str%', 'PAR%', 'GB%', 'FB%', 'LD%', 'Zone%', 'Arm%', 'Glove%', 'High%', 'Low%', 'MM%', 'Behind%']
14
- PCT_STATS = ['Usage', 'Swing%', 'Z-Swing%', 'Chase%', 'Contact%', 'Z-Contact%', 'O-Contact%', 'SwStr%', 'Whiff%', 'CSW%', 'Strike%', 'Ball%', 'F-Str%', 'PAR%', 'GB%', 'FB%', 'LD%', 'Zone%', 'Arm%', 'Glove%', 'High%', 'Low%', 'MM%', 'Behind%']
15
- STATS_WITH_PCTLS = ['Swing%', 'Z-Swing%', 'Chase%', 'Contact%', 'Z-Contact%', 'O-Contact%', 'SwStr%', 'Whiff%', 'CSW%', 'Strike%', 'Ball%', 'F-Str%', 'PAR%', 'GB%', 'FB%', 'LD%', 'Zone%']
16
  COLUMNS = ['Pitcher', 'Team', 'Throws', 'Pitch', 'Pitch (General)'] + STATS
17
 
18
  PITCH_TYPES = [pitch_type for pitch_type in ball_kind.values() if pitch_type != '-']
 
10
  from convert import ball_kind, ball_kind_to_color, get_text_color_from_color, team_names_short_to_color, get_text_color_from_team
11
  from plotting import stat_cmap
12
 
13
+ STATS = ['Count', 'Usage', 'Avg Velo', 'Max Velo', 'Swing%', 'Z-Swing%', 'Chase%', 'Contact%', 'Z-Contact%', 'O-Contact%', 'SwStr%', 'Whiff%', 'CSW%', 'Strike%', 'Ball%', 'F-Str%', 'PAR%', 'GB%', 'FB%', 'LD%', 'OFFB%', 'IFFB%', 'AIR%', 'Zone%', 'Arm%', 'Glove%', 'High%', 'Low%', 'MM%', 'Behind%']
14
+ PCT_STATS = ['Usage', 'Swing%', 'Z-Swing%', 'Chase%', 'Contact%', 'Z-Contact%', 'O-Contact%', 'SwStr%', 'Whiff%', 'CSW%', 'Strike%', 'Ball%', 'F-Str%', 'PAR%', 'GB%', 'FB%', 'LD%', 'OFFB%', 'IFFB%', 'AIR%', 'Zone%', 'Arm%', 'Glove%', 'High%', 'Low%', 'MM%', 'Behind%']
15
+ STATS_WITH_PCTLS = ['Swing%', 'Z-Swing%', 'Chase%', 'Contact%', 'Z-Contact%', 'O-Contact%', 'SwStr%', 'Whiff%', 'CSW%', 'Strike%', 'Ball%', 'F-Str%', 'PAR%', 'GB%', 'FB%', 'LD%', 'OFFB%', 'IFFB%', 'AIR%', 'Zone%']
16
  COLUMNS = ['Pitcher', 'Team', 'Throws', 'Pitch', 'Pitch (General)'] + STATS
17
 
18
  PITCH_TYPES = [pitch_type for pitch_type in ball_kind.values() if pitch_type != '-']
player_team_leaderboard.py CHANGED
@@ -57,15 +57,15 @@ def create_player_team_leaderboard_app(player_team_type):
57
 
58
  # stats
59
  if pitching:
60
- pct_stats = ['K%', 'BB%', 'Swing%', 'Z-Swing%', 'Chase%', 'Contact%', 'Z-Contact%', 'O-Contact%', 'SwStr%', 'Whiff%', 'CSW%', 'Strike%', 'Ball%', 'F-Str%', 'PAR%', 'GB%', 'FB%', 'LD%', 'Zone%', 'Arm%', 'Glove%', 'High%', 'Low%', 'MM%', 'Behind%']
61
- stats_with_pctls = ['FB Velo', 'K%', 'BB%', 'Swing%', 'Z-Swing%', 'Chase%', 'Contact%', 'Z-Contact%', 'O-Contact%', 'SwStr%', 'Whiff%', 'CSW%', 'Strike%', 'F-Str%', 'PAR%', 'Ball%', 'GB%', 'FB%', 'LD%', 'Zone%', 'Behind%']
62
- cols = ['Pitcher', 'Team', 'Throws', 'IP', 'TBF', 'FB Velo', 'K%', 'BB%', 'Swing%', 'Z-Swing%', 'Chase%', 'Contact%', 'Z-Contact%', 'O-Contact%', 'SwStr%', 'Whiff%', 'CSW%', 'Strike%', 'Ball%', 'F-Str%', 'PAR%', 'GB%', 'FB%', 'LD%', 'Zone%', 'Arm%', 'Glove%', 'High%', 'Low%', 'MM%', 'Behind%']
63
  if team:
64
  cols = [col for col in cols if col not in ('Pitcher', 'Throws')]
65
  else:
66
- pct_stats = ['K%', 'BB%', 'Swing%', 'Z-Swing%', 'Chase%', 'Contact%', 'Z-Contact%', 'O-Contact%', 'SwStr%', 'Whiff%', 'CSW%', 'GB%', 'FB%', 'LD%', 'Zone%', 'Arm%', 'Glove%', 'High%', 'Low%', 'MM%']
67
- stats_with_pctls = ['K%', 'BB%', 'Swing%', 'Z-Swing%', 'Chase%', 'Contact%', 'Z-Contact%', 'O-Contact%', 'SwStr%', 'Whiff%', 'CSW%', 'GB%', 'FB%', 'LD%', 'Zone%'] # , 'OBP']
68
- cols = ['Batter', 'Team', 'Bats', 'PA', 'K%', 'BB%', 'Swing%', 'Z-Swing%', 'Chase%', 'Contact%', 'Z-Contact%', 'O-Contact%', 'SwStr%', 'Whiff%', 'CSW%', 'GB%', 'FB%', 'LD%']#, 'AB', 'H', 'BB', 'HBP', 'SF', 'OBP']
69
  if team:
70
  cols = [col for col in cols if col not in ('Batter', 'Bats')]
71
 
 
57
 
58
  # stats
59
  if pitching:
60
+ pct_stats = ['K%', 'BB%', 'Swing%', 'Z-Swing%', 'Chase%', 'Contact%', 'Z-Contact%', 'O-Contact%', 'SwStr%', 'Whiff%', 'CSW%', 'Strike%', 'Ball%', 'F-Str%', 'PAR%', 'GB%', 'FB%', 'LD%', 'OFFB%', 'IFFB%', 'AIR%', 'Zone%', 'Arm%', 'Glove%', 'High%', 'Low%', 'MM%', 'Behind%']
61
+ stats_with_pctls = ['FB Velo', 'K%', 'BB%', 'Swing%', 'Z-Swing%', 'Chase%', 'Contact%', 'Z-Contact%', 'O-Contact%', 'SwStr%', 'Whiff%', 'CSW%', 'Strike%', 'F-Str%', 'PAR%', 'Ball%', 'GB%', 'FB%', 'LD%', 'OFFB%', 'IFFB%', 'AIR%', 'Zone%', 'Behind%']
62
+ cols = ['Pitcher', 'Team', 'Throws', 'IP', 'TBF', 'FB Velo', 'K%', 'BB%', 'Swing%', 'Z-Swing%', 'Chase%', 'Contact%', 'Z-Contact%', 'O-Contact%', 'SwStr%', 'Whiff%', 'CSW%', 'Strike%', 'Ball%', 'F-Str%', 'PAR%', 'GB%', 'FB%', 'LD%', 'OFFB%', 'IFFB%', 'AIR%', 'Zone%', 'Arm%', 'Glove%', 'High%', 'Low%', 'MM%', 'Behind%']
63
  if team:
64
  cols = [col for col in cols if col not in ('Pitcher', 'Throws')]
65
  else:
66
+ pct_stats = ['K%', 'BB%', 'Swing%', 'Z-Swing%', 'Chase%', 'Contact%', 'Z-Contact%', 'O-Contact%', 'SwStr%', 'Whiff%', 'CSW%', 'GB%', 'FB%', 'LD%', 'OFFB%', 'IFFB%', 'AIR%', 'Zone%', 'Arm%', 'Glove%', 'High%', 'Low%', 'MM%']
67
+ stats_with_pctls = ['K%', 'BB%', 'Swing%', 'Z-Swing%', 'Chase%', 'Contact%', 'Z-Contact%', 'O-Contact%', 'SwStr%', 'Whiff%', 'CSW%', 'GB%', 'FB%', 'LD%', 'OFFB%', 'IFFB%', 'AIR%', 'Zone%'] # , 'OBP']
68
+ cols = ['Batter', 'Team', 'Bats', 'PA', 'K%', 'BB%', 'Swing%', 'Z-Swing%', 'Chase%', 'Contact%', 'Z-Contact%', 'O-Contact%', 'SwStr%', 'Whiff%', 'CSW%', 'GB%', 'FB%', 'LD%', 'OFFB%', 'IFFB%', 'AIR%']#, 'AB', 'H', 'BB', 'HBP', 'SF', 'OBP']
69
  if team:
70
  cols = [col for col in cols if col not in ('Batter', 'Bats')]
71
 
stats.py CHANGED
@@ -170,12 +170,15 @@ def compute_pitch_stats(data, player_type, pitch_class_type, min_pitches=1, pitc
170
  .with_columns(
171
  (pl.col('G') + pl.col('B')).alias('GB%'),
172
  (pl.col('F') + pl.col('P')).alias('FB%'),
173
- pl.col('L').alias('LD%').round(2),
 
 
 
174
  )
175
  .drop('G', 'F', 'B', 'P', 'L', 'null')
176
  .with_columns(
177
- (pl.when(pl.col('qualified')).then(pl.col(stat)).rank(descending=((stat in ['FB%', 'LD%', 'Ball%', 'Behind%'] or 'Contact%' in stat)))/pl.when(pl.col('qualified')).then(pl.col(stat)).count()).alias(f'{stat}_pctl')
178
- for stat in ['Avg KPH', 'Max KPH', 'Avg MPH', 'Max MPH', 'Swing%', 'Z-Swing%', 'Chase%', 'Contact%', 'Z-Contact%', 'O-Contact%', 'SwStr%', 'Whiff%', 'CSW%', 'Strike%', 'Ball%', 'F-Str%', 'PAR%', 'GB%', 'FB%', 'LD%', 'Zone%', 'Behind%']
179
  )
180
  .rename({pitch_col: 'ballKind_code', pitch_name_col: 'ballKind'} if pitch_class_type == 'general' else {})
181
  .sort(id_cols[0], 'count', descending=[False, True])
@@ -236,9 +239,9 @@ def compute_player_stats(data, player_type, qual='qualified', pitcher_lr='both',
236
 
237
  # percentile ascending/descending
238
  if pitching:
239
- stat_descending_pctl = lambda stat: stat in ['BB%', 'Ball%', 'FB%', 'LD%', 'Z-Swing%', 'Behind%', 'OBP'] or 'Contact%' in stat
240
  else:
241
- stat_descending_pctl = lambda stat: not (stat in ['BB%', 'Ball%', 'FB%', 'LD%', 'Swing%', 'Z-Swing%', 'Behind%', 'OBP'] or 'Contact%' in stat)
242
 
243
  # col names
244
  match player_type:
@@ -312,11 +315,14 @@ def compute_player_stats(data, player_type, qual='qualified', pitcher_lr='both',
312
  (pl.col('G') + pl.col('B')).alias('GB%'),
313
  (pl.col('F') + pl.col('P')).alias('FB%'),
314
  pl.col('L').alias('LD%'),
 
 
 
315
  )
316
  .drop('G', 'F', 'B', 'P', 'L')
317
  .with_columns(
318
  (pl.when(pl.col('qualified')).then(pl.col(stat)).rank(descending=stat_descending_pctl(stat))/pl.when(pl.col('qualified')).then(pl.col(stat)).count()).alias(f'{stat}_pctl')
319
- for stat in ['FB Velo', 'K%', 'BB%', 'Swing%', 'Z-Swing%', 'Chase%', 'Contact%', 'Z-Contact%', 'O-Contact%', 'SwStr%', 'Whiff%', 'CSW%', 'Strike%', 'Ball%', 'F-Str%', 'PAR%', 'GB%', 'FB%', 'LD%', 'Zone%', 'Behind%', 'OBP']
320
  )
321
  .sort(qual_col, descending=True)
322
  )
 
170
  .with_columns(
171
  (pl.col('G') + pl.col('B')).alias('GB%'),
172
  (pl.col('F') + pl.col('P')).alias('FB%'),
173
+ pl.col('L').alias('LD%'),
174
+ pl.col('P').alias('IFFB%'),
175
+ pl.col('F').alias('OFFB%'),
176
+ (pl.col('F') + pl.col('P') + pl.col('L')).alias('AIR%')
177
  )
178
  .drop('G', 'F', 'B', 'P', 'L', 'null')
179
  .with_columns(
180
+ (pl.when(pl.col('qualified')).then(pl.col(stat)).rank(descending=((stat in ['FB%', 'LD%', 'OFFB%', 'AIR%', 'Ball%', 'Behind%'] or 'Contact%' in stat)))/pl.when(pl.col('qualified')).then(pl.col(stat)).count()).alias(f'{stat}_pctl')
181
+ for stat in ['Avg KPH', 'Max KPH', 'Avg MPH', 'Max MPH', 'Swing%', 'Z-Swing%', 'Chase%', 'Contact%', 'Z-Contact%', 'O-Contact%', 'SwStr%', 'Whiff%', 'CSW%', 'Strike%', 'Ball%', 'F-Str%', 'PAR%', 'GB%', 'FB%', 'LD%', 'OFFB%', 'IFFB%', 'AIR%', 'Zone%', 'Behind%']
182
  )
183
  .rename({pitch_col: 'ballKind_code', pitch_name_col: 'ballKind'} if pitch_class_type == 'general' else {})
184
  .sort(id_cols[0], 'count', descending=[False, True])
 
239
 
240
  # percentile ascending/descending
241
  if pitching:
242
+ stat_descending_pctl = lambda stat: stat in ['BB%', 'Ball%', 'FB%', 'LD%', 'OFFB%', 'AIR%', 'Z-Swing%', 'Behind%', 'OBP'] or 'Contact%' in stat
243
  else:
244
+ stat_descending_pctl = lambda stat: not (stat in ['BB%', 'Ball%', 'FB%', 'LD%', 'OFFB%', 'AIR%' 'Swing%', 'Z-Swing%', 'Behind%', 'OBP'] or 'Contact%' in stat)
245
 
246
  # col names
247
  match player_type:
 
315
  (pl.col('G') + pl.col('B')).alias('GB%'),
316
  (pl.col('F') + pl.col('P')).alias('FB%'),
317
  pl.col('L').alias('LD%'),
318
+ pl.col('P').alias('IFFB%'),
319
+ pl.col('F').alias('OFFB%'),
320
+ (pl.col('F') + pl.col('P') + pl.col('L')).alias('AIR%')
321
  )
322
  .drop('G', 'F', 'B', 'P', 'L')
323
  .with_columns(
324
  (pl.when(pl.col('qualified')).then(pl.col(stat)).rank(descending=stat_descending_pctl(stat))/pl.when(pl.col('qualified')).then(pl.col(stat)).count()).alias(f'{stat}_pctl')
325
+ for stat in ['FB Velo', 'K%', 'BB%', 'Swing%', 'Z-Swing%', 'Chase%', 'Contact%', 'Z-Contact%', 'O-Contact%', 'SwStr%', 'Whiff%', 'CSW%', 'Strike%', 'Ball%', 'F-Str%', 'PAR%', 'GB%', 'FB%', 'LD%', 'OFFB%', 'IFFB%', 'AIR%', 'Zone%', 'Behind%', 'OBP']
326
  )
327
  .sort(qual_col, descending=True)
328
  )