如何用Python从对战结果列表生成胜率矩阵?
构建角色对战胜率矩阵的实现方法
需求说明
给定包含角色对战胜负记录的Pandas DataFrame,需要生成一个行/列索引均为角色A-E的胜率矩阵:
- 单元格值为行角色对阵列角色的胜率
- 对角线(同角色对战)固定为50%
- 需合并双向对战记录计算胜率(如A对B和B对A的记录需合并,计算A对阵B的胜率)
实现步骤与代码
1. 导入依赖并初始化数据
import pandas as pd import itertools # 原始对战记录 df = pd.DataFrame( data=[['A', 'B'], ['D', 'D'], ['E', 'A'], ['C', 'D'], ['E', 'D']], columns=['Winner', 'Loser'] )
2. 生成所有角色对战组合
先定义所有角色列表,再生成行和列的全量组合:
characters = ['A', 'B', 'C', 'D', 'E'] # 生成所有(row角色, col角色)的组合 combinations = list(itertools.product(characters, characters)) comb_df = pd.DataFrame(combinations, columns=['Row', 'Col'])
3. 统计胜负次数并计算胜率
首先统计每个角色击败其他角色的次数,再通过转置得到被击败的次数,最后计算胜率:
# 统计每个(Winner, Loser)的对战次数 win_counts = df.groupby(['Winner', 'Loser']).size().unstack(fill_value=0) # 转置得到每个(Loser, Winner)的对战次数(即角色输给对手的次数) loss_counts = win_counts.T # 定义胜率计算函数 def get_win_rate(row): row_char, col_char = row['Row'], row['Col'] # 同角色对战固定50%胜率 if row_char == col_char: return 0.5 # 获取row角色击败col角色的次数 wins = win_counts.loc[row_char, col_char] if (row_char in win_counts.index and col_char in win_counts.columns) else 0 # 获取row角色输给col角色的次数 losses = loss_counts.loc[row_char, col_char] if (row_char in loss_counts.index and col_char in loss_counts.columns) else 0 total_matches = wins + losses # 无对战记录返回NaN,否则计算胜率 return wins / total_matches if total_matches > 0 else None # 计算所有组合的胜率 comb_df['Win_Rate'] = comb_df.apply(get_win_rate, axis=1)
4. 转换为胜率矩阵
将组合数据透视成矩阵,可选格式化百分比显示:
# 生成基础胜率矩阵 win_rate_matrix = comb_df.pivot(index='Row', columns='Col', values='Win_Rate') # 格式化百分比(可选,便于阅读) win_rate_matrix_formatted = win_rate_matrix.applymap( lambda x: f"{x*100:.1f}%" if pd.notna(x) else "-" ) # 打印结果 print(win_rate_matrix_formatted)
输出示例
运行上述代码后,会得到如下格式化矩阵:
Col A B C D E Row A 50.0% 100.0% - 0.0% 0.0% B 0.0% 50.0% - - - C - - 50.0% 100.0% - D - - 0.0% 50.0% 0.0% E 100.0% - - 100.0% 50.0%
关键逻辑说明
- 合并双向对战记录:通过
win_counts和转置后的loss_counts,将A对B和B对A的记录合并计算A的胜率 - 同角色处理:直接返回50%胜率,无需统计对战次数
- 无对战记录:返回
NaN并格式化显示为-,可根据需求调整为0或其他值
内容的提问来源于stack exchange,提问作者Waroulolz
相关产品推荐
相关产品推荐

