def get_boxscores_api(team_ids):
    # dictionary with every player id
    team_games, all_games = get_games_api(team_ids)

    players_dict = fill_player_dict(all_games)
    player_game_count_dict = dict.fromkeys(
        [player["id"] for player in players.get_players()])
    for key in player_game_count_dict:
        player_game_count_dict[key] = 0

    print("-------------------------------------------------")
    print("All games loaded. Beginning game by game calculations...")
    print("-------------------------------------------------")

    for game_info in team_games:
        team_id = game_info[0]
        print("Running calculations for " +
              str({teams.find_team_name_by_id(team_id)["full_name"]}) + "...")
        game_set = game_info[1]
        i = 0
        for game_id in game_set:
            print(str(i) + " games done")
            i += 1
            boxscore = boxscoreadvancedv2.BoxScoreAdvancedV2(
                game_id=game_id).get_dict()["resultSets"][0]["rowSet"]

            print("writing temp file for game: " + str(game_id))
            with open(f"games{SEASON.split('-')[0]}/{game_id}", "w") as file:
                file.write(json.dumps(boxscore))
Beispiel #2
0
def get_today_input_data():
    game_ids = [
        "0021900343",
        "0021900344",
        "0021900345",
        "0021900346",
        "0021900347",
        "0021900348",
        "0021900349",
        "0021900350",
        "0021900351",
    ]
    data = []
    players_dict = {}
    for gid in game_ids:
        print(str(gid) + " fetch 1...")
        boxscore = boxscoreadvancedv2.BoxScoreAdvancedV2(game_id=gid).get_dict()[
            "resultSets"
        ][0]["rowSet"]
        print("done. fetch 2...")
        home_team_id = (
            boxscoresummaryv2.BoxScoreSummaryV2(game_id=gid).get_dict()["resultSets"][
                0
            ]["rowSet"][0][6]
            if gid != "0021900351"
            else 1610612744
        )
        print("done.")
        home_team_players = []
        away_team_players = []
        for player_info in boxscore:
            if str(player_info[BOXSCORE_TEAM_ID]) == str(home_team_id):
                home_team_players.append(player_info[BOXSCORE_PLAYER_ID])
            else:
                away_team_players.append(player_info[BOXSCORE_PLAYER_ID])
        data.append([gid, home_team_players, away_team_players, 0])

        for player_line in boxscore:
            # update player matrix
            if player_line[BOXSCORE_STAT_START] is None:
                # DNP (coach's decision) case
                continue
            else:
                players_dict[player_line[BOXSCORE_PLAYER_ID]] = {}
            player_line[BOXSCORE_STAT_START] = int(
                player_line[BOXSCORE_STAT_START].split(":")[0]
            ) * 60 + int(player_line[BOXSCORE_STAT_START].split(":")[1])

            players_dict[player_line[BOXSCORE_PLAYER_ID]][gid] = np.array(
                player_line[BOXSCORE_STAT_START:]
            )
    all_data, games = get_2d_data(data, players_dict)
    return all_data
Beispiel #3
0
def get_boxscore(game_id):
    bs = boxscoreadvancedv2.BoxScoreAdvancedV2(game_id=game_id)
    return bs.get_data_frames()[0]
Beispiel #4
0
#SEA, NOH, NJN, NOK are odd team names I deal with later by mapping over them
team_abbrev_list


team_id_list = [team['id'] for team in nba_teams]



from nba_api.stats.endpoints import leaguegamefinder


game_id = pd.read_csv('shifted.csv')
game_id = game_id.GAME_ID
game_id[-1:]
df = pd.DataFrame()#columns=cols)
box_adv = boxscoreadvancedv2.BoxScoreAdvancedV2(game_id = 21801211)
games = box_adv.get_data_frames()[0]
print(games)

#creating database of games going back to 2007 - as far back as my odds database goes
for ele in game_id:
    gamefinder = boxscoreadvancedv2.BoxScoreAdvancedV2(game_id= ele)
    games = gamefinder.get_data_frames()[0]
    print(games)
    #games['GAME_DATE'] = pd.to_datetime(games['GAME_DATE'])
    #games = games[games.SEASON_ID.str[1:].astype(int) >= 2007]
    #df = pd.concat([df, games], ignore_index=True)
    break
