我有玩家
A
和
B
,他们都与不同的对手交手。
玩家 | 对手 | 几天前 |
---|---|---|
A | C | 1 |
A | C | 2 |
A | D | 10 |
A | F | 100 |
A | F | 101 |
A | F|| |102 | A |
G | 1 | B |
C | 1 | B |
C | 2 | B |
D | 10 | B |
F | 100 | B |
F | 101 | B |
F | 102 | B |
G | 1|| |B | G |
2 | B | G |
3 | B | G |
4 | B | G |
5 | B | G |
6 | B | G |
7 | B | G |
8 | 首先,我想找到最常见的对手。我对“最常见”的定义不是匹配总数,而是匹配的平衡数量。 例如,如果玩家 | 和 |
分别与玩家打了99次和1次
1
我更喜欢对手
2
,其中
3
和
4
都打了49次。
A
为了测量“平衡性”,我编写了以下函数:
B
此函数按预期工作:
如果我在不同的对手上运行该函数,我会看到以下结果:
import numpy as np
from collections import Counter
def balanceness(array: np.ndarray):
classes = [(c, cnt) for c, cnt in Counter(array).items()]
m = len(classes)
n = len(array)
H = -sum([(cnt / n) * np.log((cnt / n)) for c, cnt in classes])
return H / np.log(m)
对手
>> balanceness(array=np.array([0, 0, 0, 1, 1, 1]))
1.0
平衡性|| |n_matches
C | 1 | 4 |
---|---|---|
D | 1 | 2 |
F | 1 | 6 |
G | 0.5032583347756457 | 9 |
显然,对手 | 是最常见的。然而, | 和 |
对抗
F
的匹配相对较旧。
A
我应该如何将新近度因素纳入我的计算中以找到“最近的共同对手”?
B
编辑|| |经过更多思考后,我决定使用以下函数对每场比赛进行加权
F
我将所有比赛对每个对手的权重相加
对手
平衡性
n_matches
def weight(days_ago: int, epilson: float=0.005) -> float:
return np.exp(-1 * days_ago * epilson)
weighted_n_matches
C | 1 | 4 | 3.9701246258837 |
---|---|---|---|
D | 1 | 2 | 1.90245884900143 |
F | 1 | 6 | 3.62106362790388 |
G|| |0.5032583347756457 | 9 | 8.81753570603108 | 现在,对手 |
是“最近平衡的对手”。 | 然而,此方法忽略了玩家级别的“近期性”,因为我们将价值观。可能存在一种情况,玩家 | 最近与玩家 | 进行了很多比赛,而玩家 |
在遥远的过去面对过玩家
C
我们如何找到对手
1
两名玩家之间最平衡/分布最均匀的
3
最近与两名玩家进行过比赛的对手
2
faced player
3
in the distant past.
How can we find the opponent that is
- the most balanced / equally-distributed between two players
- the opponent with the most recent matches against the two players
为了找到符合你标准的对手,你需要结合平衡性和新近度。以下是一种可能的方法:
1. 计算加权平衡度
你对个别比赛进行加权的想法是好的。我们可以调整它以计算每个对手的加权平衡度得分。
2. 计算加权新近度
我们也可以为每个对手计算加权新近度得分。
3. 结合得分
最后,我们可以结合加权平衡度得分和加权新近度得分,得到一个综合得分,用于确定最符合你标准的对手。
以下是如何实现此方法的示例代码:
import numpy as np
from collections import Counter
def weight(days_ago: int, epsilon: float = 0.005) -> float:
return np.exp(-1 * days_ago * epsilon)
def opponent_score(player1_matches: list, player2_matches: list, epsilon: float = 0.005) -> dict:
"""计算每个对手的综合得分,结合了平衡性和新近度。
Args:
player1_matches: 玩家 1 比赛的列表,每个元素是一个包含对手和天数的元组。
player2_matches: 玩家 2 比赛的列表,每个元素是一个包含对手和天数的元组。
epsilon: 用于加权函数的衰减因子。
Returns:
一个字典,其中键是对手,值是它们的综合得分。
"""
# 创建一个字典来存储每个对手的比赛次数和总权重
opponent_data = {}
for player_matches in [player1_matches, player2_matches]:
for opponent, days_ago in player_matches:
if opponent not in opponent_data:
opponent_data[opponent] = {'count': [0, 0], 'weight': [0, 0]}
opponent_data[opponent]['count'][player_matches == player1_matches] += 1
opponent_data[opponent]['weight'][player_matches == player1_matches] += weight(days_ago, epsilon)
# 计算每个对手的加权平衡度和加权新近度得分
opponent_scores = {}
for opponent, data in opponent_data.items():
total_matches = sum(data['count'])
balance_score = min(data['count']) / total_matches if total_matches > 0 else 0
recency_score = sum(data['weight']) / total_matches if total_matches > 0 else 0
opponent_scores[opponent] = (balance_score + recency_score) / 2
return opponent_scores
# 示例数据
player_a_matches = [('C', 1), ('C', 2), ('D', 10), ('F', 100), ('F', 101), ('F', 102)]
player_b_matches = [('C', 1), ('C', 2), ('D', 10), ('F', 100), ('F', 101), ('F', 102), ('G', 1), ('G', 2), ('G', 3), ('G', 4), ('G', 5), ('G', 6), ('G', 7), ('G', 8)]
# 计算对手得分
opponent_scores = opponent_score(player_a_matches, player_b_matches)
# 打印得分
for opponent, score in sorted(opponent_scores.items(), by=lambda item: item[1], reverse=True):
print(f"Opponent: {opponent}, Score: {score:.4f}")
此代码将输出每个对手及其综合得分的列表。得分越高的对手在平衡性和新近度方面都得分更高。你可以根据你的具体需求调整加权函数和得分组合方法。
标签:python,numpy,counter From: 78823898