Skip to content

Instantly share code, notes, and snippets.

@adrialuzllompart
Last active January 17, 2018 14:34
Show Gist options
  • Save adrialuzllompart/2d1063596ba5c25e379c109d86b4ee5a to your computer and use it in GitHub Desktop.
Save adrialuzllompart/2d1063596ba5c25e379c109d86b4ee5a to your computer and use it in GitHub Desktop.
from __future__ import division
import numpy as np
import pandas as pd
import random
from datetime import date
def expected(A, B):
"""
Calculate expected score of team A in a match against team B
parameters
-------------------------
A: float
Elo rating for team A
B: float
Elo rating for team B
"""
return 1 / (1 + 10 ** ((B - A) / 400))
def elo(old, exp, score, k=32):
"""
Calculate the new Elo rating for the players in a given team
parameters
--------------------------
old: float
The previous Elo rating
exp: float
The expected probability of winning for this match
score: int
The actual score for this match (1 for win, 0 for loss)
k: int
The k-factor for Elo (default: 32)
"""
return old + k * (score - exp)
# read in the latest data
filename = 'C:/Users/aluz/Desktop/elo_football/elo_football.csv'
df = pd.read_csv(filename)
# have the teams already been selected?
x = raw_input('Have the teams already been selected (y or n)? >')
# if they have...
if x == 'y':
# input the names of the players who play for team 1
team_1_str = raw_input('Players in team 1 (separate with a comma) >')
# and convert that string to a list where each item is a player of team 1
team_1 = team_1_str.split(',')
# input the names of the players who play for team 2
team_2_str = raw_input('Players in team 2 (separate with a comma) >')
# and convert that string to a list where each item is a player of team 2
team_2 = team_2_str.split(',')
# calculate the team ratings by adding up the individual ratings of the players in each team
team_1_ratings = df.loc[df.player.isin(team_1), 'rating'].sum()
team_2_ratings = df.loc[df.player.isin(team_2), 'rating'].sum()
# calculate the expected probabilities of winning for each team,
# according to the Elo expected function defined above
exp_1 = expected(team_1_ratings, team_2_ratings)
exp_2 = 1 - exp_1
# print the probability of winning for team 1, as well as what players are playing in each team
print 'Probability of team 1 winning = ', exp_1
print 'Team 1: ', team_1
print 'Team 2: ', team_2
# if the teams haven't been selected yet...
else:
# input the names of all the players that are available for the game (8 to 12 players)
available = raw_input('List of players that are playing today (separate with a comma) >')
# and convert that string to a list where each item is a player
available_list = available.split(',')
# calculate the number of players in team 1
# if the length of the list is an even number, n will be equal to the number of players in each team
# if the length of the list is an odd number, n will be equal to the number of players in team 1
# team 2 will have len(available_list) - n players
# e.g. if there are 9 players, int(9 / 2) = 4, so team 1 will have 4 players and team 2 will have 5 players
n = int(len(available_list) / 2)
# initialize an empty list of players for team 1
team_1 = []
# initialize exp and iterations variables
exp = 0
iterations = 0
# repeat the following while the teams are not balanced enough
# for them to be balanced, the probability of winning for team 1
# has to be between 40 and 60%
while (exp <= 0.40) | (exp >= 0.60):
# re-create the list of all players every time
available_list = available.split(',')
team_1 = []
# do this as many times as there are players in team 1
for i in range(n):
# select a random player from the whole list of players available
name = random.choice(available_list)
# add that name to team 1
team_1.append(name)
# remove that name from the list to ensure we don't draw it again
available_list.remove(name)
# team 2 will be formed by all the players available that are not in team 1
team_2 = [player for player in available.split(',') if player not in team_1]
# calculate the ratings for each team, based on this random split
team_1_ratings = df.loc[df.player.isin(team_1), 'rating'].sum()
team_2_ratings = df.loc[df.player.isin(team_2), 'rating'].sum()
# calculate the expected probability of winning for team 1
# if this is not between 40 and 60%, the loop will run again
exp = expected(team_1_ratings, team_2_ratings)
iterations += 1
# set the final expectations of winning for each team
exp_1 = exp
exp_2 = 1 - exp_1
# print how many iterations it took the while loop to find a balanced match
# as well as the expected probability of winning for team 1
# and who's in each team
print iterations
print 'Probability of team 1 winning = ', exp_1
print 'Team 1: ', team_1
print 'Team 2: ', team_2
# after the game, input the number of the team that won the match
winning_team = raw_input('Who won? 1 or 2? >')
# if team 1 won, set their score to 1 and team 2's score to 0, and viceversa
if winning_team == '1':
score_1 = 1
score_2 = 0
else:
score_1 = 0
score_2 = 1
# calculate the difference between the current team rating and the new Elo rating
# based on the elo function defined above
diff_1 = elo(team_1_ratings, exp_1, score_1) - team_1_ratings
diff_2 = elo(team_2_ratings, exp_2, score_2) - team_2_ratings
# create a copy of the original table
df_new = df.copy()
# adjust the ratings of each player based on whether they won or lost
# the adjustment is the difference calculated above
df_new.loc[df_new.player.isin(team_1), 'rating'] += diff_1
df_new.loc[df_new.player.isin(team_2), 'rating'] += diff_2
# overwrite the original file with the new file, which has the adjusted player ratings
df_new.to_csv(filename, index=False)
# read in the historical data
filename_hist = 'C:/Users/aluz/Desktop/elo_football/elo_football_history.csv'
df_hist = pd.read_csv(filename_hist)
# format the date properly
df_hist.date = pd.to_datetime(df_hist.date, format='%d/%m/%Y')
# add the new (most up-to-date) ratings to the historical ones
df_hist_expanded = pd.concat([df_hist, df_new], axis=0)
# add today's date as the date for the new ratings
# we want to add the dates so in the future we will be able to plot the ratings over time
df_hist_expanded.date.fillna(date.today(), inplace=True)
# save the historical data
df_hist_expanded.to_csv(filename_hist, index=False)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment