<jupyter_start><jupyter_text>![A.I. Sports](https://raw.githubusercontent.com/papagorgio23/Python101/master/Logo.png)www.AISportsFirm.com  Daily Fantasy Football Lineup Optimizer ![Draft Kings](https://raw.githubusercontent.com/papagorgio23/Python101/master/DraftKings.png) We are going to tap into the Draft Kings API to access player prices and average player scores. We are then going to use this information to create optimal lineups. *   Optimial lineup = Combination of players that will score the most points  Linear Programming (The Math) The basic framework of linear/integer programming is as follows:*   There are **Decision Variables**    *  These will be the variables that we can select (i.e. which player to have in our lineup)*   There is an **Objective Function** to either Maximize or Minimize    * Our goal will be to Maximize our point total*   There are **Constraints** we must abide by    * Salary, Number of Players, Players at specific positions, non-negativity  Definitions:**Index Sets:**Let ***I*** be the set of positions, indexed by *i*Let ***J*** be the set of players, indexed by *j***Variables:**Let ***P*** be the projected pointsLet ***C*** be the cost of the player**Other Variables:**Let ***n*** be the total number of positionsLet ***m*** be the total number of players***$x_{ij} = Player$$P_{ij} = Points\ Player\ Scores$$C_{ij} = Cost\ of\ Player$*** implicit Form:$$maximize\ \ \ \ \ \ z = \sum_{i=1}^n\sum_{j=1}^m P_{ij} * x_{ij} $$$$\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ subject\ to\ \ \ \ \ \sum_{i=1}^n\sum_{j=1}^m C_{ij} * x_{ij} \leq Max\ Salary$$$$\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \sum_{j=1}^m x_{ij} =1, \ \ for\ \ i = QB$$$$\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \sum_{j=1}^m x_{ij}  =2, \ \ for\ \ i = RB$$$$\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \sum_{j=1}^m x_{ij} =3, \ \ for\ \ i = WR$$$$\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \sum_{j=1}^m x_{ij} =1, \ \ for\ \ i = TE$$$$\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \sum_{j=1}^m x_{ij} =1, \ \ for\ \ i = FLEX$$$$\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \sum_{j=1}^m x_{ij} =1, \ \ for\ \ i = DST$$$$\ \ \ \ \ \ \ \ \ \ \ \ \ \sum_{i=1}^n\sum_{j=1}^m x_{ij} = 9$$$$\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ x_{ij} \geq 0,\ \forall \ i,\ j$$***  Daily Fantasy Football Rules$50,000 to spend on your lineup  https://www.draftkings.com/help/rules/nfl ![Offense](https://raw.githubusercontent.com/papagorgio23/Python101/master/DFS%20Offense%20Scoring.png) ![Defense](https://raw.githubusercontent.com/papagorgio23/Python101/master/DFS%20Defense%20Scoring.png)  Python Code  Load Libraries<jupyter_code>!pip install pulp

import urllib, json
import pandas as pd
import re

from pulp import *<jupyter_output>Requirement already satisfied: pulp in /usr/local/lib/python3.6/dist-packages (1.6.10)
Requirement already satisfied: pyparsing>=2.0.1 in /usr/local/lib/python3.6/dist-packages (from pulp) (2.4.2)<jupyter_text>Get Data  DraftKings APIDraftKings API is undocumented... (don't report it to ICE)... If we enter the correct weekID, it will return a list of player prices and scores. We will need to make a few manipulations to get it into a form that we can use for our model.  API URLhttps://api.draftkings.com/draftgroups/v1/draftgroups/21727/draftables?format=json<jupyter_code># Week ID
weekID = '21727'
# input the week ID into the rest of the url
URL = "https://api.draftkings.com/draftgroups/v1/draftgroups/" + weekID + "/draftables?format=json"
URL<jupyter_output><empty_output><jupyter_text>Get Data<jupyter_code># connect to API
response = urllib.request.urlopen(URL)

# extract data
data = json.loads(response.read())

# put it into a dataframe
current = pd.DataFrame.from_dict(data["draftables"])<jupyter_output><empty_output><jupyter_text>Clean DataThis data is in a horrible format. *   There are Dictionaries nested in column*   Dictionary within a List nested in column*   Duplicates*   Irrelevant columns<jupyter_code># View Data
current.head()<jupyter_output><empty_output><jupyter_text>Remove Duplicates<jupyter_code># dropping duplicte Names 
current = current.drop_duplicates(subset = 'displayName', keep = 'first')<jupyter_output><empty_output><jupyter_text>Remove Injured Players<jupyter_code># status counts
current['status'].value_counts()

# Remove players that are out or questionable
current = current[current.status == "None"]
# view data
current.head()<jupyter_output><empty_output><jupyter_text>Extract Points"draftStatAttributes" contains the average fantasy points for each player. However, it is nested in a very annoying way.We need to create a function that will<jupyter_code># examine how draftStatAttributes is formatted
current['draftStatAttributes'][2]
# Create function to extract average points
def get_float(l, key):
    """ Returns first float value from a list of dictionaries based on key. Defaults to 0.0 """
    for d in l:
        try:
            return float(d.get(key))
        except:
            pass
    return 0.0
# use function on dataset
current["points"] = [get_float(x, "value") for x in current.draftStatAttributes]<jupyter_output><empty_output><jupyter_text>Select ColumnsWe only need the player's position, displayName, salary, and points<jupyter_code># subset our data and name it availables
availables = current[["position", "displayName", "salary", "points"]]

# view top 5 players
availables.head()
# reset the index numbers
availables = availables.reset_index(drop=True)

# view top 5 players
availables.head()
# See how many players are available at each position
availables["position"].value_counts()
# See top 15 priced QBs
availables[availables["position"]=="QB"].sort_values(by = 'points', ascending=False).head(15)<jupyter_output><empty_output><jupyter_text>Define The Problem  Using PuLP (Random Example)There was a natural disaster, Earthquake that caused a Tsunami and first aid is being shipped in to help the situation.There are 2 distribution centers (DC1 and DC2) that can ship supplies to either the earthquake location or the tsunami location. Each location needs a set number of supplies. What is the shortest distance needed to ship all the needed supplies?<jupyter_code># initiate the problem statement
prob = LpProblem("Natural Disaster Relief", LpMinimize)

# create the variables
y1 = LpVariable("First Aid shipments from DC1 to Earthquake", 0, None, LpInteger)
y2 = LpVariable("First Aid shipments from DC1 to Tsunami", 0, None, LpInteger)
y3 = LpVariable("First Aid shipments from DC2 to Earthquake", 0, None, LpInteger)
y4 = LpVariable("First Aid shipments from DC2 to Tsunami", 0, None, LpInteger)

# create the objective function 
prob += 240*y1 + 320*y2 + 440*y3 + 180*y4

# create the constraints
prob += y1 + y2 <= 10, "DC1 has 10 shipping containers of First Aid supplies"
prob += y3 + y4 <= 4, "DC2 has 4 shipping containers of First Aid supplies"
prob += y1 + y3 >= 8, "8 containers of supplies needed for Earthquake Relief"
prob += y2 + y4 >= 6, "6 containers of supplies needed for Tsunami Relief"

# solve the problem
prob.solve()

# print each variable with its optimal value
for v in prob.variables():
  print(v.name, "=", v.varValue)

# print the optimized objective function value 
print("\nMinimized total transit distance = ", value(prob.objective),"miles")<jupyter_output><empty_output><jupyter_text>Prepare for LP formulaThe data needs to be transformed slightly differently for PuLP to work with it.$P_{ij} = Points\ Player\ Scores$$C_{ij} = Cost\ of\ Player$<jupyter_code># create 2 dictionaries: one containing the salaries of each player, the other containing the points of each player

# Cost of Player (C_ij)
salaries = {} 

# Points of Player (P_ij)
points = {} 

# loop through each position and appened player name, salary, points to correct dictionary
for pos in availables["position"].unique():
    available_pos = availables[availables["position"] == pos]
    salary = list(available_pos[["displayName","salary"]].set_index("displayName").to_dict().values())[0]
    point = list(available_pos[["displayName","points"]].set_index("displayName").to_dict().values())[0]
    salaries[pos] = salary
    points[pos] = point<jupyter_output><empty_output><jupyter_text>Position Constraints$$\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \sum_{j=1}^m x_{ij} =1, \ \ for\ \ i = QB$$$$\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \sum_{j=1}^m x_{ij}  =2, \ \ for\ \ i = RB$$$$\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \sum_{j=1}^m x_{ij} =3, \ \ for\ \ i = WR$$$$\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \sum_{j=1}^m x_{ij} =1, \ \ for\ \ i = TE$$$$\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \sum_{j=1}^m x_{ij} =1, \ \ for\ \ i = FLEX$$$$\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \sum_{j=1}^m x_{ij} =1, \ \ for\ \ i = DST$$Flex position can be either a RB, WR, or TE. We will run 3 iterations with the flex being each on of these positions.<jupyter_code># Position Constraints
pos_num_available = {
    "QB": 1,
    "RB": 2,
    "WR": 3,
    "TE": 2,
    "DST": 1
}
# Max Salary limit
SALARY_CAP = 50000<jupyter_output><empty_output><jupyter_text>Create Player Variables$x_{ij} = Player$<jupyter_code># Create the variables
_vars = {k: LpVariable.dict(k, v, cat="Binary") for k, v in points.items()}<jupyter_output><empty_output><jupyter_text>Solve Problem<jupyter_code># initialize the problem statement (Maximize)
prob = LpProblem("Fantasy Football Lineup", LpMaximize)

# initialize lists to hold constraints
score = []
salary = []

# Setting up the reward
for k, v in _vars.items():
    salary += lpSum([salaries[k][i] * _vars[k][i] for i in v])
    score += lpSum([points[k][i] * _vars[k][i] for i in v])
    prob += lpSum([_vars[k][i] for i in v]) <= pos_num_available[k]
    

# Salary Constraint
prob += lpSum(salary) <= SALARY_CAP
    
# Objective Function
prob += lpSum(score)
prob.solve()
# my beautiful function to display the results of our LP
def summary(prob):
    div = '\n-----------------------------------------\n'
    print("\n-----------------------------------------")
    print("Linear Programming Optimization Solution:")
    print("-----------------------------------------\n")
    print("Variables:\n")
    score = str(prob.objective)
    constraints = [str(const) for const in prob.constraints.values()]
    for v in prob.variables():
        score = score.replace(v.name, str(v.varValue))
        constraints = [const.replace(v.name, str(v.varValue)) for const in constraints]
        if v.varValue != 0:
            print(v.name, "=", v.varValue)
    print(div)
    print("Salary:\n")
    for constraint in constraints:
        constraint_pretty = " + ".join(re.findall("[0-9\.]*\*1.0", constraint))
        if constraint_pretty != "":
            print("{} = {}".format(constraint_pretty, eval(constraint_pretty)))
    print(div)
    print("Score:\n")
    score_pretty = " + ".join(re.findall("[0-9\.]+\*1.0", score))
    print("{} = {}".format(score_pretty, eval(score)))
    print(div)
    print("Total Cost:  ${}".format(round(eval(constraint_pretty))))
    print("Total Points: {}\n".format(round(eval(score))))
summary(prob)<jupyter_output>-----------------------------------------
Linear Programming Optimization Solution:
-----------------------------------------

Variables:

DST_Bears_ = 1.0
QB_Patrick_Mahomes = 1.0
RB_Alvin_Kamara = 1.0
RB_Melvin_Gordon_III = 1.0
TE_George_Kittle = 1.0
TE_Jared_Cook = 1.0
WR_Golden_Tate = 1.0
WR_Keke_Coutee = 1.0
WR_Tyler_Boyd = 1.0

-----------------------------------------

Salary:

2600*1.0 + 6800*1.0 + 9600*1.0 + 8300*1.0 + 4200*1.0 + 4100*1.0 + 6600*1.0 + 3000*1.0 + 4600*1.0 = 49800.0

-----------------------------------------

Score:

14.5*1.0 + 31.1*1.0 + 36.3*1.0 + 27.9*1.0 + 15.2*1.0 + 20.3*1.0 + 23.0*1.0 + 24.7*1.0 + 19.9*1.0 = 212.9

-----------------------------------------

Total Cost:  $49800
Total Points: 213<jupyter_text>Flex Postion = RB<jupyter_code># salary and points
salaries = {} 
points = {} 
for pos in availables["position"].unique():
    available_pos = availables[availables["position"] == pos]
    salary = list(available_pos[["displayName","salary"]].set_index("displayName").to_dict().values())[0]
    point = list(available_pos[["displayName","points"]].set_index("displayName").to_dict().values())[0]
    salaries[pos] = salary
    points[pos] = point

# Max Salary limit
SALARY_CAP = 50000


# Position Constraints
pos_num_available = {
    "QB": 1,
    "RB": 3, # FLEX POSITION = RB
    "WR": 3, 
    "TE": 1, 
    "DST": 1
}



# initialize the problem statement (Maximize)
prob = LpProblem("Fantasy Football Lineup", LpMaximize)

# Create the variables
_vars = {k: LpVariable.dict(k, v, cat="Binary") for k, v in points.items()}

# initialize lists to hold constraints
score = []
salary = []

# Setting up the reward
for k, v in _vars.items():
    salary += lpSum([salaries[k][i] * _vars[k][i] for i in v])
    score += lpSum([points[k][i] * _vars[k][i] for i in v])
    prob += lpSum([_vars[k][i] for i in v]) <= pos_num_available[k]
    

# Salary Constraint
prob += lpSum(salary) <= SALARY_CAP
    
# Objective Function
prob += lpSum(score)

prob.solve()

summary(prob)<jupyter_output>-----------------------------------------
Linear Programming Optimization Solution:
-----------------------------------------

Variables:

DST_Bears_ = 1.0
QB_Patrick_Mahomes = 1.0
RB_Alvin_Kamara = 1.0
RB_James_White = 1.0
RB_Melvin_Gordon_III = 1.0
TE_Jared_Cook = 1.0
WR_Calvin_Ridley = 1.0
WR_Keke_Coutee = 1.0
WR_Tyler_Boyd = 1.0

-----------------------------------------

Salary:

2600*1.0 + 6800*1.0 + 9600*1.0 + 5400*1.0 + 8300*1.0 + 4100*1.0 + 4900*1.0 + 3000*1.0 + 4600*1.0 = 49300.0

-----------------------------------------

Score:

14.5*1.0 + 31.1*1.0 + 36.3*1.0 + 19.1*1.0 + 27.9*1.0 + 20.3*1.0 + 20.4*1.0 + 24.7*1.0 + 19.9*1.0 = 214.20000000000002

-----------------------------------------

Total Cost:  $49300
Total Points: 214<jupyter_text>Flex Postion = WR<jupyter_code># salary and points
salaries = {} 
points = {} 
for pos in availables["position"].unique():
    available_pos = availables[availables["position"] == pos]
    salary = list(available_pos[["displayName","salary"]].set_index("displayName").to_dict().values())[0]
    point = list(available_pos[["displayName","points"]].set_index("displayName").to_dict().values())[0]
    salaries[pos] = salary
    points[pos] = point

# Max Salary limit
SALARY_CAP = 50000


# Position Constraints
pos_num_available = {
    "QB": 1,
    "RB": 2,
    "WR": 4, # FLEX POSITION = WR
    "TE": 1, 
    "DST": 1
}



# initialize the problem statement (Maximize)
prob = LpProblem("Fantasy Football Lineup", LpMaximize)

# Create the variables
_vars = {k: LpVariable.dict(k, v, cat="Binary") for k, v in points.items()}

# initialize lists to hold constraints
score = []
salary = []

# Setting up the reward
for k, v in _vars.items():
    salary += lpSum([salaries[k][i] * _vars[k][i] for i in v])
    score += lpSum([points[k][i] * _vars[k][i] for i in v])
    prob += lpSum([_vars[k][i] for i in v]) <= pos_num_available[k]
    

# Salary Constraint
prob += lpSum(salary) <= SALARY_CAP
    
# Objective Function
prob += lpSum(score)

prob.solve()

summary(prob)<jupyter_output>-----------------------------------------
Linear Programming Optimization Solution:
-----------------------------------------

Variables:

DST_Bears_ = 1.0
QB_Patrick_Mahomes = 1.0
RB_Alvin_Kamara = 1.0
RB_Melvin_Gordon_III = 1.0
TE_Jared_Cook = 1.0
WR_Calvin_Ridley = 1.0
WR_DeSean_Jackson = 1.0
WR_Keke_Coutee = 1.0
WR_Tyler_Boyd = 1.0

-----------------------------------------

Salary:

2600*1.0 + 6800*1.0 + 9600*1.0 + 8300*1.0 + 4100*1.0 + 4900*1.0 + 5700*1.0 + 3000*1.0 + 4600*1.0 = 49600.0

-----------------------------------------

Score:

14.5*1.0 + 31.1*1.0 + 36.3*1.0 + 27.9*1.0 + 20.3*1.0 + 20.4*1.0 + 21.6*1.0 + 24.7*1.0 + 19.9*1.0 = 216.70000000000002

-----------------------------------------

Total Cost:  $49600
Total Points: 217<jupyter_text>Flex Postion = TE<jupyter_code># salary and points
salaries = {} 
points = {} 
for pos in availables["position"].unique():
    available_pos = availables[availables["position"] == pos]
    salary = list(available_pos[["displayName","salary"]].set_index("displayName").to_dict().values())[0]
    point = list(available_pos[["displayName","points"]].set_index("displayName").to_dict().values())[0]
    salaries[pos] = salary
    points[pos] = point

# Max Salary limit
SALARY_CAP = 50000


# Position Constraints
pos_num_available = {
    "QB": 1,
    "RB": 2,
    "WR": 3,
    "TE": 2, # FLEX POSITION = TE
    "DST": 1
}



# initialize the problem statement (Maximize)
prob = LpProblem("Fantasy Football Lineup", LpMaximize)

# Create the variables
_vars = {k: LpVariable.dict(k, v, cat="Binary") for k, v in points.items()}

# initialize lists to hold constraints
score = []
salary = []

# Setting up the reward
for k, v in _vars.items():
    salary += lpSum([salaries[k][i] * _vars[k][i] for i in v])
    score += lpSum([points[k][i] * _vars[k][i] for i in v])
    prob += lpSum([_vars[k][i] for i in v]) <= pos_num_available[k]
    

# Salary Constraint
prob += lpSum(salary) <= SALARY_CAP
    
# Objective Function
prob += lpSum(score)

prob.solve()

summary(prob)<jupyter_output>-----------------------------------------
Linear Programming Optimization Solution:
-----------------------------------------

Variables:

DST_Bears_ = 1.0
QB_Patrick_Mahomes = 1.0
RB_Alvin_Kamara = 1.0
RB_Melvin_Gordon_III = 1.0
TE_George_Kittle = 1.0
TE_Jared_Cook = 1.0
WR_Golden_Tate = 1.0
WR_Keke_Coutee = 1.0
WR_Tyler_Boyd = 1.0

-----------------------------------------

Salary:

2600*1.0 + 6800*1.0 + 9600*1.0 + 8300*1.0 + 4200*1.0 + 4100*1.0 + 6600*1.0 + 3000*1.0 + 4600*1.0 = 49800.0

-----------------------------------------

Score:

14.5*1.0 + 31.1*1.0 + 36.3*1.0 + 27.9*1.0 + 15.2*1.0 + 20.3*1.0 + 23.0*1.0 + 24.7*1.0 + 19.9*1.0 = 212.9

-----------------------------------------

Total Cost:  $49800
Total Points: 213
{'fraction_non_alphanumeric': 0.2097710592616935, 'fraction_numerical': 0.042611457991017634, 'mean_word_length': 2.6976508707978937, 'pattern_counts': {'":': 21, '<': 70, '<?xml version=': 0, '>': 63, 'https://': 7, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 2, 'word_list_counts': {'cursed_substrings.json': 59, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '16', 'dir': 'jupyter-structured-clean-dedup', 'id': '259836', 'license': 'MIT', 'n_tokens_mistral': 6984, 'n_tokens_neox': 6406, 'n_words': 1616, 'path': 'Fantasy_Football_Lineup_Optimizer_Complete.ipynb', 'repo_name': 'papagorgio23/Python101', 'size': '18258'}