nesticot's picture
Update app.py
79d40b5 verified
from shiny import App, Inputs, Outputs, Session, reactive, render, req, ui
import datasets
from datasets import load_dataset
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np
from scipy.stats import gaussian_kde
import matplotlib
from matplotlib.ticker import MaxNLocator
from matplotlib.gridspec import GridSpec
from scipy.stats import zscore
import math
import matplotlib
from adjustText import adjust_text
import matplotlib.ticker as mtick
from shinywidgets import output_widget, render_widget
import pandas as pd
#from configure import base_url
import shinyswatch
import inflect
from matplotlib.pyplot import text
from functions import rolling_batter_functions as rbf
import joblib
import polars as pl
from functions import df_update
update = df_update.df_update()
def percentile(n):
def percentile_(x):
return np.nanpercentile(x, n)
percentile_.__name__ = 'percentile_%s' % n
return percentile_
colour_palette = ['#FFB000','#648FFF','#785EF0',
'#DC267F','#FE6100','#3D1EB2','#894D80','#16AA02','#B5592B','#A3C1ED']
print('Starting Everything:')
exit_velo_df_mlb = pl.read_parquet(f"hf://datasets/TJStatsApps/mlb_data/data/mlb_pitch_data_2025.parquet")
#print(df_2023)
exit_velo_df_mlb = exit_velo_df_mlb.with_columns(pl.lit('MLB').alias('level'))
exit_velo_df_aaa = pl.read_parquet(f"hf://datasets/TJStatsApps/mlb_data/data/aaa_pitch_data_2025.parquet")
#print(df_2023)
exit_velo_df_aaa = exit_velo_df_aaa.with_columns(pl.lit('AAA').alias('level'))
exit_velo_df_aa = pl.read_parquet(f"hf://datasets/TJStatsApps/mlb_data/data/aa_pitch_data_2025.parquet")
#print(df_2023)
exit_velo_df_aa = exit_velo_df_aa.with_columns(pl.lit('AA').alias('level'))
exit_velo_df_ha = pl.read_parquet(f"hf://datasets/TJStatsApps/mlb_data/data/hi_a_pitch_data_2025.parquet")
#print(df_2023)
exit_velo_df_ha = exit_velo_df_ha.with_columns(pl.lit('A+').alias('level'))
### Import Datasets
exit_velo_df_a = pl.read_parquet(f"hf://datasets/TJStatsApps/mlb_data/data/lo_a_pitch_data_2025.parquet")
#print(df_2023)
exit_velo_df_a = exit_velo_df_a.with_columns(pl.lit('A').alias('level'))
exit_velo_df = pl.concat([exit_velo_df_mlb,exit_velo_df_aaa,exit_velo_df_aa,exit_velo_df_ha,exit_velo_df_a])
# exit_velo_df = pl.concat([exit_velo_df_mlb])#,exit_velo_df_aaa,exit_velo_df_aa,exit_velo_df_ha,exit_velo_df_a])
exit_velo_df_codes = update.update(exit_velo_df).sort('start_time')
exit_velo_df_codes_summ = update.update_summary_select(df=exit_velo_df_codes,selection=['batter_id','batter_name','level']).to_pandas()
exit_velo_df_codes = exit_velo_df_codes.to_pandas()
woba_list = ['woba']
pa_list = ['k','bb','bb_minus_k']
balls_in_play_list = ['hard_hit','launch_speed','launch_speed_90','launch_angle','barrel','sweet_spot']
pitches_list = ['zone_percent','swing_percent','sw_str','csw']
swings_list = ['whiff_percent']
in_zone_pitches_list = ['zone_swing']
in_zone_swings_list = ['zone_contact']
out_zone_pitches_list = ['chase_percent']
out_zone_swings_list = ['chase_contact']
plot_dict = {
'k':{'x_axis':'Plate Appearances','y_axis':'K%','title':'K%','x_value':'k','x_range':[0.0,0.1,0.2,0.3,0.4],'percent':True,'percentile_label':'k_percent','flip_p':True,'percentile':False,'avg_adjust':False},
'bb':{'x_axis':'Plate Appearances','y_axis':'BB%','title':'BB%','x_value':'bb','x_range':[0.0,0.1,0.2,0.3],'percent':True,'percentile_label':'bb_percent','flip_p':False,'percentile':False,'avg_adjust':False},
'bb_minus_k':{'x_axis':'Plate Appearances','y_axis':'BB-K%','title':'BB-K%','x_value':'bb_minus_k','x_range':[-0.3,-0.2,-0.1,0,0.1,0.2],'percent':True,'percentile_label':'bb_minus_k_percent','flip_p':False,'percentile':False,'avg_adjust':False},
'csw':{'x_axis':'Pitches','y_axis':'CSW%','title':'CSW%','x_value':'csw','x_range':[.2,.25,.3,.35,.4],'percent':True,'percentile_label':'csw_percent','flip_p':True,'percentile':False,'avg_adjust':False},
'woba':{'x_axis':'wOBA PA','y_axis':'wOBA','title':'wOBA','x_value':'woba','x_range':[.20,.30,.40,.50],'percent':False,'percentile_label':'woba_percent','flip_p':False,'percentile':False,'avg_adjust':True},
'launch_speed':{'x_axis':'Balls In Play','y_axis':'Exit Velocity','title':'Exit Velocity','x_value':'launch_speed','x_range':[85,90,95,100],'percent':False,'percentile_label':'launch_speed','flip_p':False,'percentile':False,'avg_adjust':False},
'launch_speed_90':{'x_axis':'Balls In Play','y_axis':'90th Percentile Exit Velocity','title':'90th Percentile Exit Velocity','x_value':'launch_speed','x_range':[95,100,105,110,115],'percent':False,'percentile_label':'launch_speed_90','flip_p':False,'percentile':True,'avg_adjust':False},
'hard_hit':{'x_axis':'Balls In Play','y_axis':'HardHit%','title':'HardHit%','x_value':'hard_hit','x_range':[0.2,0.3,0.4,0.5,0.6,0.7],'percent':True,'percentile_label':'hard_hit_percent','flip_p':False,'percentile':False,'avg_adjust':False},
'sweet_spot':{'x_axis':'Balls In Play','y_axis':'SweetSpot%','title':'SweetSpot%','x_value':'sweet_spot','x_range':[0.2,0.3,0.4,0.5],'percent':True,'percentile_label':'sweet_spot_percent','flip_p':False,'percentile':False,'avg_adjust':False},
'launch_angle':{'x_axis':'Balls In Play','y_axis':'Launch Angle','title':'Launch Angle','x_value':'launch_angle','x_range':[-20,-10,0,10,20],'percent':False,'percentile_label':'launch_angle','flip_p':False,'percentile':False,'avg_adjust':False},
'barrel':{'x_axis':'Balls In Play','y_axis':'Barrel%','title':'Barrel%','x_value':'barrel','x_range':[0,0.05,0.10,.15,.20],'percent':True,'percentile_label':'barrel_percent','flip_p':False,'percentile':False,'avg_adjust':False},
'zone_percent':{'x_axis':'Pitches','y_axis':'Zone%','title':'Zone%','x_value':'in_zone','x_range':[0.3,0.4,0.5,0.6,0.7],'percent':True,'percentile_label':'zone_percent','flip_p':False,'percentile':False,'avg_adjust':False},
'swing_percent':{'x_axis':'Pitches','y_axis':'Swing%','title':'Swing%','x_value':'swings','x_range':[0.2,0.3,0.4,0.5,0.6,0.7,0.8],'percent':True,'percentile_label':'swing_percent','flip_p':False,'percentile':False,'avg_adjust':False},
'whiff_percent':{'x_axis':'Swings','y_axis':'Whiff%','title':'Whiff%','x_value':'whiffs','x_range':[0.0,0.1,0.2,0.3,0.4,0.5],'percent':True,'percentile_label':'whiff_rate','flip_p':True,'percentile':False,'avg_adjust':False},
'sw_str':{'x_axis':'Pitches','y_axis':'SwStr%','title':'SwStr%','x_value':'whiffs','x_range':[0.0,0.05,0.1,0.15,0.2,0.25],'percent':True,'percentile_label':'swstr_rate','flip_p':True,'percentile':False,'avg_adjust':False},
'zone_swing':{'x_axis':'In-Zone Pitches','y_axis':'Z-Swing%','title':'Z-Swing%','x_value':'zone_swing','x_range':[0.3,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1],'percent':True,'percentile_label':'zone_swing_percent','flip_p':False,'percentile':False,'avg_adjust':False},
'zone_contact':{'x_axis':'In-Zone Swings','y_axis':'Z-Contact%','title':'Z-Contact%','x_value':'zone_contact','x_range':[0.5,0.6,0.7,0.8,0.9,1],'percent':True,'percentile_label':'zone_contact_percent','flip_p':False,'percentile':False,'avg_adjust':False},
'chase_percent':{'x_axis':'Out-of-Zone Pitches','y_axis':'O-Swing%','title':'O-Swing%','x_value':'ozone_swing','x_range':[0.0,0.1,0.2,0.3,0.4,0.5],'percent':True,'percentile_label':'chase_percent','flip_p':True,'percentile':False,'avg_adjust':False},
'chase_contact':{'x_axis':'Out-of-Zone Swings','y_axis':'O-Contact%','title':'O-Contact%','x_value':'ozone_contact','x_range':[0.2,0.3,0.4,0.5,0.6,0.7,0.8],'percent':True,'percentile_label':'chase_contact','flip_p':False,'percentile':False,'avg_adjust':False},}
# test_df = exit_velo_df.sort_values(by='batter_name').drop_duplicates(subset='batter_id').reset_index(drop=True)[['batter_id','batter_name']]#['pitcher'].to_dict()
# test_df = test_df.dropna()
# test_df['batter_id'] = test_df['batter_id'].astype(int)
# test_df = test_df.set_index('batter_id')
# #test_df = test_df[test_df.pitcher == 'Chris Bassitt'].append(test_df[test_df.pitcher != 'Chris Bassitt'])
batter_dict_mlb = dict(zip(exit_velo_df_mlb.sort(['batter_name'])['batter_id'],exit_velo_df_mlb.sort(['batter_name'])['batter_name']))
# batter_dict_mlb = exit_velo_df_mlb.sort(['batter_name']).set_index('batter_id')['batter_name'].to_dict()
batter_dict_aaa = dict(zip(exit_velo_df_aaa.sort(['batter_name'])['batter_id'],exit_velo_df_aaa.sort(['batter_name'])['batter_name']))
batter_dict_aa = dict(zip(exit_velo_df_aa.sort(['batter_name'])['batter_id'],exit_velo_df_aa.sort(['batter_name'])['batter_name']))
batter_dict_ha = dict(zip(exit_velo_df_ha.sort(['batter_name'])['batter_id'],exit_velo_df_ha.sort(['batter_name'])['batter_name']))
batter_dict_a =dict(zip(exit_velo_df_a.sort(['batter_name'])['batter_id'],exit_velo_df_a.sort(['batter_name'])['batter_name']))
level_dict = {'MLB':'MLB','AAA':'AAA','AA':'AA','A+':'A+','A':'A'}
plot_dict_small = {
'k':'K%',
'bb':'BB%',
'bb_minus_k':'BB-K%',
'csw':'CSW%',
'woba':'wOBA',
'launch_speed':'Exit Velocity',
'launch_speed_90':'90th Percentile Exit Velocity',
'hard_hit':'HardHit%',
'sweet_spot':'SweetSpot%',
'launch_angle':'Launch Angle',
'zone_percent':'Zone%',
'barrel':'Barrel%',
'swing_percent':'Swing%',
'whiff_percent':'Whiff%',
'sw_str':'SwStr%',
'zone_swing':'Z-Swing%',
'zone_contact':'Z-Contact%',
'chase_percent':'O-Swing%',
'chase_contact':'O-Contact%',}
def server(input,output,session):
@render.ui
def test():
# @reactive.Effect
if input.my_tabs() == 'MLB':
#test_df = test_df[test_df.pitcher == 'Chris Bassitt'].append(test_df[test_df.pitcher != 'Chris Bassitt'])
#batter_dict = exit_velo_df_mlb.set_index('batter_id')['batter_name'].to_dict()
return ui.input_select("id", "Select Player",batter_dict_mlb,selectize=True)
if input.my_tabs() == 'AAA':
#test_df = test_df[test_df.pitcher == 'Chris Bassitt'].append(test_df[test_df.pitcher != 'Chris Bassitt'])
#batter_dict = exit_velo_df_aaa.set_index('batter_id')['batter_name'].to_dict()
return ui.input_select("id", "Select Player",batter_dict_aaa,selectize=True)
if input.my_tabs() == 'AA':
#test_df = test_df[test_df.pitcher == 'Chris Bassitt'].append(test_df[test_df.pitcher != 'Chris Bassitt'])
#batter_dict = exit_velo_df_aaa.set_index('batter_id')['batter_name'].to_dict()
return ui.input_select("id", "Select Player",batter_dict_aa,selectize=True)
if input.my_tabs() == 'A+':
#test_df = test_df[test_df.pitcher == 'Chris Bassitt'].append(test_df[test_df.pitcher != 'Chris Bassitt'])
#batter_dict = exit_velo_df_aaa.set_index('batter_id')['batter_name'].to_dict()
return ui.input_select("id", "Select Player",batter_dict_ha,selectize=True)
if input.my_tabs() == 'A':
#test_df = test_df[test_df.pitcher == 'Chris Bassitt'].append(test_df[test_df.pitcher != 'Chris Bassitt'])
#batter_dict = exit_velo_df_aaa.set_index('batter_id')['batter_name'].to_dict()
return ui.input_select("id", "Select Player",batter_dict_a,selectize=True)
@output
@render.plot(alt="A histogram")
@reactive.event(input.go, ignore_none=False)
def plot_mlb():
rbf.rolling_plot(df = exit_velo_df_codes[exit_velo_df_codes['level']==input.my_tabs()],
df_summ = exit_velo_df_codes_summ[exit_velo_df_codes_summ['level']==input.my_tabs()],
player_id = input.id(),
stat_id = input.stat_id(),
batter_dict = batter_dict_mlb,
window_select = input.n(),
level_id = input.my_tabs())
@output
@render.plot(alt="A histogram")
@reactive.event(input.go, ignore_none=False)
def plot_aaa():
rbf.rolling_plot(df = exit_velo_df_codes[exit_velo_df_codes['level']==input.my_tabs()],
df_summ = exit_velo_df_codes_summ[exit_velo_df_codes_summ['level']==input.my_tabs()],
player_id = input.id(),
stat_id = input.stat_id(),
batter_dict = batter_dict_aaa,
window_select = input.n(),
level_id = input.my_tabs())
@output
@render.plot(alt="A histogram")
@reactive.event(input.go, ignore_none=False)
def plot_aa():
rbf.rolling_plot(df = exit_velo_df_codes[exit_velo_df_codes['level']==input.my_tabs()],
df_summ = exit_velo_df_codes_summ[exit_velo_df_codes_summ['level']==input.my_tabs()],
player_id = input.id(),
stat_id = input.stat_id(),
batter_dict = batter_dict_aa,
window_select = input.n(),
level_id = input.my_tabs())
@output
@render.plot(alt="A histogram")
@reactive.event(input.go, ignore_none=False)
def plot_ha():
rbf.rolling_plot(df = exit_velo_df_codes[exit_velo_df_codes['level']==input.my_tabs()],
df_summ = exit_velo_df_codes_summ[exit_velo_df_codes_summ['level']==input.my_tabs()],
player_id = input.id(),
stat_id = input.stat_id(),
batter_dict = batter_dict_ha,
window_select = input.n(),
level_id = input.my_tabs())
@output
@render.plot(alt="A histogram")
@reactive.event(input.go, ignore_none=False)
def plot_a():
rbf.rolling_plot(df = exit_velo_df_codes[exit_velo_df_codes['level']==input.my_tabs()],
df_summ = exit_velo_df_codes_summ[exit_velo_df_codes_summ['level']==input.my_tabs()],
player_id = input.id(),
stat_id = input.stat_id(),
batter_dict = batter_dict_a,
window_select = input.n(),
level_id = input.my_tabs())
from shiny import App, Inputs, Outputs, Session, reactive, render, req, ui
import datasets
from datasets import load_dataset
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np
from scipy.stats import gaussian_kde
import matplotlib
from matplotlib.ticker import MaxNLocator
from matplotlib.gridspec import GridSpec
from scipy.stats import zscore
import math
import matplotlib
from adjustText import adjust_text
import matplotlib.ticker as mtick
from shinywidgets import output_widget, render_widget
import pandas as pd
#from configure import base_url
import shinyswatch
import inflect
from matplotlib.pyplot import text
from functions import rolling_batter_functions as rbf
import joblib
import polars as pl
from functions import df_update
update = df_update.df_update()
def percentile(n):
def percentile_(x):
return np.nanpercentile(x, n)
percentile_.__name__ = 'percentile_%s' % n
return percentile_
colour_palette = ['#FFB000','#648FFF','#785EF0',
'#DC267F','#FE6100','#3D1EB2','#894D80','#16AA02','#B5592B','#A3C1ED']
print('Starting Everything:')
exit_velo_df_mlb = pl.read_parquet(f"hf://datasets/TJStatsApps/mlb_data/data/mlb_pitch_data_2025.parquet")
#print(df_2023)
exit_velo_df_mlb = exit_velo_df_mlb.with_columns(pl.lit('MLB').alias('level'))
exit_velo_df_aaa = pl.read_parquet(f"hf://datasets/TJStatsApps/mlb_data/data/aaa_pitch_data_2025.parquet")
#print(df_2023)
exit_velo_df_aaa = exit_velo_df_aaa.with_columns(pl.lit('AAA').alias('level'))
exit_velo_df_aa = pl.read_parquet(f"hf://datasets/TJStatsApps/mlb_data/data/aa_pitch_data_2025.parquet")
#print(df_2023)
exit_velo_df_aa = exit_velo_df_aa.with_columns(pl.lit('AA').alias('level'))
exit_velo_df_ha = pl.read_parquet(f"hf://datasets/TJStatsApps/mlb_data/data/hi_a_pitch_data_2025.parquet")
#print(df_2023)
exit_velo_df_ha = exit_velo_df_ha.with_columns(pl.lit('A+').alias('level'))
### Import Datasets
exit_velo_df_a = pl.read_parquet(f"hf://datasets/TJStatsApps/mlb_data/data/lo_a_pitch_data_2025.parquet")
#print(df_2023)
exit_velo_df_a = exit_velo_df_a.with_columns(pl.lit('A').alias('level'))
exit_velo_df = pl.concat([exit_velo_df_mlb,exit_velo_df_aaa,exit_velo_df_aa,exit_velo_df_ha,exit_velo_df_a])
# exit_velo_df = pl.concat([exit_velo_df_mlb])#,exit_velo_df_aaa,exit_velo_df_aa,exit_velo_df_ha,exit_velo_df_a])
exit_velo_df_codes = update.update(exit_velo_df)
exit_velo_df_codes_summ = update.update_summary_select(df=exit_velo_df_codes,selection=['batter_id','batter_name','level']).to_pandas()
exit_velo_df_codes = exit_velo_df_codes.to_pandas()
woba_list = ['woba']
pa_list = ['k','bb','bb_minus_k']
balls_in_play_list = ['hard_hit','launch_speed','launch_speed_90','launch_angle','barrel','sweet_spot']
pitches_list = ['zone_percent','swing_percent','sw_str','csw']
swings_list = ['whiff_percent']
in_zone_pitches_list = ['zone_swing']
in_zone_swings_list = ['zone_contact']
out_zone_pitches_list = ['chase_percent']
out_zone_swings_list = ['chase_contact']
plot_dict = {
'k':{'x_axis':'Plate Appearances','y_axis':'K%','title':'K%','x_value':'k','x_range':[0.0,0.1,0.2,0.3,0.4],'percent':True,'percentile_label':'k_percent','flip_p':True,'percentile':False,'avg_adjust':False},
'bb':{'x_axis':'Plate Appearances','y_axis':'BB%','title':'BB%','x_value':'bb','x_range':[0.0,0.1,0.2,0.3],'percent':True,'percentile_label':'bb_percent','flip_p':False,'percentile':False,'avg_adjust':False},
'bb_minus_k':{'x_axis':'Plate Appearances','y_axis':'BB-K%','title':'BB-K%','x_value':'bb_minus_k','x_range':[-0.3,-0.2,-0.1,0,0.1,0.2],'percent':True,'percentile_label':'bb_minus_k_percent','flip_p':False,'percentile':False,'avg_adjust':False},
'csw':{'x_axis':'Pitches','y_axis':'CSW%','title':'CSW%','x_value':'csw','x_range':[.2,.25,.3,.35,.4],'percent':True,'percentile_label':'csw_percent','flip_p':True,'percentile':False,'avg_adjust':False},
'woba':{'x_axis':'wOBA PA','y_axis':'wOBA','title':'wOBA','x_value':'woba','x_range':[.20,.30,.40,.50],'percent':False,'percentile_label':'woba_percent','flip_p':False,'percentile':False,'avg_adjust':True},
'launch_speed':{'x_axis':'Balls In Play','y_axis':'Exit Velocity','title':'Exit Velocity','x_value':'launch_speed','x_range':[85,90,95,100],'percent':False,'percentile_label':'launch_speed','flip_p':False,'percentile':False,'avg_adjust':False},
'launch_speed_90':{'x_axis':'Balls In Play','y_axis':'90th Percentile Exit Velocity','title':'90th Percentile Exit Velocity','x_value':'launch_speed','x_range':[95,100,105,110,115],'percent':False,'percentile_label':'launch_speed_90','flip_p':False,'percentile':True,'avg_adjust':False},
'hard_hit':{'x_axis':'Balls In Play','y_axis':'HardHit%','title':'HardHit%','x_value':'hard_hit','x_range':[0.2,0.3,0.4,0.5,0.6,0.7],'percent':True,'percentile_label':'hard_hit_percent','flip_p':False,'percentile':False,'avg_adjust':False},
'sweet_spot':{'x_axis':'Balls In Play','y_axis':'SweetSpot%','title':'SweetSpot%','x_value':'sweet_spot','x_range':[0.2,0.3,0.4,0.5],'percent':True,'percentile_label':'sweet_spot_percent','flip_p':False,'percentile':False,'avg_adjust':False},
'launch_angle':{'x_axis':'Balls In Play','y_axis':'Launch Angle','title':'Launch Angle','x_value':'launch_angle','x_range':[-20,-10,0,10,20],'percent':False,'percentile_label':'launch_angle','flip_p':False,'percentile':False,'avg_adjust':False},
'barrel':{'x_axis':'Balls In Play','y_axis':'Barrel%','title':'Barrel%','x_value':'barrel','x_range':[0,0.05,0.10,.15,.20],'percent':True,'percentile_label':'barrel_percent','flip_p':False,'percentile':False,'avg_adjust':False},
'zone_percent':{'x_axis':'Pitches','y_axis':'Zone%','title':'Zone%','x_value':'in_zone','x_range':[0.3,0.4,0.5,0.6,0.7],'percent':True,'percentile_label':'zone_percent','flip_p':False,'percentile':False,'avg_adjust':False},
'swing_percent':{'x_axis':'Pitches','y_axis':'Swing%','title':'Swing%','x_value':'swings','x_range':[0.2,0.3,0.4,0.5,0.6,0.7,0.8],'percent':True,'percentile_label':'swing_percent','flip_p':False,'percentile':False,'avg_adjust':False},
'whiff_percent':{'x_axis':'Swings','y_axis':'Whiff%','title':'Whiff%','x_value':'whiffs','x_range':[0.0,0.1,0.2,0.3,0.4,0.5],'percent':True,'percentile_label':'whiff_rate','flip_p':True,'percentile':False,'avg_adjust':False},
'sw_str':{'x_axis':'Pitches','y_axis':'SwStr%','title':'SwStr%','x_value':'whiffs','x_range':[0.0,0.05,0.1,0.15,0.2,0.25],'percent':True,'percentile_label':'swstr_rate','flip_p':True,'percentile':False,'avg_adjust':False},
'zone_swing':{'x_axis':'In-Zone Pitches','y_axis':'Z-Swing%','title':'Z-Swing%','x_value':'zone_swing','x_range':[0.3,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1],'percent':True,'percentile_label':'zone_swing_percent','flip_p':False,'percentile':False,'avg_adjust':False},
'zone_contact':{'x_axis':'In-Zone Swings','y_axis':'Z-Contact%','title':'Z-Contact%','x_value':'zone_contact','x_range':[0.5,0.6,0.7,0.8,0.9,1],'percent':True,'percentile_label':'zone_contact_percent','flip_p':False,'percentile':False,'avg_adjust':False},
'chase_percent':{'x_axis':'Out-of-Zone Pitches','y_axis':'O-Swing%','title':'O-Swing%','x_value':'ozone_swing','x_range':[0.0,0.1,0.2,0.3,0.4,0.5],'percent':True,'percentile_label':'chase_percent','flip_p':True,'percentile':False,'avg_adjust':False},
'chase_contact':{'x_axis':'Out-of-Zone Swings','y_axis':'O-Contact%','title':'O-Contact%','x_value':'ozone_contact','x_range':[0.2,0.3,0.4,0.5,0.6,0.7,0.8],'percent':True,'percentile_label':'chase_contact','flip_p':False,'percentile':False,'avg_adjust':False},}
# test_df = exit_velo_df.sort_values(by='batter_name').drop_duplicates(subset='batter_id').reset_index(drop=True)[['batter_id','batter_name']]#['pitcher'].to_dict()
# test_df = test_df.dropna()
# test_df['batter_id'] = test_df['batter_id'].astype(int)
# test_df = test_df.set_index('batter_id')
# #test_df = test_df[test_df.pitcher == 'Chris Bassitt'].append(test_df[test_df.pitcher != 'Chris Bassitt'])
batter_dict_mlb = dict(zip(exit_velo_df_mlb.sort(['batter_name'])['batter_id'],exit_velo_df_mlb.sort(['batter_name'])['batter_name']))
# batter_dict_mlb = exit_velo_df_mlb.sort(['batter_name']).set_index('batter_id')['batter_name'].to_dict()
batter_dict_aaa = dict(zip(exit_velo_df_aaa.sort(['batter_name'])['batter_id'],exit_velo_df_aaa.sort(['batter_name'])['batter_name']))
batter_dict_aa = dict(zip(exit_velo_df_aa.sort(['batter_name'])['batter_id'],exit_velo_df_aa.sort(['batter_name'])['batter_name']))
batter_dict_ha = dict(zip(exit_velo_df_ha.sort(['batter_name'])['batter_id'],exit_velo_df_ha.sort(['batter_name'])['batter_name']))
batter_dict_a =dict(zip(exit_velo_df_a.sort(['batter_name'])['batter_id'],exit_velo_df_a.sort(['batter_name'])['batter_name']))
level_dict = {'MLB':'MLB','AAA':'AAA','AA':'AA','A+':'A+','A':'A'}
plot_dict_small = {
'k':'K%',
'bb':'BB%',
'bb_minus_k':'BB-K%',
'csw':'CSW%',
'woba':'wOBA',
'launch_speed':'Exit Velocity',
'launch_speed_90':'90th Percentile Exit Velocity',
'hard_hit':'HardHit%',
'sweet_spot':'SweetSpot%',
'launch_angle':'Launch Angle',
'zone_percent':'Zone%',
'barrel':'Barrel%',
'swing_percent':'Swing%',
'whiff_percent':'Whiff%',
'sw_str':'SwStr%',
'zone_swing':'Z-Swing%',
'zone_contact':'Z-Contact%',
'chase_percent':'O-Swing%',
'chase_contact':'O-Contact%',}
def server(input,output,session):
@render.ui
def test():
# @reactive.Effect
if input.my_tabs() == 'MLB':
#test_df = test_df[test_df.pitcher == 'Chris Bassitt'].append(test_df[test_df.pitcher != 'Chris Bassitt'])
#batter_dict = exit_velo_df_mlb.set_index('batter_id')['batter_name'].to_dict()
return ui.input_select("id", "Select Player",batter_dict_mlb,selectize=True)
if input.my_tabs() == 'AAA':
#test_df = test_df[test_df.pitcher == 'Chris Bassitt'].append(test_df[test_df.pitcher != 'Chris Bassitt'])
#batter_dict = exit_velo_df_aaa.set_index('batter_id')['batter_name'].to_dict()
return ui.input_select("id", "Select Player",batter_dict_aaa,selectize=True)
if input.my_tabs() == 'AA':
#test_df = test_df[test_df.pitcher == 'Chris Bassitt'].append(test_df[test_df.pitcher != 'Chris Bassitt'])
#batter_dict = exit_velo_df_aaa.set_index('batter_id')['batter_name'].to_dict()
return ui.input_select("id", "Select Player",batter_dict_aa,selectize=True)
if input.my_tabs() == 'A+':
#test_df = test_df[test_df.pitcher == 'Chris Bassitt'].append(test_df[test_df.pitcher != 'Chris Bassitt'])
#batter_dict = exit_velo_df_aaa.set_index('batter_id')['batter_name'].to_dict()
return ui.input_select("id", "Select Player",batter_dict_ha,selectize=True)
if input.my_tabs() == 'A':
#test_df = test_df[test_df.pitcher == 'Chris Bassitt'].append(test_df[test_df.pitcher != 'Chris Bassitt'])
#batter_dict = exit_velo_df_aaa.set_index('batter_id')['batter_name'].to_dict()
return ui.input_select("id", "Select Player",batter_dict_a,selectize=True)
@output
@render.plot(alt="A histogram")
@reactive.event(input.go, ignore_none=False)
def plot_mlb():
rbf.rolling_plot(df = exit_velo_df_codes[exit_velo_df_codes['level']==input.my_tabs()],
df_summ = exit_velo_df_codes_summ[exit_velo_df_codes_summ['level']==input.my_tabs()],
player_id = input.id(),
stat_id = input.stat_id(),
batter_dict = batter_dict_mlb,
window_select = input.n(),
level_id = input.my_tabs())
@output
@render.plot(alt="A histogram")
@reactive.event(input.go, ignore_none=False)
def plot_aaa():
rbf.rolling_plot(df = exit_velo_df_codes[exit_velo_df_codes['level']==input.my_tabs()],
df_summ = exit_velo_df_codes_summ[exit_velo_df_codes_summ['level']==input.my_tabs()],
player_id = input.id(),
stat_id = input.stat_id(),
batter_dict = batter_dict_aaa,
window_select = input.n(),
level_id = input.my_tabs())
@output
@render.plot(alt="A histogram")
@reactive.event(input.go, ignore_none=False)
def plot_aa():
rbf.rolling_plot(df = exit_velo_df_codes[exit_velo_df_codes['level']==input.my_tabs()],
df_summ = exit_velo_df_codes_summ[exit_velo_df_codes_summ['level']==input.my_tabs()],
player_id = input.id(),
stat_id = input.stat_id(),
batter_dict = batter_dict_aa,
window_select = input.n(),
level_id = input.my_tabs())
@output
@render.plot(alt="A histogram")
@reactive.event(input.go, ignore_none=False)
def plot_ha():
rbf.rolling_plot(df = exit_velo_df_codes[exit_velo_df_codes['level']==input.my_tabs()],
df_summ = exit_velo_df_codes_summ[exit_velo_df_codes_summ['level']==input.my_tabs()],
player_id = input.id(),
stat_id = input.stat_id(),
batter_dict = batter_dict_ha,
window_select = input.n(),
level_id = input.my_tabs())
@output
@render.plot(alt="A histogram")
@reactive.event(input.go, ignore_none=False)
def plot_a():
rbf.rolling_plot(df = exit_velo_df_codes[exit_velo_df_codes['level']==input.my_tabs()],
df_summ = exit_velo_df_codes_summ[exit_velo_df_codes_summ['level']==input.my_tabs()],
player_id = input.id(),
stat_id = input.stat_id(),
batter_dict = batter_dict_a,
window_select = input.n(),
level_id = input.my_tabs())
app = App(
ui.page_fluid(
ui.page_sidebar(
ui.sidebar(
ui.tags.h5("MLB & MiLB Rolling Batter Plot"),
ui.tags.i("Baseball Analytics and Visualizations"),
ui.div(
"By: ",
ui.tags.a(
"@TJStats",
href="https://x.com/TJStats",
target="_blank"
)
),
ui.tags.p(
ui.tags.a(
"Support me on Patreon for more baseball content",
href="https://www.patreon.com/TJ_Stats",
target="_blank"
)
),
ui.row(
ui.output_ui('test', 'Select Player'), # You may need to double check this line too
ui.input_select("stat_id", "Select Stat", plot_dict_small, width=1, size=1),
ui.input_numeric("n", "Rolling Window Size", value=50),
ui.input_action_button("go", "Generate", class_="btn-primary"),
ui.output_table("result")
)
,width='500px'),
ui.navset_tab(
ui.nav("MLB", ui.output_plot("plot_mlb", height="1000px", width="1000px")),
ui.nav("AAA", ui.output_plot("plot_aaa", height="1000px", width="1000px")),
ui.nav("AA", ui.output_plot("plot_aa", height="1000px", width="1000px")),
ui.nav("A+", ui.output_plot("plot_ha", height="1000px", width="1000px")),
ui.nav("A", ui.output_plot("plot_a", height="1000px", width="1000px")),
id="my_tabs"
)
)
),
server # ✅ server passed cleanly
)