Skip to content

Instantly share code, notes, and snippets.

@lspinheiro
Created June 11, 2021 06:33
Show Gist options
  • Save lspinheiro/7132828e8f1fa58565e8f3b71e2eae33 to your computer and use it in GitHub Desktop.
Save lspinheiro/7132828e8f1fa58565e8f3b71e2eae33 to your computer and use it in GitHub Desktop.
Elo implementation for MMA
def calc_elo_rank(df: pd.DataFrame) -> pd.DataFrame:
elo_scorer = Elo(k = 20)
fighter_set = set(df['winner_slog'].unique().tolist() + df['loser_slog'].unique().tolist())
for fighter in fighter_set:
elo_scorer.add_player(fighter)
elo_f1 = np.zeros((len(df,)))
elo_f2 = np.zeros((len(df,)))
for rowidx, fs_row in tqdm(enumerate(df.itertuples())):
fighter = fs_row.winner_slog
opponent = fs_row.loser_slog
score = fs_row.win_method_score
elo_f1[rowidx] = elo_scorer[fighter]
elo_f2[rowidx] = elo_scorer[opponent]
elo_scorer.update_ratings(fighter, opponent, score)
df.loc[:, 'elo_f1'] = elo_f1
df.loc[:, 'elo_f2'] = elo_f2
return df
class Elo:
def __init__(self, k: int):
self.rating_dict = {}
self.k = k
def __getitem__(self, player: str) -> float:
return self.rating_dict[player]
def __setitem__(self, player: str, data: float) -> None:
self.rating_dict[player] = data
def get_margin_factor(self, score: float) -> float:
return np.log2(score + 1)
def get_inflation_factor(self, r_win: float, r_lose: float) -> float:
return 1 / (1 - ((r_lose - r_win) / 2200))
def add_player(self, name: str, rating: float = 1500.):
self.rating_dict[name] = rating
def update_ratings(self, winner: str, loser: str, score: float) -> None:
expected_result = self.get_expect_result(
self.rating_dict[winner], self.rating_dict[loser]
)
margin_factor = self.get_margin_factor(score)
inflation_factor = self.get_inflation_factor(
self.rating_dict[winner], self.rating_dict[loser]
)
self.rating_dict[winner] = self.rating_dict[winner] + self.k * margin_factor * inflation_factor * (1 - expected_result)
self.rating_dict[loser] = self.rating_dict[loser] + self.k * margin_factor * inflation_factor * (-1 + expected_result)
def get_expect_result(self, p1: float, p2: float) -> float:
exp = (p2 - p1) / 400.0
return 1 / ((10.0 ** (exp)) + 1)
def get_win_method_weight(x: str) -> float:
if "Decision" in x:
if "Split" in x:
return 1.
else:
return 3.
elif "KO" in x:
return 5.
elif "Submission" in x:
return 5.
else:
return 0.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment