如何计算两个DataFrame间的余弦距离并生成新结果DataFrame
两个DataFrame行向量两两余弦距离计算方案
首先注意:你提供的示例代码中构造DataFrame B时误用了group_a作为输入,会导致B和A内容完全一致,实际使用时需要传入group_b,修正后的基础数据代码如下:
import pandas as pd import numpy as np # 构造原始数据 group_a = {'0':[2.0,9.4,10.8,0.6,9.4,0.1], '1':[4.2,7.1,3,6.3,7.8,0.01], '3':[8.1,9.5,6.1,5.6,2,2.2] } A = pd.DataFrame(group_a, index=['aa','ab','ac','ad','ae','af']) group_b = {'0':[7.0,5.8,11.0,5.8,2.1,2.4], '1':[5.3,9.9,0.7,4.4,1.6,0.6], '3':[6.7,0.2,3.9,7.5,7.9,5.6] } # 原示例此处错写为group_a,已修正 B = pd.DataFrame(group_b, index=['ba','bb','bc','bd','be','bf'])
方案1:纯NumPy手写实现(无额外依赖)
逻辑:余弦距离 = 1 - 余弦相似度,余弦相似度 = 两向量点积 / (两向量L2模长的乘积),利用numpy广播机制可直接批量计算所有向量对的结果:
# 转换为numpy数组 a_arr = A.values b_arr = B.values # 计算点积矩阵 dot_product = a_arr @ b_arr.T # 计算A、B各自每行向量的L2模长 a_norm = np.linalg.norm(a_arr, axis=1, keepdims=True) b_norm = np.linalg.norm(b_arr, axis=1, keepdims=True) # 计算余弦相似度,再转换为余弦距离 cosine_dist = 1 - dot_product / (a_norm @ b_norm.T) # 转换为要求格式的DataFrame result = pd.DataFrame( cosine_dist, index=A.index, columns=B.index )
方案2:调用SciPy接口实现(适合大数据量场景,性能更优)
直接使用scipy提供的批量距离计算函数cdist,指定距离度量为余弦距离即可,代码更简洁:
from scipy.spatial.distance import cdist # 直接计算两两余弦距离 cosine_dist = cdist(A.values, B.values, metric='cosine') # 转换为目标格式DataFrame result = pd.DataFrame( cosine_dist, index=A.index, columns=B.index )
结果说明
运行后得到的result完全匹配格式要求:
- 行索引与原DataFrame A一致(aa~af)
- 列索引与原DataFrame B一致(ba~bf)
- 每个单元格的值对应当前行、列两个向量的余弦距离,取值范围为[0,2],值越小代表两个向量方向越相似。
如果按照你最初写错的B构造逻辑(B和A内容完全一致)运行,结果对角线值全为0,符合相同向量余弦距离为0的预期。
内容的提问来源于stack exchange,提问作者newbzzs
相关产品推荐
相关产品推荐

