Snippets

Ben Sherwood Playoff and Team analysis.py

Created by Ben Sherwood
from bs4 import BeautifulSoup
import math as maths
from numpy import *
import re
from collections import OrderedDict
import matplotlib.pyplot as plt
from scipy.stats import norm

s = requests.Session()

def all_player_info(result, week):
    output = []
    player_rows = result.find_all("tr")
    for row in player_rows:
        name = row.find("a", "playerName")
        points = row.find("td", "statTotal")
        if name and points:
            if name.text == "Chris Thompson" and name.attrs["class"][2].split("-")[1] == "2559368":
                print(name.attrs)
                print("begone Chris")
                continue
            else:
                output.append(name.text + "~" + points.text + "~" + str(week))
    return output


def iter_all_weeks(current_week):
    all_info = []
    for x in range(1,current_week + 1):
        for offset in range(1,988,25):
        #for offset in range(1,200,25):
            url = "https://fantasy.nfl.com/research/players?offset={}&position=O&sort=pts&statCategory=stats&statSeason=2018&statType=weekStats&statWeek={}".format(offset, str(x))
            print(offset)
            r = s.get(url)
            soup = BeautifulSoup(r.text, "html.parser")
            all_info += all_player_info(soup, x)
        for offset in range(1,32,25):
            url = "https://fantasy.nfl.com/research/players?offset={}&position=8&sort=pts&statCategory=stats&statSeason=2018&statType=weekStats&statWeek={}".format(offset, str(x))
            print(offset)
            r = s.get(url)
            soup = BeautifulSoup(r.text, "html.parser")
            all_info += all_player_info(soup, x)
        for offset in range(1,54,25):
            url = "https://fantasy.nfl.com/research/players?offset={}&position=7&sort=pts&statCategory=stats&statSeason=2018&statType=weekStats&statWeek={}".format(offset, str(x))
            print(offset)
            r = s.get(url)
            soup = BeautifulSoup(r.text, "html.parser")
            all_info += all_player_info(soup, x)

    writer = open("results.csv", "w")
    writer.write("\r\n".join(all_info))
    return all_info

def make_player_dict(info):
    play_dict = {}
    for row in info:
        player, score, week = row.split("~")
        if player not in play_dict:
            play_dict[player] = [float(score)]
        else:
            play_dict[player].append(float(score))

    return play_dict


def make_summary_stats(play_dict, weeks):
    stats_dict = {}
    weights = [1 - ((weeks - x) * 0.03) for x in range(weeks)]
    print("weights are: {}".format(weights))
    for player in play_dict:
        if len(play_dict[player]) != weeks:
            print("first", player, "dupe name")
            continue

        temp_stats = [x for x in play_dict[player] if x != 0]
        if len(temp_stats) == 0:
            stats_dict[player] = [0, 0]
            continue
        try:
            temp_weight = [x for idx, x in enumerate(weights) if play_dict[player][idx] != 0]
        except IndexError:
            print(player, play_dict[player])

        stats_dict[player] = [average(temp_stats, weights=temp_weight), std(temp_stats)]

    return stats_dict


def create_teams():
    team_dict = {}
    with open("team_config.csv") as teams:
        for team in teams:
            if team.strip() == "":
                continue
            player_info, team_name = team.strip().split("~")
            play_team = "DEF"
            if len(player_info.split("-")) != 1:
                player_info = player_info.split("-")
                play_team = player_info.pop().strip()
                player_info = "-".join(player_info)                                                              
                player_info = player_info.split(" ")
            else:
                player_info = player_info.split(" ")
            pos = player_info.pop().strip()
            while True:
                if pos.strip() == "":
                    pos = player_info.pop().strip()
                else:
                    break
            player_name = " ".join([x.strip() for x in player_info])
            del player_info

            if team_name in team_dict:
                team_dict[team_name].append({player_name: {"position": pos, "playerTeam": play_team}})
            else:
                team_dict[team_name] = [{player_name: {"position": pos, "playerTeam": play_team}}]

    return team_dict


def compare_bell_curves(m1, std1, m2, std2):
    ''' 
    For 2 input means and std deviations return the chances that 
    mean & std dev 1 is greater than mean & std dev 2
    https://math.stackexchange.com/questions/40224/probability-of-a-point-taken-from-a-certain-normal-distribution-will-be-greater
    '''
    m1, m2, std1, std2 = map(float, [m1, m2, std1, std2])
    o = ((std1 ** 2) + (std2 ** 2)) ** 0.5
    if o == 0:
        o = 0.01
    u = m1 - m2
    return (1 - (-u / o)) / 2.0


