Skip to content

Commit

Permalink
Added bat tracking and fixed Outs Above Average Leaderboard link (#430)
Browse files Browse the repository at this point in the history
  • Loading branch information
LukeFabric authored Jun 16, 2024
1 parent ae2da3a commit 6deb041
Show file tree
Hide file tree
Showing 7 changed files with 58 additions and 6 deletions.
3 changes: 2 additions & 1 deletion pybaseball/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@
statcast_batter_exitvelo_barrels,
statcast_batter_expected_stats,
statcast_batter_percentile_ranks,
statcast_batter_pitch_arsenal
statcast_batter_pitch_arsenal,
statcast_batter_bat_tracking
)
from .statcast_running import statcast_sprint_speed, statcast_running_splits
from .statcast_fielding import (
Expand Down
16 changes: 16 additions & 0 deletions pybaseball/statcast_batter.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,3 +92,19 @@ def statcast_batter_pitch_arsenal(year: int, minPA: int = 25) -> pd.DataFrame:
data = pd.read_csv(io.StringIO(res.decode('utf-8')))
data = sanitize_statcast_columns(data)
return data
@cache.df_cache()
def statcast_batter_bat_tracking(year: int, minSwings: Union[int,str] = "q" ) -> pd.DataFrame:
"""
Retrieves a player's bat tracking data for a given year.
ARGUMENTS
year: The year for which you which to retrieve the bat tracking data. Format: YYYY.
minSwings: The minimum number of competitive swings for wach player. If a player falls below this threshold,
they will be excluded from the results. If no value is specified, the default number of competitive swings
is qualified.
"""
url = f"https://baseballsavant.mlb.com/leaderboard/bat-tracking?attackZone=&batSide=&contactType=&count=&dateStart={year}-01-01&dateEnd={year}-12-31&gameType=&isHardHit=&minSwings={minSwings}&minGroupSwings=1&pitchHand=&pitchType=&seasonStart=&seasonEnd=&team=&type=batter&csv=true"
res = requests.get(url, timeout=None).content
data = pd.read_csv(io.StringIO(res.decode('utf-8')))
data = sanitize_statcast_columns(data)
return data
2 changes: 1 addition & 1 deletion pybaseball/statcast_fielding.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ def statcast_outs_above_average(year: int, pos: Union[int, str], min_att: Union[
# catcher is not included in this leaderboard
if pos == "2":
raise ValueError("This particular leaderboard does not include catchers!")
url = f"https://baseballsavant.mlb.com/leaderboard/outs_above_average?type={view}&year={year}&team=&range=year&min={min_att}&pos={pos}&roles=&viz=show&csv=true"
url = f"https://baseballsavant.mlb.com/leaderboard/outs_above_average?type={view}&startYear={year}&endYear={year}&split=no&team=&range=year&min={min_att}&pos={pos}&roles=&viz=hide&csv=true"
res = requests.get(url, timeout=None).content
data = pd.read_csv(io.StringIO(res.decode('utf-8')))
data = sanitize_statcast_columns(data)
Expand Down
15 changes: 15 additions & 0 deletions pybaseball/statcast_pitcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -201,3 +201,18 @@ def statcast_pitcher_spin_dir_comp(year: int, pitch_a: str = "FF", pitch_b: str
data = pd.read_csv(io.StringIO(res.decode('utf-8')))
data = sanitize_statcast_columns(data)
return data
@cache.df_cache()
def statcast_pitcher_bat_tracking(year: int, minSwings: Union[int,str] = "q") -> pd.DataFrame:
"""
Retrieves the bat tracking data against for pitchers.
ARGUMENTS
year: The year for which you wish to retreive bat tracking data. Format: YYYY
minSwings: The minimum number of swings batters have taken against a pitcher. If a pitcher falls
below the threshold, they will be excluded from the results. The default value is qualified.
"""
url = f"https://baseballsavant.mlb.com/leaderboard/bat-tracking?attackZone=&batSide=&contactType=&count=&dateStart={year}-01-01&dateEnd={year}-12-31&gameType=&isHardHit=&minSwings={minSwings}&minGroupSwings=1&pitchHand=&pitchType=&seasonStart=&seasonEnd=&team=&type=pitcher&csv=true"
res = requests.get(url, timeout=None).content
data = pd.read_csv(io.StringIO(res.decode('utf-8')))
data = sanitize_statcast_columns(data)
return data
13 changes: 12 additions & 1 deletion tests/integration/pybaseball/test_statcast_batter.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
statcast_batter_exitvelo_barrels,
statcast_batter_expected_stats,
statcast_batter_percentile_ranks,
statcast_batter_pitch_arsenal
statcast_batter_pitch_arsenal,
statcast_batter_bat_tracking
)


Expand Down Expand Up @@ -62,3 +63,13 @@ def test_statcast_batter_pitch_arsenal() -> None:
assert len(result.columns) == 21
assert len(result) > 0
assert len(result[result['pa'] < min_pa]) == 0
def test_statcast_batter_bat_tracking() -> None:
min_pa = 25
result: pd.DataFrame = statcast_batter_bat_tracking(2024, min_pa)

assert result is not None
assert not result.empty

assert len(result.columns) == 18
assert len(result) > 0
assert len(result[result['swings_competitive'] < min_pa]) == 0
4 changes: 2 additions & 2 deletions tests/integration/pybaseball/test_statcast_fielding.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ def test_statcast_outs_above_average() -> None:
assert result is not None
assert not result.empty

assert len(result.columns) == 17
assert len(result.columns) == 16
assert len(result) > 0

def test_statcast_outs_above_average_view() -> None:
Expand Down Expand Up @@ -101,4 +101,4 @@ def test_statcast_fielding_run_value() -> None:
assert len(result) > 0

#test_statcast_outs_above_average_view()
test_statcast_outs_above_average()
test_statcast_outs_above_average()
11 changes: 10 additions & 1 deletion tests/integration/pybaseball/test_statcast_pitcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@
statcast_pitcher_percentile_ranks,
statcast_pitcher_pitch_arsenal,
statcast_pitcher_pitch_movement,
statcast_pitcher_spin_dir_comp
statcast_pitcher_spin_dir_comp,
statcast_pitcher_bat_tracking
)


Expand Down Expand Up @@ -105,3 +106,11 @@ def test_statcast_pitcher_spin_dir_comp() -> None:

assert len(result.columns) == 30
assert len(result) > 100
def test_statcast_pitcher_bat_tracking() -> None:
result: pd.DataFrame = statcast_pitcher_bat_tracking(2024)

assert result is not None
assert not result.empty

assert len(result.columns) == 18
assert len(result) > 0

0 comments on commit 6deb041

Please sign in to comment.