def populate_pitch_type_perc(app, json_folder): with tqdm( total=len(JSON_FILE_MAP), desc="Populating percentiles table...", unit="file", mininterval=0.12, maxinterval=5, unit_scale=True, ncols=90, ) as pbar: for pitch_thrown, filename in JSON_FILE_MAP.items(): json_file = json_folder.joinpath(filename) for stat_name, stat_map in json.loads( json_file.read_text()).items(): for pitch_type_abbrev, pitch_type_map in stat_map.items(): pitch_type = PitchType.from_abbrev(pitch_type_abbrev) if PitchType.PERCENTILES & pitch_type == pitch_type: for percentile, stat_value in pitch_type_map.items(): percentile_dict = { "stat_name": stat_name, "pitch_type": pitch_type_abbrev, "thrown_r": pitch_thrown == "thrown_r", "thrown_l": pitch_thrown == "thrown_l", "thrown_both": pitch_thrown == "thrown_both", "percentile": percentile, "stat_value": stat_value, } app.db_session.add( PitchTypePercentile(**percentile_dict)) pbar.update() app.db_session.commit() return Result.Ok()
def _get_pitchfx_metrics(cls, pfx_metrics: RowDict, decimal_precision: int = 3) -> PitchFxMetricsDict: dc_fields = get_field_types(cls) pitchfx_metrics_dict = { k: round(v, decimal_precision) if dc_fields[k] is float else bool(v) if dc_fields[k] is bool else v for k, v in pfx_metrics.items() if v and k in dc_fields } pitchfx_metrics_dict["pitch_type"] = ( PitchType(pfx_metrics["pitch_type_int"]) if "pitch_type_int" in pfx_metrics else PitchType.from_abbrev(pfx_metrics["pitch_type"]) if "pitch_type" in pfx_metrics else None) pitchfx_metrics_dict["pitch_type_int"] = int( pitchfx_metrics_dict.get("pitch_type", 0)) return pitchfx_metrics_dict
def from_query_results( cls, all_pt_results: RowDict, each_pt_results: List[RowDict]) -> PitchFxMetricsCollection: metrics_collection = _get_pitchfx_metrics_for_all_pitch_types( all_pt_results) metrics_collection[ "pitch_type_metrics"] = _get_pitchfx_metrics_for_each_pitch_type( each_pt_results) metrics_collection["pitch_type_int"] = _get_all_pitch_types_int( metrics_collection["pitch_type_metrics"]) metrics_collection["pitch_type"] = PitchType( metrics_collection["pitch_type_int"]) return from_dict(data_class=cls, data=metrics_collection)
def _create_pfx_metrics_for_each_pitch_type(self): all_pitch_types = PitchType(sum({p.pitch_type_int for p in self.pfx})) valid_pfx_metrics, outlier_pitch_types = [], [] for pitch_type in all_pitch_types: pfx_for_pitch_type = list( filter(lambda x: x.mlbam_pitch_name == str(pitch_type), self.pfx)) percent = round(len(pfx_for_pitch_type) / float(len(self.pfx)), 3) if self.remove_outliers and percent < 0.01: outlier_pitch_types.append(str(pitch_type)) continue pfx_metrics = PitchFxMetrics(deepcopy(pfx_for_pitch_type), self.mlb_id, self.p_throws, self.bat_stand) valid_pfx_metrics.append(pfx_metrics) valid_pfx_metrics = self._sort_by_percent_thrown(valid_pfx_metrics) return (valid_pfx_metrics, outlier_pitch_types)
def pitch_mix(self) -> List[Dict[str, str]]: return [{ "pitch_type": PitchType.from_abbrev(pitch_type).print_name, "usage": metrics.get_usage_stats(), } for pitch_type, metrics in self.metrics_by_pitch_type.items()]
def pitch_type(self) -> List[PitchType]: return PitchType(self.pitch_type_int)
def test_pitchfx_metrics_career(vig_app): pfx_metrics_career_ALL_dict = { "avg": 0.0, "avg_break_angle": 0.0, "avg_break_length": 0.0, "avg_break_y": 0.0, "avg_extension": 0.0, "avg_hit_distance": 328.0, "avg_launch_angle": 27.0, "avg_launch_speed": 85.3, "avg_pfx_x": 0.0, "avg_pfx_z": 0.0, "avg_plate_time": 0.0, "avg_px": 0.0, "avg_pz": 0.0, "avg_speed": 0.0, "avg_spin_direction": 0.0, "avg_spin_rate": 0.0, "barrel_rate": 0.0, "bb_rate": 0.0, "called_strike_rate": 0.294, "contact_rate": 0.667, "csw_rate": 0.412, "fly_ball_rate": 0.0, "ground_ball_rate": 0.0, "hard_hit_rate": 0.0, "hr_per_fb": 0.0, "iso": 0.0, "k_rate": 0.667, "line_drive_rate": 1.0, "medium_hit_rate": 1.0, "mlb_id": 571882, "o_contact_rate": 0.667, "o_swing_rate": 0.3, "obp": 0.0, "ops": 0.0, "p_throws": "R", "percent": 1.0, "pitch_type": PitchType(32803), "pitch_type_int": 32803, "popup_rate": 0.0, "slg": 0.0, "soft_hit_rate": 0.0, "swing_rate": 0.353, "swinging_strike_rate": 0.118, "total_at_bats": 3, "total_balls_in_play": 1, "total_barrels": 0, "total_bb": 0, "total_called_strikes": 5, "total_contact_inside_zone": 2, "total_contact_outside_zone": 2, "total_doubles": 0, "total_errors": 0, "total_fly_balls": 0, "total_ground_balls": 0, "total_hard_hits": 0, "total_hbp": 0, "total_hits": 0, "total_homeruns": 0, "total_ibb": 0, "total_inside_strike_zone": 7, "total_k": 2, "total_line_drives": 1, "total_medium_hits": 1, "total_outs": 3, "total_outside_strike_zone": 10, "total_pa": 3, "total_pitches": 17, "total_popups": 0, "total_sac_fly": 0, "total_sac_hit": 0, "total_singles": 0, "total_soft_hits": 0, "total_swinging_strikes": 2, "total_swings": 6, "total_swings_inside_zone": 3, "total_swings_made_contact": 4, "total_swings_outside_zone": 3, "total_triples": 0, "whiff_rate": 0.333, "z_contact_rate": 0.667, "z_swing_rate": 0.429, "zone_rate": 0.412, } pfx_metrics_career_CU_dict = { "avg": 0.0, "avg_break_angle": 5.4, "avg_break_length": 13.2, "avg_break_y": 24.0, "avg_extension": 5.822, "avg_hit_distance": 0.0, "avg_launch_angle": 0.0, "avg_launch_speed": 0.0, "avg_pfx_x": 3.045, "avg_pfx_z": -5.965, "avg_plate_time": 0.502, "avg_px": 0.23, "avg_pz": 1.587, "avg_speed": 76.175, "avg_spin_direction": 26.75, "avg_spin_rate": 2056.25, "barrel_rate": 0.0, "bb_rate": 0.0, "called_strike_rate": 0.5, "contact_rate": 0.0, "csw_rate": 0.5, "fly_ball_rate": 0.0, "ground_ball_rate": 0.0, "hard_hit_rate": 0.0, "hr_per_fb": 0.0, "iso": 0.0, "k_rate": 0.0, "line_drive_rate": 0.0, "medium_hit_rate": 0.0, "mlb_id": 571882, "o_contact_rate": 0.0, "o_swing_rate": 0.0, "obp": 0.0, "ops": 0.0, "p_throws": "R", "percent": 0.235, "pitch_type": PitchType.CURVEBALL, "pitch_type_int": 2, "popup_rate": 0.0, "slg": 0.0, "soft_hit_rate": 0.0, "swing_rate": 0.0, "swinging_strike_rate": 0.0, "total_at_bats": 0, "total_balls_in_play": 0, "total_barrels": 0, "total_bb": 0, "total_called_strikes": 2, "total_contact_inside_zone": 0, "total_contact_outside_zone": 0, "total_doubles": 0, "total_errors": 0, "total_fly_balls": 0, "total_ground_balls": 0, "total_hard_hits": 0, "total_hbp": 0, "total_hits": 0, "total_homeruns": 0, "total_ibb": 0, "total_inside_strike_zone": 2, "total_k": 0, "total_line_drives": 0, "total_medium_hits": 0, "total_outs": 0, "total_outside_strike_zone": 2, "total_pa": 0, "total_pitches": 4, "total_popups": 0, "total_sac_fly": 0, "total_sac_hit": 0, "total_singles": 0, "total_soft_hits": 0, "total_swinging_strikes": 0, "total_swings": 0, "total_swings_inside_zone": 0, "total_swings_made_contact": 0, "total_swings_outside_zone": 0, "total_triples": 0, "whiff_rate": 0.0, "z_contact_rate": 0.0, "z_swing_rate": 0.0, "zone_rate": 0.5, } pfx_metrics_career_FF_dict = { "avg": 0.0, "avg_break_angle": 8.4, "avg_break_length": 3.6, "avg_break_y": 24.0, "avg_extension": 6.613, "avg_hit_distance": 328.0, "avg_launch_angle": 27.0, "avg_launch_speed": 85.3, "avg_pfx_x": -1.252, "avg_pfx_z": 8.577, "avg_plate_time": 0.398, "avg_px": 0.048, "avg_pz": 3.302, "avg_speed": 94.017, "avg_spin_direction": 186.333, "avg_spin_rate": 2150.0, "barrel_rate": 0.0, "bb_rate": 0.0, "called_strike_rate": 0.167, "contact_rate": 1.0, "csw_rate": 0.167, "fly_ball_rate": 0.0, "ground_ball_rate": 0.0, "hard_hit_rate": 0.0, "hr_per_fb": 0.0, "iso": 0.0, "k_rate": 0.0, "line_drive_rate": 1.0, "medium_hit_rate": 1.0, "mlb_id": 571882, "o_contact_rate": 1.0, "o_swing_rate": 0.2, "obp": 0.0, "ops": 0.0, "p_throws": "R", "percent": 0.353, "pitch_type": PitchType.FOUR_SEAM_FASTBALL, "pitch_type_int": 32, "popup_rate": 0.0, "slg": 0.0, "soft_hit_rate": 0.0, "swing_rate": 0.333, "swinging_strike_rate": 0.0, "total_at_bats": 1, "total_balls_in_play": 1, "total_barrels": 0, "total_bb": 0, "total_called_strikes": 1, "total_contact_inside_zone": 1, "total_contact_outside_zone": 1, "total_doubles": 0, "total_errors": 0, "total_fly_balls": 0, "total_ground_balls": 0, "total_hard_hits": 0, "total_hbp": 0, "total_hits": 0, "total_homeruns": 0, "total_ibb": 0, "total_inside_strike_zone": 1, "total_k": 0, "total_line_drives": 1, "total_medium_hits": 1, "total_outs": 1, "total_outside_strike_zone": 5, "total_pa": 1, "total_pitches": 6, "total_popups": 0, "total_sac_fly": 0, "total_sac_hit": 0, "total_singles": 0, "total_soft_hits": 0, "total_swinging_strikes": 0, "total_swings": 2, "total_swings_inside_zone": 1, "total_swings_made_contact": 2, "total_swings_outside_zone": 1, "total_triples": 0, "whiff_rate": 0.0, "z_contact_rate": 1.0, "z_swing_rate": 1.0, "zone_rate": 0.167, } pfx_metrics_career_CH_dict = { "avg": 0.0, "avg_break_angle": 22.8, "avg_break_length": 6.4, "avg_break_y": 24.0, "avg_extension": 6.553, "avg_hit_distance": 0.0, "avg_launch_angle": 0.0, "avg_launch_speed": 0.0, "avg_pfx_x": -6.377, "avg_pfx_z": 6.993, "avg_plate_time": 0.437, "avg_px": -0.2, "avg_pz": 2.37, "avg_speed": 85.833, "avg_spin_direction": 222.0, "avg_spin_rate": 1967.333, "barrel_rate": 0.0, "bb_rate": 0.0, "called_strike_rate": 0.333, "contact_rate": 0.5, "csw_rate": 0.667, "fly_ball_rate": 0.0, "ground_ball_rate": 0.0, "hard_hit_rate": 0.0, "hr_per_fb": 0.0, "iso": 0.0, "k_rate": 1.0, "line_drive_rate": 0.0, "medium_hit_rate": 0.0, "mlb_id": 571882, "o_contact_rate": 0.0, "o_swing_rate": 0.0, "obp": 0.0, "ops": 0.0, "p_throws": "R", "percent": 0.176, "pitch_type": PitchType.CHANGEUP, "pitch_type_int": 1, "popup_rate": 0.0, "slg": 0.0, "soft_hit_rate": 0.0, "swing_rate": 0.667, "swinging_strike_rate": 0.333, "total_at_bats": 1, "total_balls_in_play": 0, "total_barrels": 0, "total_bb": 0, "total_called_strikes": 1, "total_contact_inside_zone": 1, "total_contact_outside_zone": 0, "total_doubles": 0, "total_errors": 0, "total_fly_balls": 0, "total_ground_balls": 0, "total_hard_hits": 0, "total_hbp": 0, "total_hits": 0, "total_homeruns": 0, "total_ibb": 0, "total_inside_strike_zone": 3, "total_k": 1, "total_line_drives": 0, "total_medium_hits": 0, "total_outs": 1, "total_outside_strike_zone": 0, "total_pa": 1, "total_pitches": 3, "total_popups": 0, "total_sac_fly": 0, "total_sac_hit": 0, "total_singles": 0, "total_soft_hits": 0, "total_swinging_strikes": 1, "total_swings": 2, "total_swings_inside_zone": 2, "total_swings_made_contact": 1, "total_swings_outside_zone": 0, "total_triples": 0, "whiff_rate": 0.5, "z_contact_rate": 0.5, "z_swing_rate": 0.667, "zone_rate": 1.0, } pfx_metrics_career_SL_dict = { "avg": 0.0, "avg_break_angle": 6.0, "avg_break_length": 9.6, "avg_break_y": 24.0, "avg_extension": 6.075, "avg_hit_distance": 0.0, "avg_launch_angle": 0.0, "avg_launch_speed": 0.0, "avg_pfx_x": 2.285, "avg_pfx_z": -1.922, "avg_plate_time": 0.45, "avg_px": 0.407, "avg_pz": 1.35, "avg_speed": 83.725, "avg_spin_direction": 48.0, "avg_spin_rate": 2281.0, "barrel_rate": 0.0, "bb_rate": 0.0, "called_strike_rate": 0.25, "contact_rate": 0.5, "csw_rate": 0.5, "fly_ball_rate": 0.0, "ground_ball_rate": 0.0, "hard_hit_rate": 0.0, "hr_per_fb": 0.0, "iso": 0.0, "k_rate": 1.0, "line_drive_rate": 0.0, "medium_hit_rate": 0.0, "mlb_id": 571882, "o_contact_rate": 0.5, "o_swing_rate": 0.667, "obp": 0.0, "ops": 0.0, "p_throws": "R", "percent": 0.235, "pitch_type": PitchType.SLIDER, "pitch_type_int": 32768, "popup_rate": 0.0, "slg": 0.0, "soft_hit_rate": 0.0, "swing_rate": 0.5, "swinging_strike_rate": 0.25, "total_at_bats": 1, "total_balls_in_play": 0, "total_barrels": 0, "total_bb": 0, "total_called_strikes": 1, "total_contact_inside_zone": 0, "total_contact_outside_zone": 1, "total_doubles": 0, "total_errors": 0, "total_fly_balls": 0, "total_ground_balls": 0, "total_hard_hits": 0, "total_hbp": 0, "total_hits": 0, "total_homeruns": 0, "total_ibb": 0, "total_inside_strike_zone": 1, "total_k": 1, "total_line_drives": 0, "total_medium_hits": 0, "total_outs": 1, "total_outside_strike_zone": 3, "total_pa": 1, "total_pitches": 4, "total_popups": 0, "total_sac_fly": 0, "total_sac_hit": 0, "total_singles": 0, "total_soft_hits": 0, "total_swinging_strikes": 1, "total_swings": 2, "total_swings_inside_zone": 0, "total_swings_made_contact": 1, "total_swings_outside_zone": 2, "total_triples": 0, "whiff_rate": 0.5, "z_contact_rate": 0.0, "z_swing_rate": 0.0, "zone_rate": 0.25, } pfx_metrics_career_by_pitchtype = [ pfx_metrics_career_CU_dict, pfx_metrics_career_FF_dict, pfx_metrics_career_CH_dict, pfx_metrics_career_SL_dict, ] pfx_metrics_career_ALL = PitchFxMetricsCollection.from_query_results( pfx_metrics_career_ALL_dict, pfx_metrics_career_by_pitchtype) assert isinstance(pfx_metrics_career_ALL, PitchFxMetricsCollection) player_data = PlayerData(vig_app, 571882) assert player_data.pfx_pitching_metrics_vs_all_for_career assert player_data.percentiles_for_pitch_types_for_career assert player_data.pfx_pitching_metrics_vs_rhb_for_career assert player_data.percentiles_for_pitch_types_vs_rhb_for_career assert player_data.pfx_pitching_metrics_vs_lhb_for_career assert player_data.percentiles_for_pitch_types_vs_lhb_for_career assert player_data.pfx_pitching_metrics_vs_all_by_year assert player_data.percentiles_for_pitch_types_by_year assert player_data.pfx_pitching_metrics_vs_rhb_by_year assert player_data.percentiles_for_pitch_types_vs_rhb_by_year assert player_data.pfx_pitching_metrics_vs_lhb_by_year assert player_data.percentiles_for_pitch_types_vs_lhb_by_year assert player_data.get_pfx_pitching_metrics_vs_all_for_season(2019) assert player_data.get_pfx_pitching_metrics_vs_rhb_for_season(2019) assert player_data.get_pfx_pitching_metrics_vs_lhb_for_season(2019) assert player_data.get_pfx_pitching_metrics_vs_all_for_game(BBREF_GAME_ID) assert player_data.get_pfx_pitching_metrics_vs_rhb_for_game(BBREF_GAME_ID) assert player_data.get_pfx_pitching_metrics_vs_lhb_for_game(BBREF_GAME_ID) assert player_data.get_all_pfx_career_data() assert player_data.get_all_pfx_yearly_data() player_data = PlayerData(vig_app, 600303) assert player_data.pfx_batting_metrics_vs_all_for_career assert player_data.pfx_batting_metrics_vs_rhp_for_career assert player_data.pfx_batting_metrics_vs_lhp_for_career assert player_data.pfx_batting_metrics_vs_rhp_as_lhb_for_career assert player_data.pfx_batting_metrics_vs_lhp_as_lhb_for_career assert player_data.pfx_batting_metrics_by_year assert player_data.get_pfx_batting_metrics_vs_all_for_game(BBREF_GAME_ID) assert player_data.get_pfx_batting_metrics_vs_rhp_for_game(BBREF_GAME_ID) assert player_data.get_pfx_batting_metrics_vs_lhp_for_game(BBREF_GAME_ID) assert player_data.get_pfx_batting_metrics_vs_rhp_as_lhb_for_game( BBREF_GAME_ID) assert player_data.get_pfx_batting_metrics_vs_lhp_as_lhb_for_game( BBREF_GAME_ID) assert player_data.get_all_pfx_batting_career_data() assert player_data.get_all_pfx_batting_yearly_data() player_data = PlayerData(vig_app, 545361) assert player_data.pfx_batting_metrics_vs_rhp_as_rhb_for_career assert player_data.pfx_batting_metrics_vs_lhp_as_rhb_for_career assert player_data.get_pfx_batting_metrics_vs_rhp_as_rhb_for_game( BBREF_GAME_ID) assert player_data.get_pfx_batting_metrics_vs_lhp_as_rhb_for_game( BBREF_GAME_ID)
def _get_pitch_types_sorted(metrics_by_pitch_type): unsorted = list(metrics_by_pitch_type.values()) return [ str(PitchType(m["pitch_type_int"])) for m in sorted(unsorted, key=lambda x: x["percent"], reverse=True) ]
def as_dict(self): """Convert pitch log to a dictionary.""" return { "__brooks_pitchfx_data__": True, "pitcher_name": self.pitcher_name, "pitch_app_id": self.pitch_app_id, "pitcher_id": self.pitcher_id, "batter_id": self.batter_id, "pitcher_team_id_bb": self.pitcher_team_id_bb, "opponent_team_id_bb": self.opponent_team_id_bb, "bb_game_id": self.bb_game_id, "bbref_game_id": self.bbref_game_id, "park_sv_id": self.park_sv_id, "play_guid": self.play_guid, "ab_total": self.ab_total, "ab_count": self.ab_count, "ab_id": self.ab_id, "des": self.des, "type": self.type, "id": self.id, "sz_top": self.sz_top, "sz_bot": self.sz_bot, "mlbam_pitch_name": self.mlbam_pitch_name, "zone_location": self.zone_location, "stand": self.stand, "strikes": self.strikes, "balls": self.balls, "p_throws": self.p_throws, "pdes": self.pdes, "inning": self.inning, "pfx_x": self.pfx_x, "pfx_z": self.pfx_z, "x0": self.x0, "y0": self.y0, "z0": self.z0, "vx0": self.vx0, "vy0": self.vy0, "vz0": self.vz0, "ax": self.ax, "ay": self.ay, "az": self.az, "start_speed": self.start_speed, "px": self.px, "pz": self.pz, "plate_time": self.plate_time, "extension": self.extension, "break_angle": self.break_angle, "break_length": self.break_length, "break_y": self.break_y, "spin_rate": self.spin_rate, "spin_direction": self.spin_direction, "launch_speed": self.launch_speed, "launch_angle": self.launch_angle, "total_distance": self.total_distance, "trajectory": self.trajectory, "hardness": self.hardness, "location": self.location, "coord_x": self.coord_x, "coord_y": self.coord_y, "game_start_time_str": self.game_start_time_str, "time_pitch_thrown_str": self.get_time_pitch_thrown_str(), "has_zone_location": self.has_zone_location, "batter_did_swing": self.batter_did_swing, "batter_made_contact": self.batter_made_contact, "called_strike": self.called_strike, "swinging_strike": self.swinging_strike, "inside_strike_zone": self.inside_strike_zone, "outside_strike_zone": self.outside_strike_zone, "swing_inside_zone": self.swing_inside_zone, "swing_outside_zone": self.swing_outside_zone, "contact_inside_zone": self.contact_inside_zone, "contact_outside_zone": self.contact_outside_zone, "is_in_play": self.is_in_play, "is_ground_ball": self.is_ground_ball, "is_fly_ball": self.is_fly_ball, "is_line_drive": self.is_line_drive, "is_popup": self.is_popup, "is_hard_hit": self.is_hard_hit, "is_medium_hit": self.is_medium_hit, "is_soft_hit": self.is_soft_hit, "is_barreled": self.is_barreled, "is_final_pitch_of_ab": self.is_final_pitch_of_ab, "ab_result_out": self.is_final_pitch_of_ab, "ab_result_hit": self.is_final_pitch_of_ab, "ab_result_single": self.is_final_pitch_of_ab, "ab_result_double": self.is_final_pitch_of_ab, "ab_result_triple": self.is_final_pitch_of_ab, "ab_result_homerun": self.is_final_pitch_of_ab, "ab_result_bb": self.is_final_pitch_of_ab, "ab_result_ibb": self.is_final_pitch_of_ab, "ab_result_k": self.is_final_pitch_of_ab, "ab_result_hbp": self.is_final_pitch_of_ab, "ab_result_error": self.ab_result_error, "ab_result_sac_hit": self.is_final_pitch_of_ab, "ab_result_sac_fly": self.is_final_pitch_of_ab, "ab_result_unclear": self.ab_result_unclear, "pbp_play_result": self.pbp_play_result, "pbp_runs_outs_result": self.pbp_runs_outs_result, "pitch_type_int": int(PitchType.from_abbrev(self.mlbam_pitch_name)), "is_patched": self.is_patched, "is_invalid_ibb": self.is_invalid_ibb, "is_out_of_sequence": self.is_out_of_sequence, }
def pitch_type(self) -> PitchType: return PitchType(self.pitch_type_int)