抱歉,如果这是一个相当复杂的问题。 我有一个 pandas 数据框,记录不同玩家之间的比赛结果:
Race_ID
记录不同的比赛
Racer_ID
记录不同的玩家
N
表示该游戏的玩家人数
Place
表示该场比赛的结果,1
为获胜者,2
为亚军,依此类推。
我想添加一个名为
Elo_rating
的新列来表示该玩家的当前 elo 评级,使用以下针对 n 玩家 elo 的算法:
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
其中 D=400,如果这是该玩家的第一场比赛,则设置 E_i = 1/N
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。
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
但我不知道如何实现它。非常感谢。
# 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