在 pandas 数据框中实现 n 名玩家 Elo 评级

问题描述 投票:0回答:1

抱歉,如果这是一个相当复杂的问题。 我有一个 pandas 数据框,记录不同玩家之间的比赛结果:

Race_ID
记录不同的比赛

Racer_ID
记录不同的玩家

N
表示该游戏的玩家人数

Place
表示该场比赛的结果,
1
为获胜者,
2
为亚军,依此类推。

我想添加一个名为

Elo_rating
的新列来表示该玩家的当前 elo 评级,使用以下针对 n 玩家 elo 的算法:

  1. 如果这是该玩家的第一场游戏,则给他们 elo 评分 400:
Date        Race_ID     N   Racer_ID    Place   Elo_rating
1/12/2021   10055116    4   1           3       400
1/12/2021   10055116    4   2           2       400
1/12/2021   10055116    4   3           1       400
1/12/2021   10055116    4   4           4       400
3/5/2022    10055117    3   2           1       
3/5/2022    10055117    3   3           2       
3/5/2022    10055117    3   4           3       
2/12/2022   10055118    5   1           3       
2/12/2022   10055118    5   3           5       
2/12/2022   10055118    5   4           2       
2/12/2022   10055118    5   5           4       400
2/12/2022   10055118    5   6           1       400
1/1/2023    10055119    4   1           1       
1/1/2023    10055119    4   4           3       
1/1/2023    10055119    4   5           4       
1/1/2023    10055119    4   6           2       
  1. 通过以下公式计算玩家 x 的期望评分:

enter image description here

其中 D=400,如果这是该玩家的第一场比赛,则设置 E_i = 1/N

  1. 比赛结果出来后,选手 i 的得分函数为

S_i = (N - 位置) / (N(N-1)/2)

例如,第一场比赛后(Race_ID = 10055116)玩家 1、2、3、4 的得分分别为

S_1 = (4-3) / (4(3)/2) = 1/6,

S_2 = (4-2) / (4(3)/2) = 2/6,

S_3 = (4-1) / (4(3)/2) = 3/6,

S_4 = (4-4) / (4(3)/2) = 0/6。

  1. 最后下一场比赛的 elo 评级更新由
  2. 给出

E_i<- R_i + 30(S_i - E_i)

例如,第二场比赛的 elo 评级(Race_ID = 10055117)由下式给出:

Date        Race_ID     N   Racer_ID    Place   Elo_rating
1/12/2021   10055116    4   1           3       400
1/12/2021   10055116    4   2           2       400
1/12/2021   10055116    4   3           1       400
1/12/2021   10055116    4   4           4       400
3/5/2022    10055117    3   2           1       402.5
3/5/2022    10055117    3   3           2       407.5
3/5/2022    10055117    3   4           3       392.5
2/12/2022   10055118    5   1           3       397.5
2/12/2022   10055118    5   3           5       407.212315853
2/12/2022   10055118    5   4           2       382.859605171
2/12/2022   10055118    5   5           4       400
2/12/2022   10055118    5   6           1       400
1/1/2023    10055119    4   1           1       
1/1/2023    10055119    4   4           3       
1/1/2023    10055119    4   5           4       
1/1/2023    10055119    4   6           2       

所需的输出由下式给出:

Date Race_ID N Racer_ID Place Elo_rating 1/12/2021 10055116 4 1 3 400 1/12/2021 10055116 4 2 2 400 1/12/2021 10055116 4 3 1 400 1/12/2021 10055116 4 4 4 400 3/5/2022 10055117 3 2 1 402.5 3/5/2022 10055117 3 3 2 407.5 3/5/2022 10055117 3 4 3 392.5 2/12/2022 10055118 5 1 3 397.5 2/12/2022 10055118 5 3 5 407.212315853 2/12/2022 10055118 5 4 2 382.859605171 2/12/2022 10055118 5 5 4 400 2/12/2022 10055118 5 6 1 400 1/1/2023 10055119 4 1 1 383.501122 1/1/2023 10055119 4 4 3 372.913004 1/1/2023 10055119 4 5 4 382.8213312 1/1/2023 10055119 4 6 2 391.8213312
我不知道如何解决这个问题,但我想我们应该从 

groupby

 Racer_ID 开始,然后应用 
.map
 但我不知道如何实现它。非常感谢。

python python-3.x pandas dataframe group-by
1个回答
0
投票
你可以尝试(注意,我相信比赛 10055119 的 elo 评级应该根据你的公式与你的预期输出不同):

# set ELO for first game for player to 400 elos = dict.fromkeys(df["Racer_ID"].unique(), 400) out = [] for i, (_, g) in enumerate(df.groupby("Race_ID")): N = len(g) g["Elo_rating"] = df["Racer_ID"].map(elos) # update elos: tmp = {} for racer, place in zip(g["Racer_ID"], g["Place"]): if i == 0: E = 1 / N else: E = 0 for p in g["Racer_ID"]: if p == racer: continue E += 1 / (1 + 10 ** ((elos[p] - elos[racer]) / 400)) E /= (N * (N - 1)) / 2 S = (N - place) / ((N * (N - 1)) / 2) tmp[racer] = elos[racer] + 30 * (S - E) elos.update(tmp) out.append(g) out = pd.concat(out) print(out)
打印:

Date Race_ID N Racer_ID Place Elo_rating 0 1/12/2021 10055116 4 1 3 400.000000 1 1/12/2021 10055116 4 2 2 400.000000 2 1/12/2021 10055116 4 3 1 400.000000 3 1/12/2021 10055116 4 4 4 400.000000 4 3/5/2022 10055117 3 2 1 402.500000 5 3/5/2022 10055117 3 3 2 407.500000 6 3/5/2022 10055117 3 4 3 392.500000 7 2/12/2022 10055118 5 1 3 397.500000 8 2/12/2022 10055118 5 3 5 407.212316 9 2/12/2022 10055118 5 4 2 382.859605 10 2/12/2022 10055118 5 5 4 400.000000 11 2/12/2022 10055118 5 6 1 400.000000 12 1/1/2023 10055119 4 1 1 397.500337 13 1/1/2023 10055119 4 4 3 386.175625 14 1/1/2023 10055119 4 5 4 396.946399 15 1/1/2023 10055119 4 6 2 405.946399
    
© www.soinside.com 2019 - 2024. All rights reserved.