如何为Pandas DataFrame生成带行列索引的数值比较矩阵?
生成以姓名为索引的分数差值矩阵的最优方案
嘿,我来给你说个最高效的方法,完全不用费劲去遍历itertools.combinations,用pandas结合numpy的广播特性就能一步搞定!
首先先确认你的初始DataFrame:
import pandas as pd df = pd.DataFrame({'Name': ['Harry', 'John', 'Peter', 'Stan', 'Petra'], 'Score': [10, 9, 5, 7, 8]})
接下来直接生成你要的差值矩阵,核心就是利用广播运算来批量计算所有两两分数的差值,同时把姓名设为行列索引:
# 用numpy广播计算所有两两分数差,再包装成带姓名索引的DataFrame diff_matrix = pd.DataFrame( df['Score'].values[:, None] - df['Score'].values, index=df['Name'], columns=df['Name'] )
运行这段代码后,你得到的diff_matrix就是完全符合要求的矩阵:
Harry John Peter Stan Petra Harry 0 1 5 3 2 John -1 0 4 2 1 Peter -5 -4 0 -2 -3 Stan -3 -2 2 0 1 Petra -2 -1 3 -1 0
为什么这是最优方法?
- 效率拉满:广播是numpy底层优化的向量运算,比用
itertools手动遍历组合快得多,数据量越大优势越明显 - 代码极简:一行核心逻辑就生成完整矩阵,不用手动处理两两组合的正反差值,也不用额外构建索引
- 完整性高:自动包含每个姓名和自身的差值(也就是0),完全覆盖所有可能的行列组合
要是你用itertools.combinations的话,还得手动处理正反差值、补充自身对比的情况,代码会繁琐很多,比如这样:
from itertools import combinations # 手动构建差值字典 diff_dict = {} # 处理两两不同的组合 for (name1, score1), (name2, score2) in combinations(df.itertuples(index=False), 2): diff_dict[(name1, name2)] = score1 - score2 diff_dict[(name2, name1)] = score2 - score1 # 处理自身对比的情况 for name in df['Name']: diff_dict[(name, name)] = 0 # 转成DataFrame diff_matrix_from_itertools = pd.Series(diff_dict).unstack()
对比下来,广播的方法不管是代码简洁度还是运行效率都完胜,绝对是最优解!
内容的提问来源于stack exchange,提问作者ben121
相关产品推荐
相关产品推荐