# having an issue with IND and BOS only having 81 games, in 1 season that is the case but not all- resolved
df.head()
Beispiel #5
0
def get_value_contributed_inputs(game_id,
                                 winning_team,
                                 losing_team,
                                 season_type,
                                 season_end_year,
                                 sql_upload='no'):
    ### Create DataFrame With All Players On Winning Team and Losing Team
    traditional = boxscoretraditionalv2.BoxScoreTraditionalV2(game_id=game_id)
    traditional_players_df = traditional.player_stats.get_data_frame()

    ##Create a seconds factor column. How many seconds each player played as a percentage of how many seconds there are to go around on each team
    sec_list = []
    for idx, event in traditional_players_df['MIN'].iteritems():
        min_split = str(event).split(':')
        if len(min_split) == 2:
            sec_list.append(
                (int(min_split[0]) * 60 + int(min_split[1])) / 14400
            )  #14400 are seconds in a basketball game for 5 players on a court at a time
        else:
            sec_list.append(0)

    traditional_players_df['SEC_FACT'] = sec_list
    traditional_players_df['FG2_MADE'] = traditional_players_df[
        'FGM'] - traditional_players_df['FG3M']
    traditional_players_df[
        'FG2_MISSED'] = traditional_players_df['FGA'] - traditional_players_df[
            'FG3A'] - traditional_players_df['FG2_MADE']
    traditional_players_df['FG3_MADE'] = traditional_players_df['FG3M']
    traditional_players_df['FG3_MISSED'] = traditional_players_df[
        'FG3A'] - traditional_players_df['FG3M']

    traditional_players_df = traditional_players_df[[
        'PLAYER_ID', 'PLAYER_NAME', 'TEAM_ID', 'SEC_FACT', 'FG2_MADE',
        'FG2_MISSED', 'FG3_MADE', 'FG3_MISSED', 'FTM', 'FTA', 'AST', 'STL',
        'BLK', 'OREB', 'DREB', 'TO'
    ]]

    ### Box Score Player Tracking Object and DataFrame For Winning Team ###
    tracking = boxscoreplayertrackv2.BoxScorePlayerTrackV2(game_id=game_id)
    tracking_players_df = tracking.player_stats.get_data_frame()

    # Calculate how many field goals players successfully defended
    tracking_players_df[
        'DFG'] = tracking_players_df['DFGA'] - tracking_players_df['DFGM']
    tracking_players_df = tracking_players_df[[
        'PLAYER_ID', 'SAST', 'FTAST', 'DFG'
    ]]

    ### Merge Tracking Data With Current Data In Jacob Value DataFrame ###
    val_contr_inputs_df = pd.merge(traditional_players_df,
                                   tracking_players_df,
                                   on='PLAYER_ID',
                                   how='outer')

    ### Box Score Player Scoring Object and DataFrame    ###
    scoring = boxscorescoringv2.BoxScoreScoringV2(game_id=game_id)
    scoring_players_df = scoring.sql_players_scoring.get_data_frame()
    scoring_players_df = scoring_players_df[[
        'PLAYER_ID', 'PCT_UAST_2PM', 'PCT_UAST_3PM'
    ]]
    val_contr_inputs_df = pd.merge(val_contr_inputs_df,
                                   scoring_players_df,
                                   on='PLAYER_ID',
                                   how='outer')

    ### Box Score Player Misc Object and DataFrame ###
    misc = boxscoremiscv2.BoxScoreMiscV2(game_id=game_id)
    misc_players_df = misc.sql_players_misc.get_data_frame()
    misc_players_df = misc_players_df[['PLAYER_ID', 'PTS_2ND_CHANCE']]
    val_contr_inputs_df = pd.merge(val_contr_inputs_df,
                                   misc_players_df,
                                   on='PLAYER_ID',
                                   how='outer')

    ### Calculate Def and Off Factor For Each Player ###
    advanced = boxscoreadvancedv2.BoxScoreAdvancedV2(game_id=game_id)
    player_advanced = advanced.player_stats.get_data_frame()
    team_advanced = advanced.team_stats.get_data_frame()

    advanced_winning_players_df = player_advanced[player_advanced['TEAM_ID'] ==
                                                  winning_team]
    advanced_winning_team_df = team_advanced[team_advanced['TEAM_ID'] ==
                                             winning_team]
    advanced_winning_team_df = advanced_winning_team_df.reset_index()
    # print(advanced_winning_players_df[['PLAYER_NAME','OFF_RATING', 'DEF_RATING']])
    # print(advanced_winning_team_df[['TEAM_NAME','OFF_RATING', 'DEF_RATING']])

    advanced_losing_players_df = player_advanced[player_advanced['TEAM_ID'] ==
                                                 losing_team]
    advanced_losing_team_df = team_advanced[team_advanced['TEAM_ID'] ==
                                            losing_team]
    advanced_losing_team_df = advanced_losing_team_df.reset_index()
    # print(advanced_losing_players_df[['PLAYER_NAME','OFF_RATING', 'DEF_RATING']])
    # print(advanced_losing_team_df[['TEAM_NAME','OFF_RATING', 'DEF_RATING']])

    pd.options.mode.chained_assignment = None

    advanced_winning_players_df[
        'defense_factor'] = advanced_winning_players_df[
            'DEF_RATING'] / advanced_winning_team_df.loc[0]['DEF_RATING']
    advanced_winning_players_df[
        'defense_factor'] = advanced_winning_players_df[
            'defense_factor'].apply(lambda x: 1 - (x - 1))

    advanced_winning_players_df[
        'offense_factor'] = advanced_winning_players_df[
            'OFF_RATING'] / advanced_winning_team_df.loc[0]['OFF_RATING']

    advanced_winning_players_df = advanced_winning_players_df[[
        'PLAYER_ID', 'defense_factor', 'offense_factor'
    ]]

    advanced_losing_players_df['defense_factor'] = advanced_losing_players_df[
        'DEF_RATING'] / advanced_losing_team_df.loc[0]['DEF_RATING']
    advanced_losing_players_df['defense_factor'] = advanced_losing_players_df[
        'defense_factor'].apply(lambda x: 1 - (x - 1))

    advanced_losing_players_df['offense_factor'] = advanced_losing_players_df[
        'OFF_RATING'] / advanced_losing_team_df.loc[0]['OFF_RATING']

    advanced_losing_players_df = advanced_losing_players_df[[
        'PLAYER_ID', 'defense_factor', 'offense_factor'
    ]]

    ### Merge Advanced Data With Current Data In Jacob Value DataFrame ###
    advanced_players_df = advanced_winning_players_df.append(
        advanced_losing_players_df, ignore_index=True)
    val_contr_inputs_df = pd.merge(val_contr_inputs_df,
                                   advanced_players_df,
                                   on='PLAYER_ID',
                                   how='outer')

    #print(winning_team_df)
    #Assume that if there is an n/a the player did not do anything in that statistical category or did not play
    val_contr_inputs_df = val_contr_inputs_df.fillna(0).reset_index(drop=True)
    # print(val_contr_inputs_df)
    winning_team_df = val_contr_inputs_df[val_contr_inputs_df['TEAM_ID'] ==
                                          winning_team].reset_index(drop=True)
    losing_team_df = val_contr_inputs_df[val_contr_inputs_df['TEAM_ID'] ==
                                         losing_team].reset_index(drop=True)

    if season_type == 'Playoffs':
        val_contr_inputs_df['SEASON_TYPE'] = 'Playoffs'
    else:
        val_contr_inputs_df['SEASON_TYPE'] = 'Regular Season'

    # print(val_contr_inputs_df.columns)

    # Upload to SQL
    if sql_upload == 'no':
        pass
    else:
        sql_table = 'val_contr_inputs' + '_' + str(
            season_end_year - 1) + '_' + str(season_end_year)[-2:]

        columns = [x.lower() for x in val_contr_inputs_df.columns]
        columns = [x if x != 'to' else 'tos' for x in columns]

        copy_df = val_contr_inputs_df.copy()
        copy_df.columns = columns

        conn = pg2.connect(dbname='postgres', host="localhost")
        conn.autocommit = True
        engine = create_engine(
            'postgresql+psycopg2://jacobpress:bocaj29@localhost/wins_contr')
        copy_df.to_sql(sql_table, con=engine, if_exists="append", index=False)
        conn.close()

    return [winning_team_df, losing_team_df]
