Skip to content

Commit

Permalink
Merge pull request #841 from a-luna/patch-release/v0.6.2
Browse files Browse the repository at this point in the history
v0.6.2
  • Loading branch information
a-luna authored Sep 30, 2021
2 parents 0695fa4 + 172620d commit 96c7c91
Show file tree
Hide file tree
Showing 17 changed files with 488 additions and 268 deletions.
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "vig-node-deps",
"version": "0.6.1",
"version": "0.6.2",
"description": "This file is used for heroku deployment, the postbuild script below is called after each push to install the dependencies listed in the REAL package.json in the nightmarejs folder. Yes, I know that it is lame and hacky to have this root package.json file that exists solely to tap on the shoulder of another package.json and ask sheepishly to run freaking 'npm install' simply because heroku couldn't possibly manage the herculean feat of locating a package.json file anywhere but the root folder, but that's where we are and that's why this file exists.",
"scripts": {
"heroku-postbuild": "cd src/vigorish/nightmarejs && npm install"
Expand Down
81 changes: 65 additions & 16 deletions src/vigorish/data/metrics/bat_stats/bat_stats_metrics.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
from functools import cached_property
from typing import List
from typing import Dict, List, Union

import vigorish.database as db
from vigorish.enums import DefensePosition
from vigorish.util.list_helpers import group_and_sort_list
from vigorish.util.string_helpers import format_decimal_bat_stat


Expand All @@ -17,8 +18,6 @@ def __init__(
player_team_id_bbref: str = None,
opponent_team_id_bbref: str = None,
is_starter: bool = False,
bat_order_list: List[int] = None,
def_position_list: List[DefensePosition] = None,
stint_number: int = None,
) -> None:
self.year = year
Expand All @@ -29,8 +28,6 @@ def __init__(
self.player_team_id_bbref = team_id_bbref or player_team_id_bbref
self.opponent_team_id_bbref = opponent_team_id_bbref
self.is_starter = is_starter
self.bat_order_list = bat_order_list or []
self.def_position_list = def_position_list or []
self.stint_number = stint_number
self.changed_teams_midseason = False
self.all_stats_for_season = False
Expand Down Expand Up @@ -68,6 +65,24 @@ def __repr__(self) -> str:
def total_games(self) -> int:
return len(self.bat_stats)

@cached_property
def total_games_started(self) -> int:
return sum(bs.is_starter for bs in self.bat_stats)

@property
def total_games_subbed(self) -> int:
return self.total_games - self.total_games_started

@property
def percent_started(self) -> float:
percent_started = self.total_games_started / float(self.total_games)
return round(percent_started, ndigits=3)

@property
def percent_subbed(self) -> float:
percent_subbed = self.total_games_subbed / float(self.total_games)
return round(percent_subbed, ndigits=3)

@cached_property
def avg(self) -> float:
avg = self.hits / float(self.at_bats) if self.at_bats else 0.0
Expand Down Expand Up @@ -99,17 +114,17 @@ def iso(self) -> float:
@cached_property
def bb_rate(self) -> float:
bb_rate = self.bases_on_balls / float(self.plate_appearances) if self.plate_appearances else 0.0
return round(bb_rate, ndigits=1)
return round(bb_rate, ndigits=3)

@cached_property
def k_rate(self) -> float:
k_rate = self.strikeouts / float(self.plate_appearances) if self.plate_appearances else 0.0
return round(k_rate, ndigits=1)
return round(k_rate, ndigits=3)

@cached_property
def contact_rate(self) -> float:
cached_property = (self.at_bats - self.strikeouts) / float(self.at_bats) if self.at_bats else 0.0
return round(cached_property, ndigits=1)
return round(cached_property, ndigits=3)

@cached_property
def plate_appearances(self) -> int:
Expand Down Expand Up @@ -207,6 +222,26 @@ def re24_bat(self) -> float:
re24_bat = sum(bs.re24_bat for bs in self.bat_stats)
return round(re24_bat, ndigits=1)

@cached_property
def def_position_list(self) -> List[DefensePosition]:
return list({DefensePosition(int(bs.def_position)) for bs in self.bat_stats})

@cached_property
def def_position_metrics(self) -> List[Dict[str, Union[bool, int, float, DefensePosition]]]:
bat_stats_grouped = group_and_sort_list(self.bat_stats, "def_position", "date_id")
pos_counts = [get_pos_metrics(k, v, self.bat_stats) for k, v in bat_stats_grouped.items()]
return sorted(pos_counts, key=lambda x: x["percent"], reverse=True)

@cached_property
def bat_order_list(self) -> List[DefensePosition]:
return list({bs.bat_order for bs in self.bat_stats}) if self.bat_stats else []

@cached_property
def bat_order_metrics(self) -> List[Dict[str, Union[int, float]]]:
bat_orders_grouped = group_and_sort_list(self.bat_stats, "bat_order", "date_id")
order_number_counts = [get_bat_order_metrics(k, v, self.bat_stats) for k, v in bat_orders_grouped.items()]
return sorted(order_number_counts, key=lambda x: x["percent"], reverse=True)

def as_dict(self):
dict_keys = list(filter(lambda x: not x.startswith(("__", "as_")), dir(self)))
bat_stat_metrics_dict = {key: getattr(self, key) for key in dict_keys}
Expand All @@ -216,17 +251,31 @@ def as_dict(self):
return bat_stat_metrics_dict


def get_pos_metrics(
pos_number: str, pos_stats: List[db.BatStats], all_bat_stats: List[db.BatStats]
) -> Dict[str, Union[bool, int, float, DefensePosition]]:
def_pos = DefensePosition(int(pos_number))
return {
"def_pos": def_pos,
"is_starter": def_pos.is_starter,
"total_games": len(pos_stats),
"percent": round(len(pos_stats) / float(len(all_bat_stats)), 3) * 100,
}


def get_bat_order_metrics(
bat_order: str, bat_order_stats: List[db.BatStats], all_bat_stats: List[db.BatStats]
) -> Dict[str, Union[int, float]]:
return {
"bat_order": bat_order,
"total_games": len(bat_order_stats),
"percent": round(len(bat_order_stats) / float(len(all_bat_stats)), 3) * 100,
}


def _format_bat_order_list(bat_order_list: List[int]) -> str:
return ",".join(str(bat_order) for bat_order in bat_order_list)


def _format_def_position_list(def_position_list: List[int]) -> str:
return ",".join(str(DefensePosition(int(def_pos))) for def_pos in def_position_list)


# from vigorish.app import Vigorish
# from vigorish.enums import DefensePosition
# app = Vigorish()
# def_positions = [DefensePosition.SECOND_BASE, DefensePosition.SHORT_STOP]
# ball = app.scraped_data.get_bat_stats_for_defpos_for_season_for_all_teams(def_positions, 2021)
# bt = app.scraped_data.get_bat_stats_for_defpos_by_player_for_team(def_positions, "TOR", 2021)
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,6 @@ def for_lineup_spots_for_all_teams(self, bat_order_list: List[int], year: int) -
year=year,
team_id_bbref=team_id,
player_team_id_bbref=team_id,
bat_order_list=bat_order_list,
)
for team_id in list(TEAM_ID_MAP.keys())
]
Expand All @@ -91,7 +90,6 @@ def for_def_positions_for_all_teams(
year=year,
team_id_bbref=team_id,
player_team_id_bbref=team_id,
def_position_list=def_position_list,
)
for team_id in list(TEAM_ID_MAP.keys())
]
Expand Down
8 changes: 0 additions & 8 deletions src/vigorish/data/metrics/bat_stats/team_bat_stat_metrics.py
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,6 @@ def _get_bat_stat_metrics_for_lineup_spots(
team_id=self.team_id_bbref,
bat_stats=bat_stats_for_lineup_spots_for_season,
year=year,
bat_order_list=bat_order_list,
)
bat_stats_metrics.all_team_stats_for_bat_order = True
return bat_stats_metrics
Expand All @@ -331,7 +330,6 @@ def _get_bat_stat_metrics_for_def_positions(
team_id=self.team_id_bbref,
bat_stats=bat_stats_for_def_positions_for_season,
year=year,
def_position_list=def_position_list,
)
bat_stats_metrics.all_team_stats_for_def_pos = True
return bat_stats_metrics
Expand Down Expand Up @@ -432,7 +430,6 @@ def get_bat_stat_metrics_for_lineup_spots_for_player(
year=year,
player_id_mlb=mlb_id,
player_id_bbref=bbref_id,
bat_order_list=bat_order_list,
)