def choose_best_player(available, all_plyr):
    scores_dict = {}
    for choice1 in available:
        for choice2 in available:
            if choice1 == choice2:
                continue
            else:
                if choice1 not in scores_dict:
                    scores_dict[choice1] = [compare_bell_curves(*all_plyr[choice1] + all_plyr[choice2])]
                else:
                    scores_dict[choice1].append(compare_bell_curves(*all_plyr[choice1] + all_plyr[choice2]))

    if len(scores_dict) == 0:
        return available[0]
    else:
        max_score = max([sum(scores_dict[x]) for x in scores_dict])
        players = [x for x in scores_dict if max_score == sum(scores_dict[x])]
        # At the moment arbritrarily picking top 1 if there are 2 with same score
        # Presumably this won't happen over the course of 11 weeks but may flag later
        return players[0]


def choose_team(teams, players):
    ideal_teams = {}
    for team in teams:
        tmp_id_team = OrderedDict([
            ("QB", ""),
            ("RB1", ""),
            ("RB2", ""),
            ("WR1", ""),
            ("WR2", ""),
            ("TE", ""),
            ("WR/RB", ""),
            ("K", ""),
            ("DEF", "")
            ])

        tmp_team = teams[team]
        for position in tmp_id_team:
            if position in ["QB", "TE", "DEF", "K"]:
                choices = [result for x in tmp_team for result in x if position == x[result]["position"] and "IA" not in x[result]["playerTeam"] and "PUP" not in x[result]["playerTeam"]]
            elif position[:2] in ["RB", "WR"] and position != "WR/RB":
                choices = [result for x in tmp_team for result in x if position[:2] == x[result]["position"] and "IA" not in x[result]["playerTeam"] and "PUP" not in x[result]["playerTeam"]]
            elif position == "WR/RB":
                choices = [result for x in tmp_team for result in x if x[result]["position"] in ["RB", "WR"] and "IA" not in x[result]["playerTeam"] and "PUP" not in x[result]["playerTeam"]]
            else:
                print("oh dear", position)
                exit()
            if len(choices) == 0:
                print(team, position, teams[team])
                exit()
            choice = choose_best_player(choices, players)
            tmp_id_team[position] = choice
            # print tmp_team
            del tmp_team[[idx for idx, x in enumerate(tmp_team) for name in x if name == choice][0]]
        ideal_teams[team] = tmp_id_team

    return ideal_teams


def team_score(team, ref):
    score = sum([ref[team[position]][0] for position in team])
    std_dev = sum([ref[team[position]][1] for position in team])
    return [score, std_dev]


def create_team_stats(teams, summ_stats):
    high_stats = {}
    for team in teams:
        high_stats[team] = team_score(teams[team], summ_stats)
    return high_stats



def play_the_games(team_stats, challengers="Any"):
    if challengers == "Any":
        results = {}
        for teams_list_1 in team_stats:
            sigma = team_stats[teams_list_1][1]
            x_axis = linspace(team_stats[teams_list_1][0] - sigma, team_stats[teams_list_1][0] + sigma, 260)
            plt.plot(x_axis, norm.pdf(x_axis, *team_stats[teams_list_1]), color="b")
            plt.savefig(teams_list_1 + ".png")
            plt.close()
            for teams_list_2 in team_stats:
                if teams_list_1 == teams_list_2:
                    continue
                elne https://LOC_Code@bitbucket.org/LOC_Code/playoff-and-team-analysis.gitse:
                    results[teams_list_1 + '~' + teams_list_2] = compare_bell_curves(*team_stats[teams_list_1] + team_stats[teams_list_2])
                sigma = max(team_stats[teams_list_1][1], team_stats[teams_list_2][1]) * 3
                lower_band = min(team_stats[teams_list_1][0], team_stats[teams_list_2][0])
                upper_band = max(team_stats[teams_list_1][0], team_stats[teams_list_2][0])
                x_axis = linspace(lower_band - sigma, upper_band + sigma, 260)
                plt.plot(x_axis, norm.pdf(x_axis, *team_stats[teams_list_1]), color="b")
                plt.plot(x_axis, norm.pdf(x_axis, *team_stats[teams_list_2]), color="r")
                plt.savefig(teams_list_1 + '~' + teams_list_2 + ".png")
                plt.close()
    return results


def main():
    num_weeks = 12
    results = iter_all_weeks(num_weeks)
    player_dict = make_player_dict(results)
    summ_stats = make_summary_stats(player_dict, num_weeks)
    add_info = create_teams()
    teams_for_comp = choose_team(add_info, summ_stats)
    high_level_stats = create_team_stats(teams_for_comp, summ_stats)
    game_results = play_the_games(high_level_stats, challengers="Any")
    print(game_results)
    with open("game_results.txt", "w") as out:
        out.write("\r\n".join([x + "^" +  str(game_results[x]) for x in game_results]))
    with open("teams.txt", "w") as out:
        out.write("\r\n".join([x + "^" +  str(teams_for_comp[x]) for x in teams_for_comp]))


main()

Comments (0)

HTTPS SSH

You can clone a snippet to your computer for local editing. Learn more.