Beispiel #6
0
    def generate_inputs(self):
        home_games = leaguegamefinder.LeagueGameFinder(
            team_id_nullable=self.HOME_TEAM_ID,
            headers=headers).get_data_frames()[0]

        # In[117]:

        home_games.GAME_DATE = pd.to_datetime(home_games.GAME_DATE)
        last5_home = home_games.sort_values(by='GAME_DATE',
                                            ascending=False).loc[:5, :]

        away_games = leaguegamefinder.LeagueGameFinder(
            team_id_nullable=self.VISITOR_TEAM_ID,
            headers=headers).get_data_frames()[0]

        # In[119]:

        away_games.GAME_DATE = pd.to_datetime(away_games.GAME_DATE)
        last5_away = away_games.sort_values(by='GAME_DATE',
                                            ascending=False).loc[:5, :]

        # In[120]:

        games_unused = [
            'season_id', 'team_abbreviation', 'team_name', 'wl', 'min', 'pts',
            'fgm', 'fga', 'fg3m', 'fg3a', 'ftm', 'fta'
        ]

        # In[125]:

        games_unused = [i.upper() for i in games_unused]

        # In[126]:

        last5_home2 = last5_home.drop(games_unused, axis=1)
        last5_away2 = last5_away.drop(games_unused, axis=1)

        home_box = pd.DataFrame()

        for game in last5_home2.GAME_ID:
            box = boxscoreadvancedv2.BoxScoreAdvancedV2(
                game, headers=headers).get_data_frames()[1]
            home_box = pd.concat([home_box, box])

        box_unused = [
            'team_name', 'team_abbreviation', 'team_city', 'min', 'off_rating',
            'def_rating', 'net_rating', 'usg_pct', 'pace_per40', 'poss', 'pie'
        ]

        box_unused.extend([i for i in home_box.columns if i.startswith('E_')])
        box_unused = [i.upper() for i in box_unused]

        home_box2 = home_box.drop(box_unused, axis=1)

        away_box = pd.DataFrame()

        for game in last5_away2.GAME_ID:
            box = boxscoreadvancedv2.BoxScoreAdvancedV2(
                game, headers=headers).get_data_frames()[1]
            away_box = pd.concat([away_box, box])

        away_box2 = away_box.drop(box_unused, axis=1)

        # THIS IS BAD, A POTENTIAL BUG

        home_box2 = home_box2.loc[home_box2.TEAM_ID == self.HOME_TEAM_ID]
        away_box2 = away_box2.loc[away_box2.TEAM_ID == self.VISITOR_TEAM_ID]
        #print(home_box2.shape, away_box2.shape)

        last5_home2 = last5_home2.loc[last5_home2.TEAM_ID == self.HOME_TEAM_ID]
        last5_away2 = last5_away2.loc[last5_away2.TEAM_ID ==
                                      self.VISITOR_TEAM_ID]
        #print(last5_home2.shape, last5_away2.shape)

        home_data = home_box2.merge(last5_home2,
                                    how='left',
                                    on=['GAME_ID', 'TEAM_ID'])
        away_data = away_box2.merge(last5_away2,
                                    how='left',
                                    on=['GAME_ID', 'TEAM_ID'])

        #print(home_data.shape, away_data.shape)
        non_pred = ['game_id', 'team_id', 'game_date', 'matchup', 'plus_minus']
        non_pred = [i.upper() for i in non_pred]

        home_data2 = home_data.drop(non_pred, axis=1)
        away_data2 = away_data.drop(non_pred, axis=1)

        #print(home_data2.shape, away_data2.shape)

        test = pd.concat([home_data2, away_data2], axis=1)

        test_values = test.mean().values

        return test_values.reshape(1, -1)
