From c2fdf02f6b7270386d39579fcc0cdc6996fcce4a Mon Sep 17 00:00:00 2001 From: ss77995ss Date: Fri, 27 Dec 2024 07:37:23 +0800 Subject: [PATCH 1/2] feat(Statcast): Implement Extra Bases Taken function --- .python-version | 1 + src/baseball_stats_python/__init__.py | 4 ++ .../statcast/runner_extra_bases_taken.py | 59 +++++++++++++++++++ 3 files changed, 64 insertions(+) create mode 100644 .python-version create mode 100644 src/baseball_stats_python/statcast/runner_extra_bases_taken.py diff --git a/.python-version b/.python-version new file mode 100644 index 0000000..1e33456 --- /dev/null +++ b/.python-version @@ -0,0 +1 @@ +3.11.2 diff --git a/src/baseball_stats_python/__init__.py b/src/baseball_stats_python/__init__.py index 0ab6095..5257fa0 100644 --- a/src/baseball_stats_python/__init__.py +++ b/src/baseball_stats_python/__init__.py @@ -5,6 +5,8 @@ minor_statcast_search, ) from .statcast.mlbam_id_search import mlbam_id_search +from .statcast.runner_basestealing import runner_basestealing +from .statcast.runner_extra_bases_taken import runner_extra_bases_taken from .statcast.statcast_search import ( statcast_batter_search, statcast_pitcher_search, @@ -20,4 +22,6 @@ 'minor_statcast_batter_search', 'mlbam_id_search', 'catcher_throwing', + 'runner_basestealing', + 'runner_extra_bases_taken', ] diff --git a/src/baseball_stats_python/statcast/runner_extra_bases_taken.py b/src/baseball_stats_python/statcast/runner_extra_bases_taken.py new file mode 100644 index 0000000..15f04c7 --- /dev/null +++ b/src/baseball_stats_python/statcast/runner_extra_bases_taken.py @@ -0,0 +1,59 @@ +import pandas as pd +import requests + +from ..constants import DEFAULT_SEASON +from ..enums.statcast_leaderboard import GameType + +session = requests.Session() + +API_URL = 'https://baseballsavant.mlb.com/leaderboard/services/baserunning' + + +def runner_extra_bases_taken( + runner_id: str, + game_type: str | GameType = GameType.REGULAR_SEASON, + season: str = str(DEFAULT_SEASON), +) -> pd.DataFrame: + """ + Get extra base taken data from each advanced opportunity for a specific runner. + ref: https://baseballsavant.mlb.com/leaderboard/baserunning + + Args: + runner_id (str): The MLBAM ID of the runner. (Required) + game_type (str | GameType): The game type to filter by. Default is "Regular". + season (str): The season to filter by. The earliest season available is 2016. + Returns: + pd.DataFrame: A DataFrame containing the baserunning data. + """ + + if not runner_id: + raise ValueError('runner_id is required') + + if not isinstance(game_type, str) and not isinstance(game_type, GameType): + raise ValueError(f'Invalid type for game_type: {type(game_type)}') + + if not GameType.has_value(game_type): + raise ValueError(f'Invalid game type: {game_type}') + + if int(season) < 2016: + raise ValueError( + f'Invalid season: {season}, The earliest season available is 2016' + ) + + params = { + 'game_type': game_type, + 'season_start': season, + 'season_end': season, + 'n': 0, + } + + response = session.get(f'{API_URL}/{runner_id}', params=params) + + if response.status_code == 200: + result = response.json() + df = pd.DataFrame(result['data']) + return df + else: + raise Exception( + f'Failed to fetch data: {response.status_code} - {response.text}' + ) From 7b918f9d0d8976efd01bdc35890d399f50519fc5 Mon Sep 17 00:00:00 2001 From: ss77995ss Date: Fri, 27 Dec 2024 07:43:19 +0800 Subject: [PATCH 2/2] docs(Statcast): Add `runner_extra_bases_taken` function documentation --- docs/runner_extra_bases_taken.md | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 docs/runner_extra_bases_taken.md diff --git a/docs/runner_extra_bases_taken.md b/docs/runner_extra_bases_taken.md new file mode 100644 index 0000000..c1728b0 --- /dev/null +++ b/docs/runner_extra_bases_taken.md @@ -0,0 +1,32 @@ +# Statcast Runner Extra Bases Taken + +## `runner_extra_bases_taken` + +Function to get extra base taken data from each advanced opportunity for a specific runner. Based on Baseball Savant's [Runner Extra Bases Taken](https://baseballsavant.mlb.com/leaderboard/baserunning). + +**Examples** + +```python +from baseball_stats_python import runner_extra_bases_taken + +# Get Corbin Carroll's runner extra bases taken data +runner_extra_bases_taken('682998') + +# Get Corbin Carroll's runner extra bases taken data in 2023 +runner_extra_bases_taken('682998', season='2023') + +# Get Corbin Carroll's runner extra bases taken data in playoffs +runner_extra_bases_taken('682998', game_type=GameType.PLAYOFFS) +``` + +**Arguments** + +| Argument | Data Type | Description | +| -------------------- | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| runner_id (Required) | `str` | The MLBAM ID of the runner. | +| game_type | `str` or `GameType` | The game type to filter by. Can be `R` for regular season, `PO` for playoffs, or `All` for all games. Check enum [GameType](../enums/statcast_leaderboard.py) | +| season | `str` | The season to filter by. The earliest season available is 2016. | + +**Return** + +A DataFrame with columns that related to the [Runner Extra Bases Taken](https://baseballsavant.mlb.com/leaderboard/baserunning) leaderboard. The DataFrame will represent each advanced opportunity for a specific runner which contains data like `fielder_runs`, `runner_runs`, `base_out_text`, etc.