在Pandas中计算连续行的逐行余弦相似度
计算DataFrame连续两行的余弦相似度
问题描述
需要对按id和date排序后的DataFrame,计算每连续两行基于所有特征列(共32列)的余弦相似度。此前尝试的代码会计算每行与所有特征行的相似度,不符合需求。
解决方案
核心思路是提取连续的两行特征向量对,针对性计算它们的余弦相似度,而非让每行和所有行做对比。
方法1:使用sklearn的cosine_similarity
import pandas as pd import numpy as np from sklearn.metrics.pairwise import cosine_similarity # 构造示例数据(按id和date排序后的结构) df = pd.DataFrame(np.random.randint(0, 5, (5, 5)), columns=['id', 'date', 'feature1', 'feature2', 'feature3']) # 提取所有特征列 features = df.iloc[:, 2:] # 获取连续的两行特征向量组:前n-1行 和 后n-1行 prev_rows = features.iloc[:-1].values next_rows = features.iloc[1:].values # 计算每对连续行的余弦相似度(取结果矩阵的对角线值) similarities = cosine_similarity(prev_rows, next_rows).diagonal() # 将结果合并到原DataFrame,第一行无前置行,填充NaN df['cosine_similarity'] = [np.nan] + list(similarities)
方法2:手动计算(无需依赖sklearn)
如果环境无法安装sklearn,可以手动实现余弦相似度的计算逻辑:
import pandas as pd import numpy as np df = pd.DataFrame(np.random.randint(0, 5, (5, 5)), columns=['id', 'date', 'feature1', 'feature2', 'feature3']) features = df.iloc[:, 2:] prev_rows = features.iloc[:-1].values next_rows = features.iloc[1:].values # 计算向量点积 dot_products = np.sum(prev_rows * next_rows, axis=1) # 计算向量的模长 prev_norms = np.linalg.norm(prev_rows, axis=1) next_norms = np.linalg.norm(next_rows, axis=1) # 计算余弦相似度(加极小值避免除以0) similarities = dot_products / (prev_norms * next_norms + 1e-10) df['cosine_similarity'] = [np.nan] + list(similarities)
代码说明
features.iloc[:-1]取除最后一行外的所有特征行,features.iloc[1:]取除第一行外的所有特征行,两者一一对应就是连续的行对。- 使用
cosine_similarity时,结果矩阵的对角线元素恰好是每对连续行的相似度值;手动计算则直接对每对向量执行余弦公式。 - 最终在原DataFrame新增列,第一行因没有前一行,用
NaN填充。
内容的提问来源于stack exchange,提问作者Brie MerryWeather
相关产品推荐
相关产品推荐