Beispiel #7
0
    def create_player_box_score(self, df):
        df['season'] = self.season
        df['team_id'] = self.team_id
        df['game_id'] = self.game_id
        df['is_home'] = self.is_home
        df['game_date'] = self.game_date
        df['game_date'] = pd.to_datetime(df['game_date'])

        # --------------------
        # field_goals_attempted
        # field_goals_made
        df = df.fillna(0)
        df['field_goals_attempted'] = df['FG2A'].astype(int) + df['FG3A'].astype(int)
        df['field_goals_made'] = df['FG2M'].astype(int) + df['FG3M'].astype(int)

        # add in plus_minus and starters from NBA API
        box_json = boxscoretraditionalv2.BoxScoreTraditionalV2(self.game_id)
        box_data = json.loads(box_json.get_json())

        trad_df = pd.DataFrame(box_data['resultSets'][0]['rowSet'])
        trad_df.columns = box_data['resultSets'][0]['headers']
        trad_df['is_starter'] = np.where(trad_df['START_POSITION'] != '', True, False)
        trad_df['PLAYER_ID'] = trad_df['PLAYER_ID'].astype(int)
        trad_df = trad_df[['PLAYER_ID', 'is_starter', 'PLUS_MINUS']]
        df['EntityId'] = df['EntityId'].astype(int)

        df = df.merge(trad_df, left_on='EntityId', right_on='PLAYER_ID', how='left')
        df = df.sort_values(['is_starter', 'Minutes'], ascending=False)
        df['is_starter'] = df['is_starter'].fillna(False)

        # add in offensive and def rating and pace from nba api
        box_json = boxscoreadvancedv2.BoxScoreAdvancedV2(self.game_id)
        box_data = json.loads(box_json.get_json())

        adv_df = pd.DataFrame(box_data['resultSets'][0]['rowSet'])
        adv_df.columns = box_data['resultSets'][0]['headers']
        adv_df['PLAYER_ID'] = adv_df['PLAYER_ID'].astype(int)
        adv_df = adv_df[['PLAYER_ID', 'PACE', 'OFF_RATING', 'DEF_RATING']]

        df = df.merge(adv_df, left_on='EntityId', right_on='PLAYER_ID', how='left')
        df = df.fillna(0)

        # match columns to db names
        df = df.rename(columns={"FTA": "free_throws_attempted",
                                "FtPoints": "free_throws_made",
                                'FG3A': 'threes_attempted',
                                'FG3M': 'threes_made',
                                'OffPoss': 'offensive_possessions',
                                'DefPoss': 'defensive_possessions',
                                'AtRimFGM': 'rim_made',
                                'AtRimFGA': 'rim_attempted',
                                'EntityId': 'player_id',
                                'Minutes': 'minutes',
                                'Points': 'points',
                                'Assists': 'assists',
                                'AtRimAssists': 'rim_assists',
                                'TsPct': 'true_shooting_pct',
                                'Blocks': 'blocks',
                                'DefRebounds': 'defensive_rebounds',
                                'OffRebounds': 'offensive_rebounds',
                                'Rebounds': 'rebounds',
                                'EfgPct': 'effective_field_goal_pct',
                                'Steals': 'steals',
                                'Fouls': 'fouls',
                                'LiveBallTurnovers': 'live_turnovers',
                                'Turnovers': 'turnovers',
                                'PACE': 'pace',
                                'PLUS_MINUS': 'plus_minus',
                                'OFF_RATING': 'offensive_rating',
                                'DEF_RATING': 'defensive_rating',
                                'Usage': 'usage_pct'})

        for col in self.db_columns:
            if col not in df.columns:
                df[col] = 0

        df = df[self.db_columns]
        # make home team team line = 1
        if self.is_home:
            team_index = list(df[df['player_id'] == 0].index)[0]
            df.at[team_index, 'player_id'] = 1
        df.to_sql(name=self.table_name, con=self.con, if_exists='append', index=False)
        return df