def get_bat_stat_metrics_for_def_positions_for_player(
Expand Down Expand Up @@ -461,7 +458,6 @@ def get_bat_stat_metrics_for_def_positions_for_player(
year=year,
player_id_mlb=mlb_id,
player_id_bbref=bbref_id,
def_position_list=def_position_list,
)


Expand Down Expand Up @@ -530,8 +526,6 @@ def create_bat_stats_metrics(
player_id_mlb: int = None,
player_id_bbref: str = None,
is_starter: bool = False,
bat_order_list: List[int] = 0,
def_position_list: List[DefensePosition] = None,
) -> BatStatsMetrics:
return BatStatsMetrics(
bat_stats=deepcopy(bat_stats),
Expand All @@ -541,6 +535,4 @@ def create_bat_stats_metrics(
team_id_bbref=team_id,
player_team_id_bbref=team_id,
is_starter=is_starter,
bat_order_list=bat_order_list,
def_position_list=def_position_list,
)
10 changes: 5 additions & 5 deletions src/vigorish/data/metrics/pitch_stats/pitch_stats_metrics.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,26 +137,26 @@ def hr_per_nine(self) -> float:
@cached_property
def k_per_bb(self) -> float:
k_per_bb = self.strikeouts / float(self.bases_on_balls) if self.bases_on_balls else 0.0
return round(k_per_bb * 27, ndigits=1)
return round(k_per_bb, ndigits=1)

@cached_property
def k_rate(self) -> float:
k_rate = self.strikeouts / float(self.batters_faced) if self.batters_faced else 0.0
return round(k_rate, ndigits=1)
return round(k_rate, ndigits=3)

@cached_property
def bb_rate(self) -> float:
bb_rate = self.bases_on_balls / float(self.batters_faced) if self.batters_faced else 0.0
return round(bb_rate, ndigits=1)
return round(bb_rate, ndigits=3)

@cached_property
def k_minus_bb(self) -> float:
return self.k_rate - self.bb_rate
return round(self.k_rate - self.bb_rate, ndigits=3)

@cached_property
def hr_per_fb(self) -> float:
hr_per_fb = self.homeruns / float(self.fly_balls) if self.fly_balls else 0.0
return round(hr_per_fb, ndigits=1)
return round(hr_per_fb, ndigits=3)

@cached_property
def pitch_count(self) -> int:
Expand Down
14 changes: 7 additions & 7 deletions src/vigorish/data/metrics/pitchfx/pitchfx_metrics.py
Original file line number Diff line number Diff line change
Expand Up @@ -416,17 +416,17 @@ def iso(self) -> float:
@cached_property
def bb_rate(self) -> float:
bb_rate = self.total_bb / float(self.total_pa) if self.total_pa else 0.0
return round(bb_rate, ndigits=1)
return round(bb_rate, ndigits=3)

@cached_property
def k_rate(self) -> float:
k_rate = self.total_k / float(self.total_pa) if self.total_pa else 0.0
return round(k_rate, ndigits=1)
return round(k_rate, ndigits=3)

@cached_property
def hr_per_fb(self) -> float:
hr_per_fb = self.total_homeruns / float(self.total_fly_balls) if self.total_fly_balls else 0.0
return round(hr_per_fb, ndigits=1)
return round(hr_per_fb, ndigits=3)

@cached_property
def avg_launch_speed(self) -> float:
Expand All @@ -451,22 +451,22 @@ def avg_hit_distance(self) -> float:
@cached_property
def hard_hit_rate(self) -> float:
hard_hit_rate = self.total_hard_hits / float(self.total_balls_in_play) if self.total_balls_in_play else 0.0
return round(hard_hit_rate, ndigits=1)
return round(hard_hit_rate, ndigits=3)

@cached_property
def medium_hit_rate(self) -> float:
medium_hit_rate = self.total_medium_hits / float(self.total_balls_in_play) if self.total_balls_in_play else 0.0
return round(medium_hit_rate, ndigits=1)
return round(medium_hit_rate, ndigits=3)

@cached_property
def soft_hit_rate(self) -> float:
soft_hit_rate = self.total_soft_hits / float(self.total_balls_in_play) if self.total_balls_in_play else 0.0
return round(soft_hit_rate, ndigits=1)
return round(soft_hit_rate, ndigits=3)

@cached_property
def barrel_rate(self) -> float:
barrel_rate = self.total_barrels / float(self.total_balls_in_play) if self.total_balls_in_play else 0.0
return round(barrel_rate, ndigits=1)
return round(barrel_rate, ndigits=3)

def as_dict(self):
dict_keys = list(filter(lambda x: not x.startswith(("__", "for_", "as_", "create_", "get_", "pfx")), dir(self)))
Expand Down
34 changes: 29 additions & 5 deletions src/vigorish/data/player_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,18 @@ def get_all_pfx_batting_career_data(
"metrics": self.pfx_batting_metrics_vs_lhp_for_career,
"percentiles": self.bat_stat_percentiles_vs_lhp_career,
},
"as_rhb_vs_rhp": {
"metrics": self.pfx_batting_metrics_vs_rhp_as_rhb_for_career,
},
"as_rhb_vs_lhp": {
"metrics": self.pfx_batting_metrics_vs_lhp_as_rhb_for_career,
},
"as_lhb_vs_rhp": {
"metrics": self.pfx_batting_metrics_vs_rhp_as_lhb_for_career,
},
"as_lhb_vs_lhp": {
"metrics": self.pfx_batting_metrics_vs_lhp_as_lhb_for_career,
},
}

@cached_property
Expand All @@ -370,7 +382,7 @@ def pfx_batting_metrics_vs_all_by_year(self) -> Dict[int, PitchFxMetricsSet]:
@cached_property
def bat_stat_percentiles_vs_all_by_year(self) -> Dict[int, BatterPercentile]:
return {
year: [self.scraped_data.calculate_batter_percentiles(pfx_metrics_collection.metrics_combined)]
year: self.scraped_data.calculate_batter_percentiles(pfx_metrics_collection.metrics_combined)
for year, pfx_metrics_collection in self.pfx_batting_metrics_vs_all_by_year.items()
}

Expand All @@ -384,7 +396,7 @@ def pfx_batting_metrics_vs_rhp_by_year(self) -> Dict[int, PitchFxMetricsSet]:
@cached_property
def bat_stat_percentiles_vs_rhp_by_year(self) -> Dict[int, BatterPercentile]:
return {
year: [self.scraped_data.calculate_batter_percentiles(pfx_metrics_collection.metrics_combined)]
year: self.scraped_data.calculate_batter_percentiles(pfx_metrics_collection.metrics_combined)
for year, pfx_metrics_collection in self.pfx_batting_metrics_vs_rhp_by_year.items()
}

Expand Down Expand Up @@ -412,7 +424,7 @@ def pfx_batting_metrics_vs_lhp_by_year(self) -> Dict[int, PitchFxMetricsSet]:
@cached_property
def bat_stat_percentiles_vs_lhp_by_year(self) -> Dict[int, BatterPercentile]:
return {
year: [self.scraped_data.calculate_batter_percentiles(pfx_metrics_collection.metrics_combined)]
year: self.scraped_data.calculate_batter_percentiles(pfx_metrics_collection.metrics_combined)
for year, pfx_metrics_collection in self.pfx_batting_metrics_vs_lhp_by_year.items()
}

Expand All @@ -438,14 +450,26 @@ def get_all_pfx_batting_yearly_data(
"metrics": self.pfx_batting_metrics_vs_all_by_year,
"percentiles": self.bat_stat_percentiles_vs_all_by_year,
},
"vs_rhb": {
"vs_rhp": {
"metrics": self.pfx_batting_metrics_vs_rhp_by_year,
"percentiles": self.bat_stat_percentiles_vs_rhp_by_year,
},
"vs_lhb": {
"vs_lhp": {
"metrics": self.pfx_batting_metrics_vs_lhp_by_year,
"percentiles": self.bat_stat_percentiles_vs_lhp_by_year,
},
"as_rhb_vs_rhp": {
"metrics": self.pfx_batting_metrics_vs_rhp_as_rhb_by_year,
},
"as_rhb_vs_lhp": {
"metrics": self.pfx_batting_metrics_vs_lhp_as_rhb_by_year,
},
"as_lhb_vs_rhp": {
"metrics": self.pfx_batting_metrics_vs_rhp_as_lhb_by_year,
},
"as_lhb_vs_lhp": {
"metrics": self.pfx_batting_metrics_vs_lhp_as_lhb_by_year,
},
}

def get_pfx_pitching_metrics_vs_all_for_season(self, year: int) -> PitchFxMetricsSet:
Expand Down
2 changes: 1 addition & 1 deletion src/vigorish/nightmarejs/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion src/vigorish/nightmarejs/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "vig-nodejs",
"version": "0.6.1",
"version": "0.6.2",
"description": "NightmareJS and other node modules used to scrape html from websites",
"author": "Aaron Luna <[email protected]> (https://aaronluna.dev)",
"license": "MIT",
Expand Down
Loading

0 comments on commit 96c7c91

Please sign in to comment.