首页 > 解决方案 > 不同长度的两个数据帧的列之间的余弦相似度?

问题描述

我在 df1 中有文本列,在 df2 中有文本列。df2 的长度与 df1 的长度不同。我想计算 df1[text] 中每个条目与 df2[text] 中每个条目的余弦相似度,并为每个匹配项打分。

样本输入

df1                           
mahesh                 
suresh


df2                                                                                  
surendra    
mahesh    
shrivatsa    
suresh    
maheshwari

样本输出

mahesh    surendra       30
mahesh    mahesh         100
mahesh    shrivatsa      20
mahesh    suresh         60
mahesh    maheshwari     80
suresh    surendra       70
suresh    mahesh         60
suresh    shrivatsa      40
suresh    suresh         100
suresh    maheshwari     30

当我尝试使用 tf-idf 方法匹配这两列的相似性时,我遇到了问题(得到关键错误),因为这些列的长度不同。有没有其他方法可以解决这个问题......任何帮助都会非常感激。我进行了很多搜索,发现几乎在所有情况下,人们都将第一个文档与同一语料库中的其余文档进行比较。这就像将 corpus 1 的每个文档与 corpus2 上的每个文档进行比较。

标签: pythonpandasdataframecosine-similarityname-matching

解决方案


有许多不同的字符串距离度量。我不确定如何在这种情况下使用余弦相似度,但我建议查看一个strsim库。

我会给你一个例子,说明我将如何使用Jaro-Winkler最适合短字符串的度量来解决这个问题。

另外,我将尝试使用cosine similarity该库文档中的示例。

这可能是完全错误的,但应该让您大致了解如何从两列不同长度的笛卡尔积制作数据帧,以及如何将strsim的算法应用于存储在pd.DataFrame


资料准备

import pandas as pd

from similarity.jarowinkler import JaroWinkler
from similarity.cosine import Cosine


df1 = pd.DataFrame({
    "name": ["mahesh", "suresh"]
})

df2 = pd.DataFrame({
    "name": ["mahesh", "surendra", "shrivatsa", "suresh", "maheshwari"]
})

df = pd.MultiIndex.from_product(
    [df1["name"], df2["name"]], names=["col1", "col2"]
).to_frame(index=False)

返回:

     col1        col2
0  mahesh      mahesh
1  mahesh    surendra
2  mahesh   shrivatsa
3  mahesh      suresh
4  mahesh  maheshwari
5  suresh      mahesh
6  suresh    surendra
7  suresh   shrivatsa
8  suresh      suresh
9  suresh  maheshwari

雅罗-温克勒

jarowinkler = JaroWinkler()
df["jarowinkler_sim"] = [jarowinkler.similarity(i,j) for i,j in zip(df["col1"],df["col2"])]

返回:

    col1    col2        jarowinkler_sim
0   mahesh  mahesh      1.0
1   mahesh  surendra    0.4305555555555555
2   mahesh  shrivatsa   0.5185185185185185
3   mahesh  suresh      0.6666666666666666
4   mahesh  maheshwari  0.9466666666666667
5   suresh  mahesh      0.6666666666666666
6   suresh  surendra    0.8333333333333334
7   suresh  shrivatsa   0.611111111111111
8   suresh  suresh      1.0
9   suresh  maheshwari  0.48888888888888893


余弦相似度

cosine = Cosine(2)
df["p0"] = df["col1"].apply(lambda s: cosine.get_profile(s)) 
df["p1"] = df["col2"].apply(lambda s: cosine.get_profile(s)) 
df["cosine_sim"] = [cosine.similarity_profiles(p0,p1) for p0,p1 in zip(df["p0"],df["p1"])]

df.drop(["p0", "p1"], axis=1)

返回:

    col1    col2        cosine_sim
0   mahesh  mahesh      0.9999999999999998
1   mahesh  surendra    0.0
2   mahesh  shrivatsa   0.15811388300841897
3   mahesh  suresh      0.3999999999999999
4   mahesh  maheshwari  0.7453559924999299
5   suresh  mahesh      0.3999999999999999
6   suresh  surendra    0.5070925528371099
7   suresh  shrivatsa   0.15811388300841897
8   suresh  suresh      0.9999999999999998
9   suresh  maheshwari  0.29814239699997197


推荐阅读