Beispiel #8
0
    def create_team_box_score(self, df, rotation_chart_location, shot_chart_location):
        df['season'] = self.season
        df['team_id'] = self.team_id
        df['game_id'] = self.game_id
        df['is_home'] = self.is_home
        df['rotation_chart_location'] = rotation_chart_location
        df['shot_chart_location'] = shot_chart_location
        df['game_date'] = self.game_date
        df['game_date'] = pd.to_datetime(df['game_date'])

        # --------------------
        # field_goals_attempted
        # field_goals_made
        df['field_goals_attempted'] = df['FG2A'].astype(int) + df['FG3A'].astype(int)
        df['field_goals_made'] = df['FG2M'].astype(int) + df['FG3M'].astype(int)

        # add in offensive and def rating, pace and num OTs from nba api
        box_json = boxscoreadvancedv2.BoxScoreAdvancedV2(self.game_id)
        box_data = json.loads(box_json.get_json())

        adv_df = pd.DataFrame(box_data['resultSets'][1]['rowSet'])
        adv_df.columns = box_data['resultSets'][1]['headers']
        adv_df['minutes_num'] = (adv_df['MIN'].str.split(':', expand=True)[0]).astype(int)
        adv_df['num_overtimes'] = ((adv_df['minutes_num'] / 5) - 48) / 5
        adv_df = adv_df[['TEAM_ID', 'PACE', 'OFF_RATING', 'DEF_RATING', 'num_overtimes']]
        adv_df['TEAM_ID'] = adv_df['TEAM_ID'].astype(int)

        df['team_id'] = df['team_id'].astype(int)

        df = df.merge(adv_df, left_on='team_id', right_on='TEAM_ID', how='left')
        df = df.fillna(0)
        # match columns to db names
        df = df.rename(columns={"FTA": "free_throws_attempted",
                                "FtPoints": "free_throws_made",
                                'FG3A': 'threes_attempted',
                                'FG3M': 'threes_made',
                                'OffPoss': 'offensive_possessions',
                                'DefPoss': 'defensive_possessions',
                                'AtRimFGM': 'rim_made',
                                'AtRimFGA': 'rim_attempted',
                                'EntityId': 'player_id',
                                'Points': 'score',
                                'Assists': 'assists',
                                'AtRimAssists': 'rim_assists',
                                'TsPct': 'true_shooting_pct',
                                'Blocks': 'blocks',
                                'DefRebounds': 'defensive_rebounds',
                                'OffRebounds': 'offensive_rebounds',
                                'Rebounds': 'rebounds',
                                'EfgPct': 'effective_field_goal_pct',
                                'Steals': 'steals',
                                'Fouls': 'fouls',
                                'LiveBallTurnovers': 'live_turnovers',
                                'Turnovers': 'turnovers',
                                'PACE': 'pace',
                                'OFF_RATING': 'offensive_rating',
                                'DEF_RATING': 'defensive_rating'})

        for col in self.db_columns:
            if col not in df.columns:
                df[col] = 0

        df = df[self.db_columns]
        df.to_sql(name=self.table_name, con=self.con, if_exists='append', index=False)
        return df
