在没有循环的情况下按行计算 pandas 中的余弦相似度
Posted
技术标签:
【中文标题】在没有循环的情况下按行计算 pandas 中的余弦相似度【英文标题】:row-wise calculation of cosine similarity in pandas without looping 【发布时间】:2020-10-02 00:20:25 【问题描述】:我有一个包含很多行的 pandas 数据框 df。对于每一行,我想计算行的列 A(第一个向量)和行的列 B(第二个向量)之间的余弦相似度。最后,我的目标是为每一行获得一个具有一个余弦相似度值的向量。我找到了一个解决方案,但在我看来,如果没有这个循环,它可以做得更快。有人可以给我一些关于这段代码的反馈吗? 非常感谢!
for row in np.unique(df.index):
cos_sim[row]=scipy.spatial.distance.cosine(df[df.index==row][columnsA],
df[df.index==row][columnsB])
df['cos_sim']=cos_sim
这里有一些示例数据:
df = pd.DataFrame('featureA1': [2, 4, 1, 4],
'featureA2': [2, 4, 1, 4],
'featureB1': [10, 2, 1, 8],
'featureB2': [10, 2, 1, 8],
index=['Pit', 'Mat', 'Tim', 'Sam'])
columnsA=['featureA1', 'featureA2']
columnsB=['featureB1', 'featureB2']
这是我想要的输出(Pit、Mat、Tim 和 Sam 的余弦相似度):
cos_sim=[1, 1, 1, 1]
我已经通过我的方法收到了这个输出,但我确信从性能角度来看代码可以改进
【问题讨论】:
欢迎来到 SO。请提供示例数据和所需的输出:) 感谢@Chris,提供此提示。我添加了一些示例数据。 【参考方案1】:你可以改进的几件事:)
-
看看
DataFrame.apply
函数。 pandas 已经为您提供了“幕后”循环。
df['cos_sim'] = df.apply(lambda _df: scipy.spatial.distance.cosine(_df[columnsA], _df[columnsB])
或类似的东西应该更高效
-
也可以看看
DataFrame.loc
df[df.index==row][columnsA]
和
df.loc[row,columnsA]
应该是等价的
-
如果您确实必须遍历数据帧(由于性能损失并且更难阅读和理解,应该再次避免),pandas 为您提供了行(和 id)的生成器
for index, row in df.iterrows():
scipy.spatial.distance.cosine(row[columnsA], row[columnsB])
-
最后,如上所述,为了在 *** 上获得更好的答案,请始终提供问题可重现的具体示例。否则,很难正确解释问题并测试解决方案。
【讨论】:
哇,@maow,非常感谢!!这对问题本身和我的一般编码技能都有很大帮助!多么愉快的第一次 *** 体验 :)【参考方案2】:相当老的帖子,但我正在回复未来的读者。我为所有那些按行的相似性/距离计算创建了https://github.com/ma7555/evalify
(免责声明:我是包的所有者)
【讨论】:
以上是关于在没有循环的情况下按行计算 pandas 中的余弦相似度的主要内容,如果未能解决你的问题,请参考以下文章
Python pandas - 在缺少日期的情况下按组有效地将函数应用于滚动窗口
Python:在 Pandas 中计算两列之间的 tf-idf 余弦相似度时出现 MemoryError