Spaces:
Running
Running
Commit
·
56c6bd4
1
Parent(s):
e86b89f
Make leaderboard text smaller and add Zone% percentiles
Browse files
app.py
CHANGED
@@ -3,6 +3,7 @@ import gradio as gr
|
|
3 |
from data import data_df
|
4 |
from pitcher_overview import create_pitcher_overview
|
5 |
from pitch_leaderboard import create_pitch_leaderboard
|
|
|
6 |
|
7 |
updated = '2025-07-21'
|
8 |
limitations = '''**General Limitations**
|
@@ -10,7 +11,7 @@ limitations = '''**General Limitations**
|
|
10 |
'''
|
11 |
|
12 |
if __name__ == '__main__':
|
13 |
-
with gr.Blocks() as app:
|
14 |
with gr.Tab('Pitcher Overview'):
|
15 |
create_pitcher_overview(data_df)
|
16 |
with gr.Tab('Pitch Leaderboard'):
|
|
|
3 |
from data import data_df
|
4 |
from pitcher_overview import create_pitcher_overview
|
5 |
from pitch_leaderboard import create_pitch_leaderboard
|
6 |
+
from css import css
|
7 |
|
8 |
updated = '2025-07-21'
|
9 |
limitations = '''**General Limitations**
|
|
|
11 |
'''
|
12 |
|
13 |
if __name__ == '__main__':
|
14 |
+
with gr.Blocks(css=css) as app:
|
15 |
with gr.Tab('Pitcher Overview'):
|
16 |
create_pitcher_overview(data_df)
|
17 |
with gr.Tab('Pitch Leaderboard'):
|
css.py
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
css = '''
|
2 |
+
#leaderboard span {font-size: 0.75em;}
|
3 |
+
'''
|
pitch_leaderboard.py
CHANGED
@@ -12,7 +12,7 @@ from plotting import stat_cmap
|
|
12 |
|
13 |
STATS = ['Count', 'Usage', 'Swing%', 'Z-Swing%', 'Chase%', 'Contact%', 'Z-Contact%', 'O-Contact%', 'SwStr%', 'Whiff%', 'CSW%', 'GB%', 'FB%', 'LD%', 'Zone%', 'Arm%', 'Glove%', 'High%', 'Low%', 'MM%']
|
14 |
PCT_STATS = ['Usage', 'Swing%', 'Z-Swing%', 'Chase%', 'Contact%', 'Z-Contact%', 'O-Contact%', 'SwStr%', 'Whiff%', 'CSW%', 'GB%', 'FB%', 'LD%', 'Zone%', 'Arm%', 'Glove%', 'High%', 'Low%', 'MM%']
|
15 |
-
STATS_WITH_PCTLS = ['Swing%', 'Z-Swing%', 'Chase%', 'Contact%', 'Z-Contact%', 'O-Contact%', 'SwStr%', 'Whiff%', 'CSW%', 'GB%', 'FB%', 'LD%']
|
16 |
COLUMNS = ['Pitcher', 'Team', 'Pitch', 'Pitch (General)'] + STATS
|
17 |
|
18 |
PITCH_TYPES = [pitch_type for pitch_type in ball_kind.values() if pitch_type != '-']
|
@@ -84,6 +84,7 @@ def gr_create_pitch_leaderboard(start_date, end_date, min_pitches, pitcher_lr='B
|
|
84 |
for i, row in enumerate(pitch_stats[COLUMNS].iter_rows()):
|
85 |
styling_row = []
|
86 |
for col, item in zip(pitch_stats[COLUMNS].columns, row):
|
|
|
87 |
if f'{col}_pctl' in pitch_stats:
|
88 |
r, g, b = (stat_cmap([pitch_stats[f'{col}_pctl'][i]])[0, :3]*255).astype(np.uint8)
|
89 |
styling_row.append(f'background-color: rgba({r}, {g}, {b})')
|
@@ -141,10 +142,11 @@ def create_pitch_leaderboard():
|
|
141 |
# pin_columns = gr.Checkbox(True, 'Pin columns')
|
142 |
leaderboard = gr.DataFrame(
|
143 |
pl.DataFrame({'Pitcher': [], 'Pitch': []}),
|
144 |
-
column_widths=[
|
145 |
show_copy_button=True,
|
146 |
show_search='filter',
|
147 |
pinned_columns=3,
|
|
|
148 |
)
|
149 |
|
150 |
gr.Markdown(notes)
|
|
|
12 |
|
13 |
STATS = ['Count', 'Usage', 'Swing%', 'Z-Swing%', 'Chase%', 'Contact%', 'Z-Contact%', 'O-Contact%', 'SwStr%', 'Whiff%', 'CSW%', 'GB%', 'FB%', 'LD%', 'Zone%', 'Arm%', 'Glove%', 'High%', 'Low%', 'MM%']
|
14 |
PCT_STATS = ['Usage', 'Swing%', 'Z-Swing%', 'Chase%', 'Contact%', 'Z-Contact%', 'O-Contact%', 'SwStr%', 'Whiff%', 'CSW%', 'GB%', 'FB%', 'LD%', 'Zone%', 'Arm%', 'Glove%', 'High%', 'Low%', 'MM%']
|
15 |
+
STATS_WITH_PCTLS = ['Swing%', 'Z-Swing%', 'Chase%', 'Contact%', 'Z-Contact%', 'O-Contact%', 'SwStr%', 'Whiff%', 'CSW%', 'GB%', 'FB%', 'LD%', 'Zone%']
|
16 |
COLUMNS = ['Pitcher', 'Team', 'Pitch', 'Pitch (General)'] + STATS
|
17 |
|
18 |
PITCH_TYPES = [pitch_type for pitch_type in ball_kind.values() if pitch_type != '-']
|
|
|
84 |
for i, row in enumerate(pitch_stats[COLUMNS].iter_rows()):
|
85 |
styling_row = []
|
86 |
for col, item in zip(pitch_stats[COLUMNS].columns, row):
|
87 |
+
_styling = 'font-size: 0.75em; '
|
88 |
if f'{col}_pctl' in pitch_stats:
|
89 |
r, g, b = (stat_cmap([pitch_stats[f'{col}_pctl'][i]])[0, :3]*255).astype(np.uint8)
|
90 |
styling_row.append(f'background-color: rgba({r}, {g}, {b})')
|
|
|
142 |
# pin_columns = gr.Checkbox(True, 'Pin columns')
|
143 |
leaderboard = gr.DataFrame(
|
144 |
pl.DataFrame({'Pitcher': [], 'Pitch': []}),
|
145 |
+
column_widths=[125, 75, 125, 125] + [max(50, 10*len(stat)) for stat in STATS],
|
146 |
show_copy_button=True,
|
147 |
show_search='filter',
|
148 |
pinned_columns=3,
|
149 |
+
elem_id='leaderboard'
|
150 |
)
|
151 |
|
152 |
gr.Markdown(notes)
|
stats.py
CHANGED
@@ -102,7 +102,7 @@ def compute_pitch_stats(data, player_type, pitch_class_type, min_pitches=1):
|
|
102 |
.drop('G', 'F', 'B', 'P', 'L', 'null')
|
103 |
.with_columns(
|
104 |
(pl.when(pl.col('qualified')).then(pl.col(stat)).rank(descending=((stat in ['FB%', 'LD%'] or 'Contact%' in stat)))/pl.when(pl.col('qualified')).then(pl.col(stat)).count()).alias(f'{stat}_pctl')
|
105 |
-
for stat in ['Swing%', 'Z-Swing%', 'Chase%', 'Contact%', 'Z-Contact%', 'O-Contact%', 'SwStr%', 'Whiff%', 'CSW%', 'GB%', 'FB%', 'LD%']
|
106 |
)
|
107 |
.rename({pitch_col: 'ballKind_code', pitch_name_col: 'ballKind'} if pitch_class_type == 'general' else {})
|
108 |
.sort(id_col, 'count', descending=[False, True])
|
|
|
102 |
.drop('G', 'F', 'B', 'P', 'L', 'null')
|
103 |
.with_columns(
|
104 |
(pl.when(pl.col('qualified')).then(pl.col(stat)).rank(descending=((stat in ['FB%', 'LD%'] or 'Contact%' in stat)))/pl.when(pl.col('qualified')).then(pl.col(stat)).count()).alias(f'{stat}_pctl')
|
105 |
+
for stat in ['Swing%', 'Z-Swing%', 'Chase%', 'Contact%', 'Z-Contact%', 'O-Contact%', 'SwStr%', 'Whiff%', 'CSW%', 'GB%', 'FB%', 'LD%', 'Zone%']
|
106 |
)
|
107 |
.rename({pitch_col: 'ballKind_code', pitch_name_col: 'ballKind'} if pitch_class_type == 'general' else {})
|
108 |
.sort(id_col, 'count', descending=[False, True])
|