def build_rotation(game_id, away_abbr, home_abbr, save_path):
    data = playbyplayv2.PlayByPlayV2(game_id=game_id)
    pbp_data = json.loads(data.get_json())
    rows = pbp_data['resultSets'][0]['rowSet']
    headers = pbp_data['resultSets'][0]['headers']
    pd.set_option('display.max_rows', None)
    pd.set_option('display.max_columns', None)
    pbp_df = pd.DataFrame(rows)
    pbp_df.columns = headers

    pbp_df['Sub_In_Player'] = np.where(pbp_df['EVENTMSGTYPE'] == 8, pbp_df['PLAYER2_NAME'], '')
    pbp_df['Sub_In_ID'] = np.where(pbp_df['EVENTMSGTYPE'] == 8, pbp_df['PLAYER2_ID'], '').astype(str)
    pbp_df['Sub_Out_Player'] = np.where(pbp_df['EVENTMSGTYPE'] == 8, pbp_df['PLAYER1_NAME'], '')
    pbp_df['Sub_Out_ID'] = np.where(pbp_df['EVENTMSGTYPE'] == 8, pbp_df['PLAYER1_ID'], '').astype(str)

    qtr_box_dfs = []
    for qtr in list(pbp_df['PERIOD'].unique()):
        box_data = boxscoreadvancedv2.BoxScoreAdvancedV2(game_id=game_id,
                                                         start_period=qtr,
                                                         end_period=qtr,
                                                         range_type=1
                                                         )

        box_json = json.loads(box_data.get_json())

        rows = box_json['resultSets'][0]['rowSet']
        headers = box_json['resultSets'][0]['headers']

        box_df = pd.DataFrame(rows)
        box_df.columns = headers
        box_df['PLAYER_ID'] = box_df['PLAYER_ID'].astype(str)

        qtr_box_dfs.append(box_df)

    pbp_df['Away_Lineup_Change'] = np.where(
        ((pbp_df['EVENTMSGTYPE'] == 8) & (pbp_df['PLAYER1_TEAM_ABBREVIATION'] == away_abbr)), 1, 0)
    pbp_df['Home_Lineup_Change'] = np.where(
        ((pbp_df['EVENTMSGTYPE'] == 8) & (pbp_df['PLAYER1_TEAM_ABBREVIATION'] == home_abbr)), 1, 0)

    pbp_df['Away_On_Court'] = None
    pbp_df['Away_On_Court_IDs'] = None
    pbp_df['Home_On_Court'] = None
    pbp_df['Home_On_Court_IDs'] = None

    for index, df in enumerate(qtr_box_dfs, start=1):
        df['PERIOD'] = index

        period_sub_df = pbp_df[(pbp_df['EVENTMSGTYPE'] == 8) & (pbp_df['PERIOD'] == index)]
        period_sub_df = period_sub_df.drop_duplicates(subset=['Sub_Out_ID'], keep='first')

        period_sub_df['Sub_Num'] = period_sub_df.groupby('PLAYER2_TEAM_ABBREVIATION').cumcount() + 1

        period_sub_df['isStarter'] = 0

        # get starters by loopiong through df and checking that person getting subbed out hasnt already been subbed in
        for i in period_sub_df.index:
            if period_sub_df.loc[i, 'Sub_Out_ID'] not in list(period_sub_df.loc[:i - 1, 'Sub_In_ID']):
                period_sub_df.at[i, 'isStarter'] = 1

        starters_df = period_sub_df[period_sub_df['isStarter'] == 1]
        starter_ids = list(starters_df['Sub_Out_ID'])
        df['isStarter'] = np.where(df['PLAYER_ID'].isin(starter_ids), 1,
                                   np.where(df['PERIOD'] < 5,
                                            np.where(df['MIN'] == '12:00', 1, 0),
                                            np.where(df['MIN'] == '5:00', 1, 0)
                                            )
                                   )

        away_starters = list(df[(df['TEAM_ABBREVIATION'] == away_abbr) & (df['isStarter'] == 1)]['PLAYER_NAME'])
        away_starters_ids = list(df[(df['TEAM_ABBREVIATION'] == away_abbr) & (df['isStarter'] == 1)]['PLAYER_ID'])
        home_starters = list(df[(df['TEAM_ABBREVIATION'] == home_abbr) & (df['isStarter'] == 1)]['PLAYER_NAME'])
        home_starters_ids = list(df[(df['TEAM_ABBREVIATION'] == home_abbr) & (df['isStarter'] == 1)]['PLAYER_ID'])

        if index < 5:
            qtr_start_index = pbp_df.loc[(pbp_df['PERIOD'] == index) & (pbp_df['PCTIMESTRING'] == '12:00')].index[0]
        else:
            qtr_start_index = pbp_df.loc[(pbp_df['PERIOD'] == index) & (pbp_df['PCTIMESTRING'] == '5:00')].index[0]

        pbp_df.at[qtr_start_index, 'Away_On_Court'] = away_starters
        pbp_df.at[qtr_start_index, 'Away_On_Court_IDs'] = away_starters_ids
        pbp_df.at[qtr_start_index, 'Home_On_Court'] = home_starters
        pbp_df.at[qtr_start_index, 'Home_On_Court_IDs'] = home_starters_ids

    pbp_df = fill_lineup_forward(pbp_df, 'Away')
    pbp_df = fill_lineup_forward(pbp_df, 'Home')

    mlb_a = MultiLabelBinarizer()
    pbp_df = pbp_df.merge(
        pd.DataFrame(mlb_a.fit_transform(pbp_df['Away_On_Court_IDs']), columns=mlb_a.classes_, index=pbp_df.index),
        on=pbp_df.index,
        how='left')
    away_ids = mlb_a.classes_

    mlb_h = MultiLabelBinarizer()
    pbp_df = pbp_df.drop(columns=['key_0'])
    pbp_df = pbp_df.merge(
        pd.DataFrame(mlb_h.fit_transform(pbp_df['Home_On_Court_IDs']), columns=mlb_h.classes_, index=pbp_df.index),
        on=pbp_df.index,
        how='left')
    home_ids = mlb_h.classes_

    pbp_df['away_num_players_on_court'] = 0
    on_court_count = pbp_df['away_num_players_on_court']
    for pid in away_ids:
        on_court_count = on_court_count + pbp_df[pid]

    pbp_df['away_num_players_on_court'] = on_court_count

    pbp_df['home_num_players_on_court'] = 0
    on_court_count = pbp_df['home_num_players_on_court']
    for pid in home_ids:
        on_court_count = on_court_count + pbp_df[pid]

    pbp_df['home_num_players_on_court'] = on_court_count

    pbp_df['GameTime'] = pd.to_datetime(pbp_df['PCTIMESTRING'], format='%M:%S')
    pbp_df['PeriodEndTime'] = np.where(pbp_df['PERIOD'] < 5,
                                       pd.Timedelta(minutes=12) * pbp_df['PERIOD'],
                                       (pd.Timedelta(minutes=12) * 4) + (
                                               pd.Timedelta(minutes=5) * (pbp_df['PERIOD'] - 4)))
    # causes type error --> time delta cant be converted to datetime
    # pbp_df['PeriodEndTime'] = pd.to_datetime(pbp_df['PeriodEndTime']) - pd.Timedelta(days=25567)
    # convert timdelta to string then to datetime to avoid the depricated passing time delta error
    pbp_df['PeriodEndTime'] = pd.to_datetime(pbp_df['PeriodEndTime'].astype(str).str.replace('0 days ', ''),
                                             format='%H:%M:%S')  # .%f
    pbp_df['ElapsedGameTime'] = pbp_df['PeriodEndTime'] - pbp_df['GameTime']

    pbp_df['SCORE'] = pbp_df['SCORE'].ffill()
    pbp_df['SCORE'] = pbp_df['SCORE'].fillna('0 - 0')
    pbp_df[['Away_SCORE', 'Home_SCORE']] = pbp_df['SCORE'].str.split(' - ', expand=True)
    pbp_df['Away_SCORE'] = pbp_df['Away_SCORE'].astype(float)
    pbp_df['Home_SCORE'] = pbp_df['Home_SCORE'].astype(float)

    box_data = boxscoreadvancedv2.BoxScoreAdvancedV2(game_id=game_id)

    box_json = json.loads(box_data.get_json())

    rows = box_json['resultSets'][0]['rowSet']
    headers = box_json['resultSets'][0]['headers']

    full_box_df = pd.DataFrame(rows)
    full_box_df.columns = headers
    full_box_df['PLAYER_ID'] = full_box_df['PLAYER_ID'].astype(str)
    full_box_df['isStarter'] = np.where(full_box_df['START_POSITION'].str.contains('[A-Z]'), 1, 0)
    full_box_df['MIN'] = pd.to_datetime(full_box_df['MIN'], format='%M:%S')
    full_box_df = full_box_df.sort_values(['TEAM_ABBREVIATION', 'isStarter', 'MIN'], ascending=False)
    full_box_df['MIN'] = full_box_df['MIN'].dt.strftime('%M:%S')
    # get ids from sorted box score (sorted by starters, min)
    away_ids = list(
        full_box_df[(full_box_df['TEAM_ABBREVIATION'] == away_abbr) & (full_box_df['PLAYER_ID'].isin(away_ids))][
            'PLAYER_ID'])
    home_ids = list(
        full_box_df[(full_box_df['TEAM_ABBREVIATION'] == home_abbr) & (full_box_df['PLAYER_ID'].isin(home_ids))][
            'PLAYER_ID'])

    away_stints = collect_stints(full_box_df, pbp_df, away_ids, False)
    home_stints = collect_stints(full_box_df, pbp_df, home_ids, True)

    away_rotation_file_name = graph_stints(away_stints, away_abbr, save_path)
    home_rotation_file_name = graph_stints(home_stints, home_abbr, save_path)

    return away_rotation_file_name, home_rotation_file_name